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