3 * (C) Copyright 1989-1995
12 * Extensions: P. Felber
21 #ifndef SDK_VERSION_STRING
22 #define SDK_VERSION_STRING "3.0.0"
25 #define TARGET_STRING "gbz80"
30 * The module lkmain.c contains the functions which
31 * (1) input the linker options, parameters, and specifications
32 * (2) perform a two pass link
33 * (3) produce the appropriate linked data output and/or
34 * link map file and/or relocated listing files.
36 * lkmain.c contains the following functions:
37 * FILE * afile(fn,ft,wf)
42 * VOID main(argc,argv)
49 * lkmain.c contains the following local variables:
50 * char * usetext[] array of pointers to the
51 * command option tect lines
55 /*)Function VOID main(argc,argv)
57 * int argc number of command line arguments + 1
58 * char * argv[] array of pointers to the command line
61 * The function main() evaluates the command line arguments to
62 * determine if the linker parameters are to input through 'stdin'
63 * or read from a command file. The functiond getline() and parse()
64 * are to input and evaluate the linker parameters. The linking process
65 * proceeds by making the first pass through each .rel file in the order
66 * presented to the linker. At the end of the first pass the setbase(),
67 * lnkarea(), setgbl(), and symdef() functions are called to evaluate
68 * the base address terms, link all areas, define global variables,
69 * and look for undefined symbols. Following these routines a linker
70 * map file may be produced and the linker output files may be opened.
71 * The second pass through the .rel files will output the linked data
72 * in one of the four supported formats.
75 * char * p pointer to an argument string
76 * int c character from argument string
81 * lfile *cfp The pointer *cfp points to the
82 * current lfile structure
83 * char ctype[] array of character types, one per
85 * lfile *filep The pointer *filep points to the
86 * beginning of a linked list of
88 * head *hp Pointer to the current
90 * char ib[NINPUT] .rel file text line
91 * char *ip pointer into the .rel file
92 * lfile *linkp pointer to first lfile structure
93 * containing an input .rel file
95 * int lkerr error flag
96 * int mflag Map output flag
97 * int oflag Output file type flag
98 * FILE *ofp Output file handle
100 * FILE *ofph Output file handle
101 * for high byte format
102 * FILE *ofpl Output file handle
103 * for low byte format
104 * int pass linker pass number
105 * int pflag print linker command file flag
106 * int radix current number conversion radix
107 * FILE *sfp The file handle sfp points to the
108 * currently open file
109 * lfile *startp asmlnk startup file structure
110 * FILE * stdin c_library
111 * FILE * stdout c_library
114 * FILE * afile() lkmain.c
115 * int fclose() c_library
116 * int fprintf() c_library
117 * int getline() lklex.c
118 * VOID library() lklibr.c
119 * VOID link() lkmain.c
120 * VOID lkexit() lkmain.c
121 * VOID lnkarea() lkarea.c
122 * VOID map() lkmain.c
124 * int parse() lkmain.c
125 * VOID reloc() lkreloc.c
126 * VOID search() lklibr.c
127 * VOID setbas() lkmain.c
128 * VOID setgbl() lkmain.c
129 * VOID symdef() lksym.c
130 * VOID usage() lkmain.c
133 * Completion of main() completes the linking process
134 * and may produce a map file (.map) and/or a linked
135 * data files (.ihx or .s19) and/or one or more
136 * relocated listing files (.rst).
143 char *default_basep[] = {
149 char *default_globlp[] = {
150 /* DMA transfer must start at multiples of 0x100 */
153 ".refresh_OAM=0xFF80",
174 for(i = 0; default_basep[i] != NULL; i++) {
176 basep = (struct base *)new(sizeof(struct base));
179 bsp->b_base = (struct base *)new(sizeof(struct base));
182 bsp->b_strp = default_basep[i];
184 for(i = 0; default_globlp[i] != NULL; i++) {
186 globlp = (struct globl *)new(sizeof(struct globl));
189 gsp->g_globl = (struct globl *)new(sizeof(struct globl));
192 gsp->g_strp = default_globlp[i];
196 fprintf(stdout, "\n");
199 startp = (struct lfile *) new (sizeof (struct lfile));
202 for (i=1; i<argc; ++i) {
205 while (ctype[c = *(++p)] & LETTER) {
210 startp->f_type = F_STD;
215 startp->f_type = F_LNK;
235 startp->f_type = F_CMD;
236 startp->f_idp = (char *)&argv[i+1];
242 if (startp->f_type == F_LNK) {
247 if (startp->f_type == F_INV)
249 if (startp->f_type == F_LNK && startp->f_idp == NULL)
252 if (startp->f_type == F_CMD && startp->f_idp == NULL)
263 if (pflag && sfp != stdin)
264 fprintf(stdout, "%s\n", ip);
265 if (*ip == '\0' || parse())
273 if (linkp->f_flp == NULL)
278 for(i = 1; i < nb_rom_banks; i++) {
279 bsp->b_base = (struct base *)new(sizeof(struct base));
281 bsp->b_strp = (char *)malloc(18);
282 sprintf(bsp->b_strp, "_CODE_%d=0x4000", i);
284 for(i = 0; i < nb_ram_banks; i++) {
285 bsp->b_base = (struct base *)new(sizeof(struct base));
287 bsp->b_strp = (char *)malloc(18);
288 sprintf(bsp->b_strp, "_DATA_%d=0xA000", i);
293 for (pass=0; pass<2; ++pass) {
297 filep = linkp->f_flp;
310 * Search libraries for global symbols
314 * Set area base addresses.
318 * Link all area addresses.
322 * Process global definitions.
326 * Check for undefined globals.
343 ofp = afile(linkp->f_idp, "ihx", 1);
345 ofp = afile(linkp->f_idp, "IHX", 1);
353 ofp = afile(linkp->f_idp, "s19", 1);
355 ofp = afile(linkp->f_idp, "S19", 1);
364 ofp = afile(linkp->f_idp, "", 1);
373 * Link in library files
381 /* Never get here. */
385 /*)Function VOID lkexit(i)
389 * The function lkexit() explicitly closes all open
390 * files and then terminates the program.
396 * FILE * mfp file handle for .map
397 * FILE * ofp file handle for .ihx/.s19
398 * FILE * rfp file hanlde for .rst
399 * FILE * sfp file handle for .rel
400 * FILE * tfp file handle for .lst
403 * int fclose() c_library
404 * VOID exit() c_library
407 * All files closed. Program terminates.
414 if (mfp != NULL) fclose(mfp);
415 if (ofp != NULL) fclose(ofp);
416 if (rfp != NULL) fclose(rfp);
417 if (sfp != NULL) fclose(sfp);
418 if (tfp != NULL) fclose(tfp);
424 * The function link() evaluates the directives for each line of
425 * text read from the .rel file(s). The valid directives processed
427 * X, D, Q, H, M, A, S, T, R, and P.
430 * int c first non blank character of a line
433 * head *headp The pointer to the first
434 * head structure of a linked list
435 * head *hp Pointer to the current
437 * int pass linker pass number
438 * int radix current number conversion radix
441 * char endline() lklex.c
442 * VOID module() lkhead.c
443 * VOID newarea() lkarea.c
444 * VOID newhead() lkhead.c
445 * sym * newsym() lksym.c
446 * VOID reloc() lkreloc.c
449 * Head, area, and symbol structures are created and
450 * the radix is set as the .rel file(s) are read.
458 if ((c=endline()) == 0) { return; }
496 if (sdp.s_area == NULL) {
498 sdp.s_areax = areap->a_axp;
519 if (c == 'X' || c == 'D' || c == 'Q') {
520 if ((c = get()) == 'H') {
529 /*)Function VOID map()
531 * The function map() opens the output map file and calls the various
533 * (1) output the variables in each area,
534 * (2) list the files processed with module names,
535 * (3) list the libraries file processed,
536 * (4) list base address definitions,
537 * (5) list global variable definitions, and
538 * (6) list any undefined variables.
542 * head * hdp pointer to head structure
543 * lbfile *lbfh pointer to library file structure
546 * area *ap Pointer to the current
548 * area *areap The pointer to the first
549 * area structure of a linked list
550 * base *basep The pointer to the first
552 * base *bsp Pointer to the current
554 * lfile *filep The pointer *filep points to the
555 * beginning of a linked list of
557 * globl *globlp The pointer to the first
559 * globl *gsp Pointer to the current
561 * head *headp The pointer to the first
562 * head structure of a linked list
563 * lbfile *lbfhead The pointer to the first
564 * lbfile structure of a linked list
565 * lfile *linkp pointer to first lfile structure
566 * containing an input REL file
568 * int lop current line number on page
569 * FILE *mfp Map output file handle
570 * int page current page number
573 * FILE * afile() lkmain.c
574 * int fprintf() c_library
575 * VOID lkexit() lkmain.c
576 * VOID lstarea() lklist.c
577 * VOID newpag() lklist.c
578 * VOID symdef() lksym.c
581 * The map file is created.
589 register struct head *hdp;
590 register struct lbfile *lbfh;
596 mfp = afile(linkp->f_idp, "map", 1);
598 mfp = afile(linkp->f_idp, "MAP", 1);
605 * Output Map Area Lists
618 fprintf(mfp, "\nFiles Linked [ module(s) ]\n\n");
621 filep = linkp->f_flp;
626 fprintf(mfp, "%-16s", filep->f_idp);
628 while ((hdp != NULL) && (hdp->h_lfile == filep)) {
630 fprintf(mfp, ", %8.8s", hdp->m_id);
633 fprintf(mfp, ",\n%20s%8.8s", "", hdp->m_id);
635 fprintf(mfp, " [ %8.8s", hdp->m_id);
644 filep = filep->f_flp;
647 * List Linked Libraries
649 if (lbfhead != NULL) {
651 "\nLibraries Linked [ object file ]\n\n");
652 for (lbfh=lbfhead; lbfh; lbfh=lbfh->next) {
653 fprintf(mfp, "%-32s [ %16.16s ]\n",
654 lbfh->libspc, lbfh->relfil);
659 * List Base Address Definitions
663 fprintf(mfp, "\nUser Base Address Definitions\n\n");
666 fprintf(mfp, "%s\n", bsp->b_strp);
671 * List Global Definitions
675 fprintf(mfp, "\nUser Global Definitions\n\n");
678 fprintf(mfp, "%s\n", gsp->g_strp);
682 fprintf(mfp, "\n\f");
688 register struct head *hdp;
689 register struct lbfile *lbfh;
695 mfp = afile(linkp->f_idp, "map", 1);
697 mfp = afile(linkp->f_idp, "MAP", 1);
704 *Output Map Area Lists
718 filep = linkp->f_flp;
723 fprintf( mfp, "MODULES\n");
726 fprintf(mfp, "\tFILE %s\n", filep->f_idp);
727 while ((hdp != NULL) && (hdp->h_lfile == filep)) {
728 if (strlen(hdp->m_id)>0)
729 fprintf(mfp, "\t\tNAME %s\n", hdp->m_id);
732 filep = filep->f_flp;
735 * List Linked Libraries
737 if (lbfhead != NULL) {
738 fprintf(mfp, "LIBRARIES\n");
739 for (lbfh=lbfhead; lbfh; lbfh=lbfh->next) {
740 fprintf(mfp, "\tLIBRARY %s\n"
742 lbfh->libspc, lbfh->relfil);
746 * List Base Address Definitions
749 fprintf(mfp, "USERBASEDEF\n");
752 fprintf(mfp, "\t%s\n", bsp->b_strp);
757 * List Global Definitions
760 fprintf(mfp, "USERGLOBALDEF\n");
763 fprintf(mfp, "\t%s\n", gsp->g_strp);
779 VOID lstareatosym(struct area *xp);
786 mfp = afile(linkp->f_idp, "sym", 1);
790 fprintf( mfp, "; no$gmb format .sym file\n"
791 "; Generated automagically by ASxxxx linker %s (SDK " SDK_VERSION_STRING ")\n"
794 * Output sym Area Lists
810 /*)Function int parse()
812 * The function parse() evaluates all command line or file input
813 * linker directives and updates the appropriate variables.
816 * int c character value
817 * char fid[] file id string
820 * char ctype[] array of character types, one per
822 * lfile *lfp pointer to current lfile structure
823 * being processed by parse()
824 * lfile *linkp pointer to first lfile structure
825 * containing an input REL file
827 * int mflag Map output flag
828 * int oflag Output file type flag
829 * int pflag print linker command file flag
830 * FILE * stderr c_library
831 * int uflag Relocated listing flag
832 * int xflag Map file radix type flag
835 * VOID addlib() lklibr.c
836 * VOID addpath() lklibr.c
837 * VOID bassav() lkmain.c
838 * int fprintf() c_library
839 * VOID gblsav() lkmain.c
840 * VOID getfid() lklex.c
841 * char getnb() lklex.c
842 * VOID lkexit() lkmain.c
843 * char * strcpy() c_library
844 * int strlen() c_library
847 * Various linker flags are updated and the linked
848 * structure lfile is created.
857 while ((c = getnb()) != 0) {
859 while (ctype[c=get()] & LETTER) {
875 if(c == 'O' || c == 'o')
876 nb_rom_banks = expr(0);
877 else if(c == 'A' || c == 'a')
878 nb_ram_banks = expr(0);
879 else if(c == 'T' || c == 't')
881 else if(c == 'N' || c == 'n') {
883 if(getnb() != '=' || getnb() != '"') {
884 fprintf(stderr, "Syntax error in -YN=\"name\" flag\n");
887 while((c = get()) != '"' && i < 16) {
895 } else if(c == 'P' || c == 'p') {
898 patches = (patch *)malloc(sizeof(patch));
900 patches->addr = expr(0);
902 fprintf(stderr, "Syntax error in -YHaddr=val flag\n");
905 patches->value = expr(0);
907 fprintf(stderr, "Invalid option\n");
983 fprintf(stderr, "Invalid option\n");
988 if (ctype[c] != ILL) {
990 linkp = (struct lfile *)
991 new (sizeof (struct lfile));
994 lfp->f_flp = (struct lfile *)
995 new (sizeof (struct lfile));
999 lfp->f_idp = (char *) new (strlen(fid)+1);
1000 strcpy(lfp->f_idp, fid);
1001 lfp->f_type = F_REL;
1003 fprintf(stderr, "Invalid input");
1010 /*)Function VOID bassav()
1012 * The function bassav() creates a linked structure containing
1013 * the base address strings input to the linker.
1019 * base *basep The pointer to the first
1021 * base *bsp Pointer to the current
1023 * char *ip pointer into the REL file
1027 * char getnb() lklex.c
1028 * VOID * new() lksym.c
1029 * int strlen() c_library
1030 * char * strcpy() c_library
1031 * VOID unget() lklex.c
1034 * The basep structure is created.
1040 if (basep == NULL) {
1041 basep = (struct base *)
1042 new (sizeof (struct base));
1045 bsp->b_base = (struct base *)
1046 new (sizeof (struct base));
1050 bsp->b_strp = (char *) new (strlen(ip)+1);
1051 strcpy(bsp->b_strp, ip);
1054 /*)Function VOID setbas()
1056 * The function setbas() scans the base address lines in hte
1057 * basep structure, evaluates the arguments, and sets beginning
1058 * address of the specified areas.
1061 * int v expression value
1062 * char id[] base id string
1065 * area *ap Pointer to the current
1067 * area *areap The pointer to the first
1068 * area structure of a linked list
1069 * base *basep The pointer to the first
1071 * base *bsp Pointer to the current
1073 * char *ip pointer into the REL file
1075 * int lkerr error flag
1078 * Addr_T expr() lkeval.c
1079 * int fprintf() c_library
1080 * VOID getid() lklex.c
1081 * char getnb() lklex.c
1082 * int symeq() lksym.c
1085 * The base address of an area is set.
1098 if (getnb() == '=') {
1100 for (ap = areap; ap != NULL; ap = ap->a_ap) {
1101 if (symeq(id, ap->a_id))
1107 "No definition of area %s\n", id);
1114 fprintf(stderr, "No '=' in base expression");
1121 /*)Function VOID gblsav()
1123 * The function gblsav() creates a linked structure containing
1124 * the global variable strings input to the linker.
1130 * globl *globlp The pointer to the first
1132 * globl *gsp Pointer to the current
1134 * char *ip pointer into the REL file
1136 * int lkerr error flag
1139 * char getnb() lklex.c
1140 * VOID * new() lksym.c
1141 * int strlen() c_library
1142 * char * strcpy() c_library
1143 * VOID unget() lklex.c
1146 * The globlp structure is created.
1152 if (globlp == NULL) {
1153 globlp = (struct globl *)
1154 new (sizeof (struct globl));
1157 gsp->g_globl = (struct globl *)
1158 new (sizeof (struct globl));
1162 gsp->g_strp = (char *) new (strlen(ip)+1);
1163 strcpy(gsp->g_strp, ip);
1166 /*)Function VOID setgbl()
1168 * The function setgbl() scans the global variable lines in hte
1169 * globlp structure, evaluates the arguments, and sets a variable
1173 * int v expression value
1174 * char id[] base id string
1175 * sym * sp pointer to a symbol structure
1178 * char *ip pointer into the REL file
1180 * globl *globlp The pointer to the first
1182 * globl *gsp Pointer to the current
1184 * FILE * stderr c_library
1185 * int lkerr error flag
1188 * Addr_T expr() lkeval.c
1189 * int fprintf() c_library
1190 * VOID getid() lklex.c
1191 * char getnb() lklex.c
1192 * sym * lkpsym() lksym.c
1195 * The value of a variable is set.
1202 register struct sym *sp;
1209 if (getnb() == '=') {
1215 "No definition of symbol %s\n", id);
1220 if (sp->s_flag & S_DEF) {
1222 "Redefinition of symbol %s\n", id);
1228 sp->s_type |= S_DEF;
1231 fprintf(stderr, "No '=' in global expression");
1238 /*)Function FILE * afile(fn,, ft, wf)
1240 * char * fn file specification string
1241 * char * ft file type string
1242 * int wf read(0)/write(1) flag
1244 * The function afile() opens a file for reading or writing.
1245 * (1) If the file type specification string ft
1246 * is not NULL then a file specification is
1247 * constructed with the file path\name in fn
1248 * and the extension in ft.
1249 * (2) If the file type specification string ft
1250 * is NULL then the file specification is
1251 * constructed from fn. If fn does not have
1252 * a file type then the default .rel file
1253 * type is appended to the file specification.
1255 * afile() returns a file handle for the opened file or aborts
1256 * the assembler on an open error.
1259 * int c character value
1260 * char fb[] constructed file specification string
1261 * FILE * fp filehandle for opened file
1262 * char * p1 pointer to filespec string fn
1263 * char * p2 pointer to filespec string fb
1264 * char * p3 pointer to filetype string ft
1267 * int lkerr error flag
1270 * FILE * fopen() c_library
1271 * int fprintf() c_library
1274 * File is opened for read or write.
1282 register char *p1, *p2, *p3;
1290 while ((c = *p1++) != 0 && c != FSEPX) {
1291 if (p2 < &fb[FILSPC-4])
1306 while ((c = *p3++) != 0) {
1307 if (p2 < &fb[FILSPC-1])
1312 if ((fp = fopen(fb, wf?(binary?"wb":"w"):(binary?"rb":"r"))) == NULL) {
1314 if ((fp = fopen(fb, wf?"w":"r")) == NULL) {
1316 fprintf(stderr, "%s: cannot %s.\n", fb, wf?"create":"open");
1324 "Distributed with SDK " SDK_VERSION_STRING ", built on " __DATE__ " " __TIME__,
1325 "Compile options: SDK Target " TARGET_STRING
1333 " -- [Commands] Non-interactive command line input",
1335 " -c Command line input",
1336 " -f file[LNK] File input",
1337 " -p Prompt and echo of file[LNK] to stdout (default)",
1338 " -n No echo of file[LNK] to stdout",
1340 "Usage: [-Options] outfile file [file ...]",
1342 "Usage: [-Options] file [file ...]",
1345 " -k Library path specification, one per -k",
1346 " -l Library file specification, one per -l",
1348 " -b area base address = expression",
1349 " -g global symbol = expression",
1351 " -yo Number of rom banks (default: 2)",
1352 " -ya Number of ram banks (default: 0)",
1353 " -yt MBC type (default: no MBC)",
1354 " -yn Name of program (default: name of output file)",
1355 " -yp# Patch one byte in the output GB file (# is: addr=byte)",
1356 #endif /* GAMEBOY */
1358 " -m Map output generated as file[MAP]",
1360 " -j no$gmb symbol file generated as file[SYM]",
1362 " -x Hexidecimal (default)",
1366 " -i Intel Hex as file[IHX]",
1367 " -s Motorola S19 as file[S19]",
1370 " -z Gamegear image as file[GG]",
1372 " -z Gameboy image as file[GB]",
1373 #endif /* GAMEGEAR */
1376 " -u Update listing file(s) with link data as file(s)[.RST]",
1378 " -e or null line terminates input",
1383 /*)Function VOID usage()
1385 * The function usage() outputs to the stderr device the
1386 * assembler name and version and a list of valid assembler options.
1389 * char ** dp pointer to an array of
1390 * text string pointers.
1393 * FILE * stderr c_library
1396 * int fprintf() c_library
1407 fprintf(stderr, "\nASxxxx Linker %s\n\n", VERSION);
1408 for (dp = usetxt; *dp; dp++)
1409 fprintf(stderr, "%s\n", *dp);