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