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