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