4 * (C) Copyright 1989-1995
13 * Extensions: P. Felber
23 * The module lkmain.c contains the functions which
24 * (1) input the linker options, parameters, and specifications
25 * (2) perform a two pass link
26 * (3) produce the appropriate linked data output and/or
27 * link map file and/or relocated listing files.
29 * lkmain.c contains the following functions:
30 * FILE * afile(fn,ft,wf)
35 * VOID main(argc,argv)
42 * lkmain.c contains the following local variables:
43 * char * usetext[] array of pointers to the
44 * command option tect lines
48 /*)Function VOID main(argc,argv)
50 * int argc number of command line arguments + 1
51 * char * argv[] array of pointers to the command line
54 * The function main() evaluates the command line arguments to
55 * determine if the linker parameters are to input through 'stdin'
56 * or read from a command file. The functiond getline() and parse()
57 * are to input and evaluate the linker parameters. The linking process
58 * proceeds by making the first pass through each .rel file in the order
59 * presented to the linker. At the end of the first pass the setbase(),
60 * lnkarea(), setgbl(), and symdef() functions are called to evaluate
61 * the base address terms, link all areas, define global variables,
62 * and look for undefined symbols. Following these routines a linker
63 * map file may be produced and the linker output files may be opened.
64 * The second pass through the .rel files will output the linked data
65 * in one of the four supported formats.
68 * char * p pointer to an argument string
69 * int c character from argument string
74 * lfile *cfp The pointer *cfp points to the
75 * current lfile structure
76 * char ctype[] array of character types, one per
78 * lfile *filep The pointer *filep points to the
79 * beginning of a linked list of
81 * head *hp Pointer to the current
83 * char ib[NINPUT] .rel file text line
84 * char *ip pointer into the .rel file
85 * lfile *linkp pointer to first lfile structure
86 * containing an input .rel file
88 * int lkerr error flag
89 * int mflag Map output flag
90 * int oflag Output file type flag
91 * FILE *ofp Output file handle
93 * FILE *ofph Output file handle
94 * for high byte format
95 * FILE *ofpl Output file handle
97 * int pass linker pass number
98 * int pflag print linker command file flag
99 * int radix current number conversion radix
100 * FILE *sfp The file handle sfp points to the
101 * currently open file
102 * lfile *startp asmlnk startup file structure
103 * FILE * stdin c_library
104 * FILE * stdout c_library
107 * FILE * afile() lkmain.c
108 * int fclose() c_library
109 * int fprintf() c_library
110 * int getline() lklex.c
111 * VOID library() lklibr.c
112 * VOID link() lkmain.c
113 * VOID lkexit() lkmain.c
114 * VOID lnkarea() lkarea.c
115 * VOID map() lkmain.c
117 * int parse() lkmain.c
118 * VOID reloc() lkreloc.c
119 * VOID search() lklibr.c
120 * VOID setbas() lkmain.c
121 * VOID setgbl() lkmain.c
122 * VOID symdef() lksym.c
123 * VOID usage() lkmain.c
126 * Completion of main() completes the linking process
127 * and may produce a map file (.map) and/or a linked
128 * data files (.ihx or .s19) and/or one or more
129 * relocated listing files (.rst).
136 char *default_basep[] = {
142 char *default_globlp[] = {
143 /* DMA transfer must start at multiples of 0x100 */
146 ".refresh_OAM=0xFF80",
167 for(i = 0; default_basep[i] != NULL; i++) {
169 basep = (struct base *)new(sizeof(struct base));
172 bsp->b_base = (struct base *)new(sizeof(struct base));
175 bsp->b_strp = default_basep[i];
177 for(i = 0; default_globlp[i] != NULL; i++) {
179 globlp = (struct globl *)new(sizeof(struct globl));
182 gsp->g_globl = (struct globl *)new(sizeof(struct globl));
185 gsp->g_strp = default_globlp[i];
189 fprintf(stdout, "\n");
192 startp = (struct lfile *) new (sizeof (struct lfile));
195 for (i=1; i<argc; ++i) {
198 while (ctype[c = *(++p)] & LETTER) {
203 startp->f_type = F_STD;
208 startp->f_type = F_LNK;
228 startp->f_type = F_CMD;
229 startp->f_idp = (char *)&argv[i+1];
235 if (startp->f_type == F_LNK) {
240 if (startp->f_type == NULL)
242 if (startp->f_type == F_LNK && startp->f_idp == NULL)
245 if (startp->f_type == F_CMD && startp->f_idp == NULL)
256 if (pflag && sfp != stdin)
257 fprintf(stdout, "%s\n", ip);
258 if (*ip == NULL || parse())
266 if (linkp->f_flp == NULL)
271 for(i = 1; i < nb_rom_banks; i++) {
272 bsp->b_base = (struct base *)new(sizeof(struct base));
274 bsp->b_strp = (char *)malloc(18);
275 sprintf(bsp->b_strp, "_CODE_%d=0x4000", i);
277 for(i = 0; i < nb_ram_banks; i++) {
278 bsp->b_base = (struct base *)new(sizeof(struct base));
280 bsp->b_strp = (char *)malloc(18);
281 sprintf(bsp->b_strp, "_BSS_%d=0xA000", i);
286 for (pass=0; pass<2; ++pass) {
290 filep = linkp->f_flp;
303 * Search libraries for global symbols
307 * Set area base addresses.
311 * Link all area addresses.
315 * Process global definitions.
319 * Check for undefined globals.
336 ofp = afile(linkp->f_idp, "ihx", 1);
338 ofp = afile(linkp->f_idp, "IHX", 1);
346 ofp = afile(linkp->f_idp, "s19", 1);
348 ofp = afile(linkp->f_idp, "S19", 1);
357 ofp = afile(linkp->f_idp, "", 1);
366 * Link in library files
375 /*)Function VOID lkexit(i)
379 * The function lkexit() explicitly closes all open
380 * files and then terminates the program.
386 * FILE * mfp file handle for .map
387 * FILE * ofp file handle for .ihx/.s19
388 * FILE * rfp file hanlde for .rst
389 * FILE * sfp file handle for .rel
390 * FILE * tfp file handle for .lst
393 * int fclose() c_library
394 * VOID exit() c_library
397 * All files closed. Program terminates.
404 if (mfp != NULL) fclose(mfp);
405 if (ofp != NULL) fclose(ofp);
406 if (rfp != NULL) fclose(rfp);
407 if (sfp != NULL) fclose(sfp);
408 if (tfp != NULL) fclose(tfp);
414 * The function link() evaluates the directives for each line of
415 * text read from the .rel file(s). The valid directives processed
417 * X, D, Q, H, M, A, S, T, R, and P.
420 * int c first non blank character of a line
423 * head *headp The pointer to the first
424 * head structure of a linked list
425 * head *hp Pointer to the current
427 * int pass linker pass number
428 * int radix current number conversion radix
431 * char endline() lklex.c
432 * VOID module() lkhead.c
433 * VOID newarea() lkarea.c
434 * VOID newhead() lkhead.c
435 * sym * newsym() lksym.c
436 * VOID reloc() lkreloc.c
439 * Head, area, and symbol structures are created and
440 * the radix is set as the .rel file(s) are read.
448 if ((c=endline()) == 0) { return; }
486 if (sdp.s_area == NULL) {
488 sdp.s_areax = areap->a_axp;
509 if (c == 'X' || c == 'D' || c == 'Q') {
510 if ((c = get()) == 'H') {
519 /*)Function VOID map()
521 * The function map() opens the output map file and calls the various
523 * (1) output the variables in each area,
524 * (2) list the files processed with module names,
525 * (3) list the libraries file processed,
526 * (4) list base address definitions,
527 * (5) list global variable definitions, and
528 * (6) list any undefined variables.
532 * head * hdp pointer to head structure
533 * lbfile *lbfh pointer to library file structure
536 * area *ap Pointer to the current
538 * area *areap The pointer to the first
539 * area structure of a linked list
540 * base *basep The pointer to the first
542 * base *bsp Pointer to the current
544 * lfile *filep The pointer *filep points to the
545 * beginning of a linked list of
547 * globl *globlp The pointer to the first
549 * globl *gsp Pointer to the current
551 * head *headp The pointer to the first
552 * head structure of a linked list
553 * lbfile *lbfhead The pointer to the first
554 * lbfile structure of a linked list
555 * lfile *linkp pointer to first lfile structure
556 * containing an input REL file
558 * int lop current line number on page
559 * FILE *mfp Map output file handle
560 * int page current page number
563 * FILE * afile() lkmain.c
564 * int fprintf() c_library
565 * VOID lkexit() lkmain.c
566 * VOID lstarea() lklist.c
567 * VOID newpag() lklist.c
568 * VOID symdef() lksym.c
571 * The map file is created.
579 register struct head *hdp;
580 register struct lbfile *lbfh;
586 mfp = afile(linkp->f_idp, "map", 1);
588 mfp = afile(linkp->f_idp, "MAP", 1);
595 * Output Map Area Lists
608 fprintf(mfp, "\nFiles Linked [ module(s) ]\n\n");
611 filep = linkp->f_flp;
616 fprintf(mfp, "%-16s", filep->f_idp);
618 while ((hdp != NULL) && (hdp->h_lfile == filep)) {
620 fprintf(mfp, ", %8.8s", hdp->m_id);
623 fprintf(mfp, ",\n%20s%8.8s", "", hdp->m_id);
625 fprintf(mfp, " [ %8.8s", hdp->m_id);
634 filep = filep->f_flp;
637 * List Linked Libraries
639 if (lbfhead != NULL) {
641 "\nLibraries Linked [ object file ]\n\n");
642 for (lbfh=lbfhead; lbfh; lbfh=lbfh->next) {
643 fprintf(mfp, "%-32s [ %16.16s ]\n",
644 lbfh->libspc, lbfh->relfil);
649 * List Base Address Definitions
653 fprintf(mfp, "\nUser Base Address Definitions\n\n");
656 fprintf(mfp, "%s\n", bsp->b_strp);
661 * List Global Definitions
665 fprintf(mfp, "\nUser Global Definitions\n\n");
668 fprintf(mfp, "%s\n", gsp->g_strp);
672 fprintf(mfp, "\n\f");
679 register struct head *hdp;
680 register struct lbfile *lbfh;
686 mfp = afile(linkp->f_idp, "map", 1);
688 mfp = afile(linkp->f_idp, "MAP", 1);
695 *Output Map Area Lists
709 filep = linkp->f_flp;
714 fprintf( mfp, "MODULES\n");
717 fprintf(mfp, "\tFILE %s\n", filep->f_idp);
718 while ((hdp != NULL) && (hdp->h_lfile == filep)) {
719 if (strlen(hdp->m_id)>0)
720 fprintf(mfp, "\t\tNAME %s\n", hdp->m_id);
723 filep = filep->f_flp;
726 * List Linked Libraries
728 if (lbfhead != NULL) {
729 fprintf(mfp, "LIBRARIES\n");
730 for (lbfh=lbfhead; lbfh; lbfh=lbfh->next) {
731 fprintf(mfp, "\tLIBRARY %s\n"
733 lbfh->libspc, lbfh->relfil);
737 * List Base Address Definitions
740 fprintf(mfp, "USERBASEDEF\n");
743 fprintf(mfp, "\t%s\n", bsp->b_strp);
748 * List Global Definitions
751 fprintf(mfp, "USERGLOBALDEF\n");
754 fprintf(mfp, "\t%s\n", gsp->g_strp);
772 register struct head *hdp;
773 register struct lbfile *lbfh;
778 mfp = afile(linkp->f_idp, "sym", 1);
782 fprintf( mfp, "; no$gmb format .sym file\n"
783 "; Generated automagically by ASxxxx linker %s (SDK " SDK_VERSION_STRING ")\n"
786 * Output sym Area Lists
802 /*)Function int parse()
804 * The function parse() evaluates all command line or file input
805 * linker directives and updates the appropriate variables.
808 * int c character value
809 * char fid[] file id string
812 * char ctype[] array of character types, one per
814 * lfile *lfp pointer to current lfile structure
815 * being processed by parse()
816 * lfile *linkp pointer to first lfile structure
817 * containing an input REL file
819 * int mflag Map output flag
820 * int oflag Output file type flag
821 * int pflag print linker command file flag
822 * FILE * stderr c_library
823 * int uflag Relocated listing flag
824 * int xflag Map file radix type flag
827 * VOID addlib() lklibr.c
828 * VOID addpath() lklibr.c
829 * VOID bassav() lkmain.c
830 * int fprintf() c_library
831 * VOID gblsav() lkmain.c
832 * VOID getfid() lklex.c
833 * char getnb() lklex.c
834 * VOID lkexit() lkmain.c
835 * char * strcpy() c_library
836 * int strlen() c_library
839 * Various linker flags are updated and the linked
840 * structure lfile is created.
849 while ((c = getnb()) != 0) {
851 while (ctype[c=get()] & LETTER) {
867 if(c == 'O' || c == 'o')
868 nb_rom_banks = expr(0);
869 else if(c == 'A' || c == 'a')
870 nb_ram_banks = expr(0);
871 else if(c == 'T' || c == 't')
873 else if(c == 'N' || c == 'n') {
875 if(getnb() != '=' || getnb() != '"') {
876 fprintf(stderr, "Syntax error in -YN=\"name\" flag\n");
879 while((c = get()) != '"' && i < 16) {
887 } else if(c == 'P' || c == 'p') {
892 patches = (patch *)malloc(sizeof(patch));
894 patches->addr = expr(0);
896 fprintf(stderr, "Syntax error in -YHaddr=val flag\n");
899 patches->value = expr(0);
901 fprintf(stderr, "Invalid option\n");
977 fprintf(stderr, "Invalid option\n");
982 if (ctype[c] != ILL) {
984 linkp = (struct lfile *)
985 new (sizeof (struct lfile));
988 lfp->f_flp = (struct lfile *)
989 new (sizeof (struct lfile));
993 lfp->f_idp = (char *) new (strlen(fid)+1);
994 strcpy(lfp->f_idp, fid);
997 fprintf(stderr, "Invalid input");
1004 /*)Function VOID bassav()
1006 * The function bassav() creates a linked structure containing
1007 * the base address strings input to the linker.
1013 * base *basep The pointer to the first
1015 * base *bsp Pointer to the current
1017 * char *ip pointer into the REL file
1021 * char getnb() lklex.c
1022 * VOID * new() lksym.c
1023 * int strlen() c_library
1024 * char * strcpy() c_library
1025 * VOID unget() lklex.c
1028 * The basep structure is created.
1034 if (basep == NULL) {
1035 basep = (struct base *)
1036 new (sizeof (struct base));
1039 bsp->b_base = (struct base *)
1040 new (sizeof (struct base));
1044 bsp->b_strp = (char *) new (strlen(ip)+1);
1045 strcpy(bsp->b_strp, ip);
1048 /*)Function VOID setbas()
1050 * The function setbas() scans the base address lines in hte
1051 * basep structure, evaluates the arguments, and sets beginning
1052 * address of the specified areas.
1055 * int v expression value
1056 * char id[] base id string
1059 * area *ap Pointer to the current
1061 * area *areap The pointer to the first
1062 * area structure of a linked list
1063 * base *basep The pointer to the first
1065 * base *bsp Pointer to the current
1067 * char *ip pointer into the REL file
1069 * int lkerr error flag
1072 * addr_t expr() lkeval.c
1073 * int fprintf() c_library
1074 * VOID getid() lklex.c
1075 * char getnb() lklex.c
1076 * int symeq() lksym.c
1079 * The base address of an area is set.
1092 if (getnb() == '=') {
1094 for (ap = areap; ap != NULL; ap = ap->a_ap) {
1095 if (symeq(id, ap->a_id))
1101 "No definition of area %s\n", id);
1108 fprintf(stderr, "No '=' in base expression");
1115 /*)Function VOID gblsav()
1117 * The function gblsav() creates a linked structure containing
1118 * the global variable strings input to the linker.
1124 * globl *globlp The pointer to the first
1126 * globl *gsp Pointer to the current
1128 * char *ip pointer into the REL file
1130 * int lkerr error flag
1133 * char getnb() lklex.c
1134 * VOID * new() lksym.c
1135 * int strlen() c_library
1136 * char * strcpy() c_library
1137 * VOID unget() lklex.c
1140 * The globlp structure is created.
1146 if (globlp == NULL) {
1147 globlp = (struct globl *)
1148 new (sizeof (struct globl));
1151 gsp->g_globl = (struct globl *)
1152 new (sizeof (struct globl));
1156 gsp->g_strp = (char *) new (strlen(ip)+1);
1157 strcpy(gsp->g_strp, ip);
1160 /*)Function VOID setgbl()
1162 * The function setgbl() scans the global variable lines in hte
1163 * globlp structure, evaluates the arguments, and sets a variable
1167 * int v expression value
1168 * char id[] base id string
1169 * sym * sp pointer to a symbol structure
1172 * char *ip pointer into the REL file
1174 * globl *globlp The pointer to the first
1176 * globl *gsp Pointer to the current
1178 * FILE * stderr c_library
1179 * int lkerr error flag
1182 * addr_t expr() lkeval.c
1183 * int fprintf() c_library
1184 * VOID getid() lklex.c
1185 * char getnb() lklex.c
1186 * sym * lkpsym() lksym.c
1189 * The value of a variable is set.
1196 register struct sym *sp;
1203 if (getnb() == '=') {
1209 "No definition of symbol %s\n", id);
1214 if (sp->s_flag & S_DEF) {
1216 "Redefinition of symbol %s\n", id);
1222 sp->s_type |= S_DEF;
1225 fprintf(stderr, "No '=' in global expression");
1232 /*)Function FILE * afile(fn,, ft, wf)
1234 * char * fn file specification string
1235 * char * ft file type string
1236 * int wf read(0)/write(1) flag
1238 * The function afile() opens a file for reading or writing.
1239 * (1) If the file type specification string ft
1240 * is not NULL then a file specification is
1241 * constructed with the file path\name in fn
1242 * and the extension in ft.
1243 * (2) If the file type specification string ft
1244 * is NULL then the file specification is
1245 * constructed from fn. If fn does not have
1246 * a file type then the default .rel file
1247 * type is appended to the file specification.
1249 * afile() returns a file handle for the opened file or aborts
1250 * the assembler on an open error.
1253 * int c character value
1254 * char fb[] constructed file specification string
1255 * FILE * fp filehandle for opened file
1256 * char * p1 pointer to filespec string fn
1257 * char * p2 pointer to filespec string fb
1258 * char * p3 pointer to filetype string ft
1261 * int lkerr error flag
1264 * FILE * fopen() c_library
1265 * int fprintf() c_library
1268 * File is opened for read or write.
1276 register char *p1, *p2, *p3;
1284 while ((c = *p1++) != 0 && c != FSEPX) {
1285 if (p2 < &fb[FILSPC-4])
1300 while ((c = *p3++) != 0) {
1301 if (p2 < &fb[FILSPC-1])
1306 if ((fp = fopen(fb, wf?(binary?"wb":"w"):(binary?"rb":"r"))) == NULL) {
1308 if ((fp = fopen(fb, wf?"w":"r")) == NULL) {
1310 fprintf(stderr, "%s: cannot %s.\n", fb, wf?"create":"open");
1318 "Distributed with SDK " SDK_VERSION_STRING ", built on " __DATE__ " " __TIME__,
1319 "Compile options: SDK Target " TARGET_STRING
1327 " -- [Commands] Non-interactive command line input",
1329 " -c Command line input",
1330 " -f file[LNK] File input",
1331 " -p Prompt and echo of file[LNK] to stdout (default)",
1332 " -n No echo of file[LNK] to stdout",
1334 "Usage: [-Options] outfile file [file ...]",
1336 "Usage: [-Options] file [file ...]",
1339 " -k Library path specification, one per -k",
1340 " -l Library file specification, one per -l",
1342 " -b area base address = expression",
1343 " -g global symbol = expression",
1345 " -yo Number of rom banks (default: 2)",
1346 " -ya Number of ram banks (default: 0)",
1347 " -yt MBC type (default: no MBC)",
1348 " -yn Name of program (default: name of output file)",
1349 " -yp# Patch one byte in the output GB file (# is: addr=byte)",
1350 #endif /* GAMEBOY */
1352 " -m Map output generated as file[MAP]",
1354 " -j no$gmb symbol file generated as file[SYM]",
1356 " -x Hexidecimal (default)",
1360 " -i Intel Hex as file[IHX]",
1361 " -s Motorola S19 as file[S19]",
1364 " -z Gamegear image as file[GG]",
1366 " -z Gameboy image as file[GB]",
1367 #endif /* GAMEGEAR */
1370 " -u Update listing file(s) with link data as file(s)[.RST]",
1372 " -e or null line terminates input",
1377 /*)Function VOID usage()
1379 * The function usage() outputs to the stderr device the
1380 * assembler name and version and a list of valid assembler options.
1383 * char ** dp pointer to an array of
1384 * text string pointers.
1387 * FILE * stderr c_library
1390 * int fprintf() c_library
1401 fprintf(stderr, "\nASxxxx Linker %s\n\n", VERSION);
1402 for (dp = usetxt; *dp; dp++)
1403 fprintf(stderr, "%s\n", *dp);