Lots.
[fw/sdcc] / link / z80 / lkmain.c
1 /* lkmain.c */
2
3 /*
4  * (C) Copyright 1989-1995
5  * All Rights Reserved
6  *
7  * Alan R. Baldwin
8  * 721 Berkeley St.
9  * Kent, Ohio  44240
10  */
11
12 /*
13  * Extensions: P. Felber
14  */
15
16 #include <stdio.h>
17 #include <string.h>
18 #include <alloc.h>
19 #include "aslink.h"
20
21 /*)Module       lkmain.c
22  *
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.
28  *
29  *      lkmain.c contains the following functions:
30  *              FILE *  afile(fn,ft,wf)
31  *              VOID    bassav()
32  *              VOID    gblsav()
33  *              VOID    link()
34  *              VOID    lkexit()
35  *              VOID    main(argc,argv)
36  *              VOID    map()
37  *              int     parse()
38  *              VOID    setbas()
39  *              VOID    setgbl()
40  *              VOID    usage()
41  *
42  *      lkmain.c contains the following local variables:
43  *              char *  usetext[]       array of pointers to the
44  *                                      command option tect lines
45  *
46  */
47
48 /*)Function     VOID    main(argc,argv)
49  *
50  *              int     argc            number of command line arguments + 1
51  *              char *  argv[]          array of pointers to the command line
52  *                                      arguments
53  *
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.
66  *
67  *      local variables:
68  *              char *  p               pointer to an argument string
69  *              int     c               character from argument string
70  *              int     i               loop counter
71  *
72  *      global variables:
73  *                                      text line in ib[]
74  *              lfile   *cfp            The pointer *cfp points to the
75  *                                      current lfile structure
76  *              char    ctype[]         array of character types, one per
77  *                                      ASCII character
78  *              lfile   *filep          The pointer *filep points to the
79  *                                      beginning of a linked list of
80  *                                      lfile structures.
81  *              head    *hp             Pointer to the current
82  *                                      head structure
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
87  *                                      specification
88  *              int     lkerr           error flag
89  *              int     mflag           Map output flag
90  *              int     oflag           Output file type flag
91  *              FILE    *ofp            Output file handle
92  *                                      for word formats
93  *              FILE    *ofph           Output file handle
94  *                                      for high byte format
95  *              FILE    *ofpl           Output file handle
96  *                                      for low byte format
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
105  *
106  *      functions called:
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
116  *              VOID    new()           lksym.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
124  *
125  *      side effects:
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).
130  */
131
132 #ifdef SDK
133 int binary = 0;
134 #endif /* SDK */
135 #ifdef GAMEBOY
136 char *default_basep[] = {
137   "_CODE=0x0200",
138   "_DATA=0xC0A0",
139   NULL
140 };
141
142 char *default_globlp[] = {
143   /* DMA transfer must start at multiples of 0x100 */
144   ".OAM=0xC000",
145   ".STACK=0xE000",
146   ".refresh_OAM=0xFF80",
147
148   ".init=0x0000",
149
150   NULL
151 };
152 #endif /* GAMEBOY */
153
154 VOID
155 main(argc, argv)
156 char *argv[];
157 {
158         register char *p;
159         register c, i;
160
161 #ifdef GAMEBOY
162         nb_rom_banks = 2;
163         nb_ram_banks = 0;
164         mbc_type = 0;
165         symflag=0;
166
167         for(i = 0; default_basep[i] != NULL; i++) {
168                 if(basep == NULL) {
169                         basep = (struct base *)new(sizeof(struct base));
170                         bsp = basep;
171                 } else {
172                         bsp->b_base = (struct base *)new(sizeof(struct base));
173                         bsp = bsp->b_base;
174                 }
175                 bsp->b_strp = default_basep[i];
176         }
177         for(i = 0; default_globlp[i] != NULL; i++) {
178                 if(globlp == NULL) {
179                         globlp = (struct globl *)new(sizeof(struct globl));
180                         gsp = globlp;
181                 } else {
182                         gsp->g_globl = (struct globl *)new(sizeof(struct globl));
183                         gsp = gsp->g_globl;
184                 }
185                 gsp->g_strp = default_globlp[i];
186         }
187 #endif /* GAMEBOY */
188 #ifndef SDK
189         fprintf(stdout, "\n");
190 #endif /* SDK */
191
192         startp = (struct lfile *) new (sizeof (struct lfile));
193
194         pflag = 1;
195         for (i=1; i<argc; ++i) {
196                 p = argv[i];
197                 if (*p == '-') {
198                         while (ctype[c = *(++p)] & LETTER) {
199                                 switch(c) {
200
201                                 case 'c':
202                                 case 'C':
203                                         startp->f_type = F_STD;
204                                         break;
205
206                                 case 'f':
207                                 case 'F':
208                                         startp->f_type = F_LNK;
209                                         break;
210                                         
211                                 case 'n':
212                                 case 'N':
213                                         pflag = 0;
214                                         break;
215
216                                 case 'p':
217                                 case 'P':
218                                         pflag = 1;
219                                         break;
220
221                                 default:
222                                         usage();
223                                 }
224                         }
225
226 #ifdef SDK                      
227                         if(c == '-') {
228                                 startp->f_type = F_CMD;
229                                 startp->f_idp = (char *)&argv[i+1];
230                                 break;
231                         }
232 #endif /* SDK */
233
234                 } else {
235                         if (startp->f_type == F_LNK) {
236                                 startp->f_idp = p;
237                         }
238                 }
239         }
240         if (startp->f_type == NULL)
241                 usage();
242         if (startp->f_type == F_LNK && startp->f_idp == NULL)
243                 usage();
244 #ifdef SDK
245         if (startp->f_type == F_CMD && startp->f_idp == NULL)
246                 usage();
247 #endif /* SDK */
248
249         cfp = NULL;
250         sfp = NULL;
251         filep = startp;
252         while (1) {
253                 ip = ib;                                        
254                 if (getline() == 0)
255                         break;
256                 if (pflag && sfp != stdin)
257                         fprintf(stdout, "%s\n", ip);
258                 if (*ip == NULL || parse())
259                         break;
260         }
261         if (sfp)
262                 fclose(sfp);
263         if (linkp == NULL)
264                 usage();
265 #ifdef SDK
266         if (linkp->f_flp == NULL)
267                 usage();
268 #endif /* SDK */
269
270 #ifdef GAMEBOY
271         for(i = 1; i < nb_rom_banks; i++) {
272                 bsp->b_base = (struct base *)new(sizeof(struct base));
273                 bsp = bsp->b_base;
274                 bsp->b_strp = (char *)malloc(18);
275                 sprintf(bsp->b_strp, "_CODE_%d=0x4000", i);
276         }
277         for(i = 0; i < nb_ram_banks; i++) {
278                 bsp->b_base = (struct base *)new(sizeof(struct base));
279                 bsp = bsp->b_base;
280                 bsp->b_strp = (char *)malloc(18);
281                 sprintf(bsp->b_strp, "_BSS_%d=0xA000", i);
282         }
283 #endif /* GAMEBOY */
284
285         syminit();
286         for (pass=0; pass<2; ++pass) {
287                 cfp = NULL;
288                 sfp = NULL;
289 #ifdef SDK
290                 filep = linkp->f_flp;
291 #else /* SDK */
292                 filep = linkp;
293 #endif /* SDK */
294                 hp = NULL;
295                 radix = 10;
296
297                 while (getline()) {
298                         ip = ib;
299                         link();
300                 }
301                 if (pass == 0) {
302                         /*
303                          * Search libraries for global symbols
304                          */
305                         search();
306                         /*
307                          * Set area base addresses.
308                          */
309                         setbas();
310                         /*
311                          * Link all area addresses.
312                          */
313                         lnkarea();
314                         /*
315                          * Process global definitions.
316                          */
317                         setgbl();
318                         /*
319                          * Check for undefined globals.
320                          */
321                         symdef(stderr);
322 #ifdef SDK
323                         if (symflag) 
324                                 sym();
325 #endif
326                         /*
327                          * Output Link Map.
328                          */
329                         if (mflag)
330                                 map();
331                         /*
332                          * Open output file
333                          */
334                         if (oflag == 1) {
335 #ifdef SDK
336                                 ofp = afile(linkp->f_idp, "ihx", 1);
337 #else /* SDK */
338                                 ofp = afile(linkp->f_idp, "IHX", 1);
339 #endif /* SDK */
340                                 if (ofp == NULL) {
341                                         lkexit(1);
342                                 }
343                         } else
344                         if (oflag == 2) {
345 #ifdef SDK
346                                 ofp = afile(linkp->f_idp, "s19", 1);
347 #else /* SDK */
348                                 ofp = afile(linkp->f_idp, "S19", 1);
349 #endif /* SDK */
350                                 if (ofp == NULL) {
351                                         lkexit(1);
352                                 }
353 #ifdef SDK
354                         } else
355                         if (oflag == 3) {
356                                 binary = 1;
357                                 ofp = afile(linkp->f_idp, "", 1);
358                                 binary = 0;
359                                 if (ofp == NULL) {
360                                         lkexit(1);
361                                 }
362 #endif /* SDK */
363                         }
364                 } else {
365                         /*
366                          * Link in library files
367                          */
368                         library();
369                         reloc('E');
370                 }
371         }
372         lkexit(lkerr);
373 }
374
375 /*)Function     VOID    lkexit(i)
376  *
377  *                      int     i       exit code
378  *
379  *      The function lkexit() explicitly closes all open
380  *      files and then terminates the program.
381  *
382  *      local variables:
383  *              none
384  *
385  *      global variables:
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
391  *
392  *      functions called:
393  *              int     fclose()        c_library
394  *              VOID    exit()          c_library
395  *
396  *      side effects:
397  *              All files closed. Program terminates.
398  */
399
400 VOID 
401 lkexit(i)
402 int i;
403 {
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);
409         exit(i);
410 }
411
412 /*)Function     link()
413  *
414  *      The function link() evaluates the directives for each line of
415  *      text read from the .rel file(s).  The valid directives processed
416  *      are:
417  *              X, D, Q, H, M, A, S, T, R, and P.
418  *
419  *      local variables:
420  *              int     c               first non blank character of a line
421  *
422  *      global variables:
423  *              head    *headp          The pointer to the first
424  *                                      head structure of a linked list
425  *              head    *hp             Pointer to the current
426  *                                      head structure
427  *              int     pass            linker pass number
428  *              int     radix           current number conversion radix
429  *
430  *      functions called:
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
437  *
438  *      side effects:
439  *              Head, area, and symbol structures are created and
440  *              the radix is set as the .rel file(s) are read.
441  */
442
443 VOID
444 link()
445 {
446         register c;
447
448         if ((c=endline()) == 0) { return; }
449         switch (c) {
450
451         case 'X':
452                 radix = 16;
453                 break;
454
455         case 'D':
456                 radix = 10;
457                 break;
458
459         case 'Q':
460                 radix = 8;
461                 break;
462
463         case 'H':
464                 if (pass == 0) {
465                         newhead();
466                 } else {
467                         if (hp == 0) {
468                                 hp = headp;
469                         } else {
470                                 hp = hp->h_hp;
471                         }
472                 }
473                 sdp.s_area = NULL;
474                 sdp.s_areax = NULL;
475                 sdp.s_addr = 0;
476                 break;
477
478         case 'M':
479                 if (pass == 0)
480                         module();
481                 break;
482
483         case 'A':
484                 if (pass == 0)
485                         newarea();
486                 if (sdp.s_area == NULL) {
487                         sdp.s_area = areap;
488                         sdp.s_areax = areap->a_axp;
489                         sdp.s_addr = 0;
490                 }
491                 break;
492
493         case 'S':
494                 if (pass == 0)
495                         newsym();
496                 break;
497
498         case 'T':
499         case 'R':
500         case 'P':
501                 if (pass == 0)
502                         break;
503                 reloc(c);
504                 break;
505
506         default:
507                 break;
508         }
509         if (c == 'X' || c == 'D' || c == 'Q') {
510                 if ((c = get()) == 'H') {
511                         hilo = 1;
512                 } else
513                 if (c == 'L') {
514                         hilo = 0;
515                 }
516         }
517 }
518
519 /*)Function     VOID    map()
520  *
521  *      The function map() opens the output map file and calls the various
522  *      routines to
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.
529  *
530  *      local variables:
531  *              int     i               counter
532  *              head *  hdp             pointer to head structure
533  *              lbfile *lbfh            pointer to library file structure
534  *
535  *      global variables:
536  *              area    *ap             Pointer to the current
537  *                                      area structure
538  *              area    *areap          The pointer to the first
539  *                                      area structure of a linked list
540  *              base    *basep          The pointer to the first
541  *                                      base structure
542  *              base    *bsp            Pointer to the current
543  *                                      base structure
544  *              lfile   *filep          The pointer *filep points to the
545  *                                      beginning of a linked list of
546  *                                      lfile structures.
547  *              globl   *globlp         The pointer to the first
548  *                                      globl structure
549  *              globl   *gsp            Pointer to the current
550  *                                      globl structure
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
557  *                                      specification
558  *              int     lop             current line number on page
559  *              FILE    *mfp            Map output file handle
560  *              int     page            current page number
561  *
562  *      functions called:
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
569  *
570  *      side effects:
571  *              The map file is created.
572  */
573
574 #ifndef MLH_MAP
575 VOID
576 map()
577 {
578         register i;
579         register struct head *hdp;
580         register struct lbfile *lbfh;
581
582         /*
583          * Open Map File
584          */
585 #ifdef SDK
586         mfp = afile(linkp->f_idp, "map", 1);
587 #else /* SDK */
588         mfp = afile(linkp->f_idp, "MAP", 1);
589 #endif /* SDK */
590         if (mfp == NULL) {
591                 lkexit(1);
592         }
593
594         /*
595          * Output Map Area Lists
596          */
597         page = 0;
598         lop  = NLPP;
599         ap = areap;
600         while (ap) {
601                 lstarea(ap);
602                 ap = ap->a_ap;
603         }
604         /*
605          * List Linked Files
606          */
607         newpag(mfp);
608         fprintf(mfp, "\nFiles Linked      [ module(s) ]\n\n");
609         hdp = headp;
610 #ifdef SDK
611         filep = linkp->f_flp;
612 #else /* SDK */
613         filep = linkp;
614 #endif /* SDK */
615         while (filep) {
616                 fprintf(mfp, "%-16s", filep->f_idp);
617                 i = 0;
618                 while ((hdp != NULL) && (hdp->h_lfile == filep)) {
619                         if (i % 5) {
620                             fprintf(mfp, ", %8.8s", hdp->m_id);
621                         } else {
622                             if (i) {
623                                 fprintf(mfp, ",\n%20s%8.8s", "", hdp->m_id);
624                             } else {
625                                 fprintf(mfp, "  [ %8.8s", hdp->m_id);
626                             }
627                         }
628                         hdp = hdp->h_hp;
629                         i++;
630                 }
631                 if (i)
632                         fprintf(mfp, " ]");
633                 fprintf(mfp, "\n");
634                 filep = filep->f_flp;
635         }
636         /*
637          * List Linked Libraries
638          */
639         if (lbfhead != NULL) {
640                 fprintf(mfp,
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);
645                 }
646                 fprintf(mfp, "\n");
647         }
648         /*
649          * List Base Address Definitions
650          */
651         if (basep) {
652                 newpag(mfp);
653                 fprintf(mfp, "\nUser Base Address Definitions\n\n");
654                 bsp = basep;
655                 while (bsp) {
656                         fprintf(mfp, "%s\n", bsp->b_strp);
657                         bsp = bsp->b_base;
658                 }
659         }
660         /*
661          * List Global Definitions
662          */
663         if (globlp) {
664                 newpag(mfp);
665                 fprintf(mfp, "\nUser Global Definitions\n\n");
666                 gsp = globlp;
667                 while (gsp) {
668                         fprintf(mfp, "%s\n", gsp->g_strp);
669                         gsp = gsp->g_globl;
670                 }
671         }
672         fprintf(mfp, "\n\f");
673         symdef(mfp);
674 }
675 #else
676 VOID map()
677 {
678         register i;
679         register struct head *hdp;
680         register struct lbfile *lbfh;
681
682         /*
683          * Open Map File
684          */
685 #ifdef SDK
686         mfp = afile(linkp->f_idp, "map", 1);
687 #else /* SDK */
688         mfp = afile(linkp->f_idp, "MAP", 1);
689 #endif /* SDK */
690         if (mfp == NULL) {
691                 lkexit(1);
692         }
693
694         /*
695          *Output Map Area Lists
696          */
697         page = 0;
698         lop  = NLPP;
699         ap = areap;
700         while (ap) {
701                 lstarea(ap);
702                 ap = ap->a_ap;
703         }
704         /*
705          * List Linked Files
706          */
707         hdp = headp;
708 #ifdef SDK
709         filep = linkp->f_flp;
710 #else /* SDK */
711         filep = linkp;
712 #endif /* SDK */
713         if (filep) {
714                 fprintf( mfp, "MODULES\n");
715         }
716         while (filep) {
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);
721                         hdp = hdp->h_hp;
722                 }
723                 filep = filep->f_flp;
724         }
725         /*
726          * List Linked Libraries
727          */
728         if (lbfhead != NULL) {
729                 fprintf(mfp, "LIBRARIES\n");
730                 for (lbfh=lbfhead; lbfh; lbfh=lbfh->next) {
731                         fprintf(mfp,    "\tLIBRARY %s\n"
732                                         "\t\tMODULE %s\n",
733                                 lbfh->libspc, lbfh->relfil);
734                 }
735         }
736         /*
737          * List Base Address Definitions
738          */
739         if (basep) {
740                 fprintf(mfp, "USERBASEDEF\n");
741                 bsp = basep;
742                 while (bsp) {
743                         fprintf(mfp, "\t%s\n", bsp->b_strp);
744                         bsp = bsp->b_base;
745                 }
746         }
747         /*
748          * List Global Definitions
749          */
750         if (globlp) {
751                 fprintf(mfp, "USERGLOBALDEF\n");
752                 gsp = globlp;
753                 while (gsp) {
754                         fprintf(mfp, "\t%s\n", gsp->g_strp);
755                         gsp = gsp->g_globl;
756                 }
757         }
758         symdef(mfp);
759 #ifdef SDK
760         if (mfp!=NULL) {
761                 fclose(mfp);
762                 mfp = NULL;
763         }
764 #endif
765 }
766 #endif /* MLH_MAP */
767
768 #ifdef SDK
769 VOID sym()
770 {
771         register i;
772         register struct head *hdp;
773         register struct lbfile *lbfh;
774
775         /*
776          * Open sym File
777          */
778         mfp = afile(linkp->f_idp, "sym", 1);
779         if (mfp == NULL) {
780                 lkexit(1);
781         }
782         fprintf( mfp,   "; no$gmb format .sym file\n"
783                         "; Generated automagically by ASxxxx linker %s (SDK " SDK_VERSION_STRING ")\n"
784                 , VERSION );
785         /*
786          * Output sym Area Lists
787          */
788         page = 0;
789         lop  = NLPP;
790         ap = areap;
791         while (ap) {
792                 lstareatosym(ap);
793                 ap = ap->a_ap;
794         }
795         if (mfp!=NULL) {
796                 fclose(mfp);
797                 mfp = NULL;
798         }
799 }
800 #endif /* SDK */
801
802 /*)Function     int     parse()
803  *
804  *      The function parse() evaluates all command line or file input
805  *      linker directives and updates the appropriate variables.
806  *
807  *      local variables:
808  *              int     c               character value
809  *              char    fid[]           file id string
810  *
811  *      global variables:
812  *              char    ctype[]         array of character types, one per
813  *                                      ASCII character
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
818  *                                      specification
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
825  *
826  *      Functions called:
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
837  *
838  *      side effects:
839  *              Various linker flags are updated and the linked
840  *              structure lfile is created.
841  */
842
843 int
844 parse()
845 {
846         register c;
847         char fid[NINPUT];
848
849         while ((c = getnb()) != 0) {
850                 if ( c == '-') {
851                         while (ctype[c=get()] & LETTER) {
852                                 switch(c) {
853
854                                 case 'i':
855                                 case 'I':
856                                         oflag = 1;
857                                         break;
858
859                                 case 's':
860                                 case 'S':
861                                         oflag = 2;
862                                         break;
863 #ifdef GAMEBOY
864                                 case 'y':
865                                 case 'Y':
866                                         c = get();
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')
872                                                 mbc_type = expr(0);
873                                         else if(c == 'N' || c == 'n') {
874                                                 int i = 0;
875                                                 if(getnb() != '=' || getnb() != '"') {
876                                                         fprintf(stderr, "Syntax error in -YN=\"name\" flag\n");
877                                                         lkexit(1);
878                                                 }
879                                                 while((c = get()) != '"' && i < 16) {
880                                                         cart_name[i++] = c;
881                                                 }
882                                                 if(i < 16)
883                                                         cart_name[i] = 0;
884                                                 else
885                                                         while(get() != '"')
886                                                                 ;
887                                         } else if(c == 'P' || c == 'p') {
888                                                 unsigned int addr;
889                                                 unsigned char value;
890                                                 patch *p = patches;
891
892                                                 patches = (patch *)malloc(sizeof(patch));
893                                                 patches->next = p;
894                                                 patches->addr = expr(0);
895                                                 if(getnb() != '=') {
896                                                         fprintf(stderr, "Syntax error in -YHaddr=val flag\n");
897                                                         lkexit(1);
898                                                 }
899                                                 patches->value = expr(0);
900                                         } else {
901                                                 fprintf(stderr, "Invalid option\n");
902                                                 lkexit(1);
903                                         }
904                                         break;
905
906 #endif /* GAMEBOY */
907 #ifdef SDK
908                                 case 'j':
909                                 case 'J':
910                                         ++symflag;
911                                         break;
912                                 case 'z':
913                                 case 'Z':
914                                         oflag = 3;
915                                         break;
916 #endif /* SDK */
917                                 case 'm':
918                                 case 'M':
919                                         ++mflag;
920                                         break;
921
922                                 case 'u':
923                                 case 'U':
924                                         uflag = 1;
925                                         break;
926
927                                 case 'x':
928                                 case 'X':
929                                         xflag = 0;
930                                         break;
931
932                                 case 'q':
933                                 case 'Q':
934                                         xflag = 1;
935                                         break;
936
937                                 case 'd':
938                                 case 'D':
939                                         xflag = 2;
940                                         break;
941
942                                 case 'e':
943                                 case 'E':
944                                         return(1);
945
946                                 case 'n':
947                                 case 'N':
948                                         pflag = 0;
949                                         break;
950
951                                 case 'p':
952                                 case 'P':
953                                         pflag = 1;
954                                         break;
955
956                                 case 'b':
957                                 case 'B':
958                                         bassav();
959                                         return(0);
960
961                                 case 'g':
962                                 case 'G':
963                                         gblsav();
964                                         return(0);
965
966                                 case 'k':
967                                 case 'K':
968                                         addpath();
969                                         return(0);
970
971                                 case 'l':
972                                 case 'L':
973                                         addlib();
974                                         return(0);
975
976                                 default:
977                                         fprintf(stderr, "Invalid option\n");
978                                         lkexit(1);
979                                 }
980                         }
981                 } else
982                 if (ctype[c] != ILL) {
983                         if (linkp == NULL) {
984                                 linkp = (struct lfile *)
985                                         new (sizeof (struct lfile));
986                                 lfp = linkp;
987                         } else {
988                                 lfp->f_flp = (struct lfile *)
989                                                 new (sizeof (struct lfile));
990                                 lfp = lfp->f_flp;
991                         }
992                         getfid(fid, c);
993                         lfp->f_idp = (char *) new (strlen(fid)+1);
994                         strcpy(lfp->f_idp, fid);
995                         lfp->f_type = F_REL;
996                 } else {
997                         fprintf(stderr, "Invalid input");
998                         lkexit(1);
999                 }
1000         }
1001         return(0);
1002 }
1003
1004 /*)Function     VOID    bassav()
1005  *
1006  *      The function bassav() creates a linked structure containing
1007  *      the base address strings input to the linker.
1008  *
1009  *      local variables:
1010  *              none
1011  *
1012  *      global variables:
1013  *              base    *basep          The pointer to the first
1014  *                                      base structure
1015  *              base    *bsp            Pointer to the current
1016  *                                      base structure
1017  *              char    *ip             pointer into the REL file
1018  *                                      text line in ib[]
1019  *
1020  *       functions called:
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
1026  *
1027  *      side effects:
1028  *              The basep structure is created.
1029  */
1030
1031 VOID
1032 bassav()
1033 {
1034         if (basep == NULL) {
1035                 basep = (struct base *)
1036                         new (sizeof (struct base));
1037                 bsp = basep;
1038         } else {
1039                 bsp->b_base = (struct base *)
1040                                 new (sizeof (struct base));
1041                 bsp = bsp->b_base;
1042         }
1043         unget(getnb());
1044         bsp->b_strp = (char *) new (strlen(ip)+1);
1045         strcpy(bsp->b_strp, ip);
1046 }
1047         
1048 /*)Function     VOID    setbas()
1049  *
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.
1053  *
1054  *      local variables:
1055  *              int     v               expression value
1056  *              char    id[]            base id string
1057  *
1058  *      global variables:
1059  *              area    *ap             Pointer to the current
1060  *                                      area structure
1061  *              area    *areap          The pointer to the first
1062  *                                      area structure of a linked list
1063  *              base    *basep          The pointer to the first
1064  *                                      base structure
1065  *              base    *bsp            Pointer to the current
1066  *                                      base structure
1067  *              char    *ip             pointer into the REL file
1068  *                                      text line in ib[]
1069  *              int     lkerr           error flag
1070  *
1071  *       functions called:
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
1077  *
1078  *      side effects:
1079  *              The base address of an area is set.
1080  */
1081
1082 VOID
1083 setbas()
1084 {
1085         register v;
1086         char id[NCPS];
1087
1088         bsp = basep;
1089         while (bsp) {
1090                 ip = bsp->b_strp;
1091                 getid(id, -1);
1092                 if (getnb() == '=') {
1093                         v = expr(0);
1094                         for (ap = areap; ap != NULL; ap = ap->a_ap) {
1095                                 if (symeq(id, ap->a_id))
1096                                         break;
1097                         }
1098                         if (ap == NULL) {
1099 #ifndef SDK
1100                                 fprintf(stderr,
1101                                 "No definition of area %s\n", id);
1102                                 lkerr++;
1103 #endif /* SDK */
1104                         } else {
1105                                 ap->a_addr = v;
1106                         }
1107                 } else {
1108                         fprintf(stderr, "No '=' in base expression");
1109                         lkerr++;
1110                 }
1111                 bsp = bsp->b_base;
1112         }
1113 }
1114
1115 /*)Function     VOID    gblsav()
1116  *
1117  *      The function gblsav() creates a linked structure containing
1118  *      the global variable strings input to the linker.
1119  *
1120  *      local variable:
1121  *              none
1122  *
1123  *      global variables:
1124  *              globl   *globlp         The pointer to the first
1125  *                                      globl structure
1126  *              globl   *gsp            Pointer to the current
1127  *                                      globl structure
1128  *              char    *ip             pointer into the REL file
1129  *                                      text line in ib[]
1130  *              int     lkerr           error flag
1131  *
1132  *      functions called:
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
1138  *
1139  *      side effects:
1140  *              The globlp structure is created.
1141  */
1142
1143 VOID
1144 gblsav()
1145 {
1146         if (globlp == NULL) {
1147                 globlp = (struct globl *)
1148                         new (sizeof (struct globl));
1149                 gsp = globlp;
1150         } else {
1151                 gsp->g_globl = (struct globl *)
1152                                 new (sizeof (struct globl));
1153                 gsp = gsp->g_globl;
1154         }
1155         unget(getnb());
1156         gsp->g_strp = (char *) new (strlen(ip)+1);
1157         strcpy(gsp->g_strp, ip);
1158 }
1159         
1160 /*)Function     VOID    setgbl()
1161  *
1162  *      The function setgbl() scans the global variable lines in hte
1163  *      globlp structure, evaluates the arguments, and sets a variable
1164  *      to this value.
1165  *
1166  *      local variables:
1167  *              int     v               expression value
1168  *              char    id[]            base id string
1169  *              sym *   sp              pointer to a symbol structure
1170  *
1171  *      global variables:
1172  *              char    *ip             pointer into the REL file
1173  *                                      text line in ib[]
1174  *              globl   *globlp         The pointer to the first
1175  *                                      globl structure
1176  *              globl   *gsp            Pointer to the current
1177  *                                      globl structure
1178  *              FILE *  stderr          c_library
1179  *              int     lkerr           error flag
1180  *
1181  *       functions called:
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
1187  *
1188  *      side effects:
1189  *              The value of a variable is set.
1190  */
1191
1192 VOID
1193 setgbl()
1194 {
1195         register v;
1196         register struct sym *sp;
1197         char id[NCPS];
1198
1199         gsp = globlp;
1200         while (gsp) {
1201                 ip = gsp->g_strp;
1202                 getid(id, -1);
1203                 if (getnb() == '=') {
1204                         v = expr(0);
1205                         sp = lkpsym(id, 0);
1206                         if (sp == NULL) {
1207 #ifndef SDK
1208                                 fprintf(stderr,
1209                                 "No definition of symbol %s\n", id);
1210                                 lkerr++;
1211 #endif /* SDK */
1212                         } else {
1213 #ifndef SDK
1214                                 if (sp->s_flag & S_DEF) {
1215                                         fprintf(stderr,
1216                                         "Redefinition of symbol %s\n", id);
1217                                         lkerr++;
1218                                         sp->s_axp = NULL;
1219                                 }
1220 #endif /* SDK */
1221                                 sp->s_addr = v;
1222                                 sp->s_type |= S_DEF;
1223                         }
1224                 } else {
1225                         fprintf(stderr, "No '=' in global expression");
1226                         lkerr++;
1227                 }
1228                 gsp = gsp->g_globl;
1229         }
1230 }
1231
1232 /*)Function     FILE *  afile(fn,, ft, wf)
1233  *
1234  *              char *  fn              file specification string
1235  *              char *  ft              file type string
1236  *              int     wf              read(0)/write(1) flag
1237  *
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.
1248  *
1249  *      afile() returns a file handle for the opened file or aborts
1250  *      the assembler on an open error.
1251  *
1252  *      local variables:
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
1259  *
1260  *      global variables:
1261  *              int     lkerr           error flag
1262  *
1263  *      functions called:
1264  *              FILE *  fopen()         c_library
1265  *              int     fprintf()       c_library
1266  *
1267  *      side effects:
1268  *              File is opened for read or write.
1269  */
1270
1271 FILE *
1272 afile(fn, ft, wf)
1273 char *fn;
1274 char *ft;
1275 {
1276         register char *p1, *p2, *p3;
1277         register c;
1278         FILE *fp;
1279         char fb[FILSPC];
1280
1281         p1 = fn;
1282         p2 = fb;
1283         p3 = ft;
1284         while ((c = *p1++) != 0 && c != FSEPX) {
1285                 if (p2 < &fb[FILSPC-4])
1286                         *p2++ = c;
1287         }
1288         *p2++ = FSEPX;
1289         if (*p3 == 0) {
1290                 if (c == FSEPX) {
1291                         p3 = p1;
1292                 } else {
1293 #ifdef SDK
1294                         p3 = "rel";
1295 #else /* SDK */
1296                         p3 = "REL";
1297 #endif /* SDK */
1298                 }
1299         }
1300         while ((c = *p3++) != 0) {
1301                 if (p2 < &fb[FILSPC-1])
1302                         *p2++ = c;
1303         }
1304         *p2++ = 0;
1305 #ifdef SDK
1306         if ((fp = fopen(fb, wf?(binary?"wb":"w"):(binary?"rb":"r"))) == NULL) {
1307 #else /* SDK */
1308         if ((fp = fopen(fb, wf?"w":"r")) == NULL) {
1309 #endif /* SDK */
1310                 fprintf(stderr, "%s: cannot %s.\n", fb, wf?"create":"open");
1311                 lkerr++;
1312         }
1313         return (fp);
1314 }
1315
1316 char *usetxt[] = {
1317 #ifdef SDK
1318         "Distributed with SDK " SDK_VERSION_STRING ", built on " __DATE__ " " __TIME__,
1319         "Compile options: SDK Target " TARGET_STRING
1320 #ifdef INDEXLIB
1321         " INDEXLIB"
1322 #endif
1323         "\n",
1324 #endif
1325         "Startup:",
1326 #ifdef SDK
1327         "  --   [Commands]              Non-interactive command line input",
1328 #endif /* SDK */
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",
1333 #ifdef SDK
1334         "Usage: [-Options] outfile file [file ...]",
1335 #else /* SDK */
1336         "Usage: [-Options] file [file ...]",
1337 #endif /* SDK */
1338         "Librarys:",
1339         "  -k   Library path specification, one per -k",
1340         "  -l   Library file specification, one per -l",
1341         "Relocation:",
1342         "  -b   area base address = expression",
1343         "  -g   global symbol = expression",
1344 #ifdef GAMEBOY
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 */
1351         "Map format:",
1352         "  -m   Map output generated as file[MAP]",
1353 #ifdef SDK
1354         "  -j   no$gmb symbol file generated as file[SYM]",
1355 #endif /* SDK */
1356         "  -x   Hexidecimal (default)",
1357         "  -d   Decimal",
1358         "  -q   Octal",
1359         "Output:",
1360         "  -i   Intel Hex as file[IHX]",
1361         "  -s   Motorola S19 as file[S19]",
1362 #ifdef SDK
1363 #ifdef GAMEGEAR
1364         "  -z   Gamegear image as file[GG]",
1365 #else
1366         "  -z   Gameboy image as file[GB]",
1367 #endif /* GAMEGEAR */
1368 #endif /* SDK */
1369         "List:",
1370         "  -u   Update listing file(s) with link data as file(s)[.RST]",
1371         "End:",
1372         "  -e   or null line terminates input",
1373         "",
1374         0
1375 };
1376
1377 /*)Function     VOID    usage()
1378  *
1379  *      The function usage() outputs to the stderr device the
1380  *      assembler name and version and a list of valid assembler options.
1381  *
1382  *      local variables:
1383  *              char ** dp              pointer to an array of
1384  *                                      text string pointers.
1385  *
1386  *      global variables:
1387  *              FILE *  stderr          c_library
1388  *
1389  *      functions called:
1390  *              int     fprintf()       c_library
1391  *
1392  *      side effects:
1393  *              none
1394  */
1395
1396 VOID
1397 usage()
1398 {
1399         register char   **dp;
1400
1401         fprintf(stderr, "\nASxxxx Linker %s\n\n", VERSION);
1402         for (dp = usetxt; *dp; dp++)
1403                 fprintf(stderr, "%s\n", *dp);
1404         lkexit(1);
1405 }