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