548a44fdf53ba6e222c337bba8c1681192fff450
[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                         }
363                 } else {
364                         /*
365                          * Link in library files
366                          */
367                         library();
368                         reloc('E');
369                 }
370         }
371         //JCF:
372         CreateAOMF51();
373
374 #ifdef WIN32T
375     Timer(1, "Linker execution time");
376 #endif
377
378         lkexit(lkerr);
379         return 0;
380 }
381
382 /*)Function     VOID    lkexit(i)
383  *
384  *                      int     i       exit code
385  *
386  *      The function lkexit() explicitly closes all open
387  *      files and then terminates the program.
388  *
389  *      local variables:
390  *              none
391  *
392  *      global variables:
393  *              FILE *  mfp             file handle for .map
394  *              FILE *  ofp             file handle for .ihx/.s19
395  *              FILE *  rfp             file hanlde for .rst
396  *              FILE *  sfp             file handle for .rel
397  *              FILE *  tfp             file handle for .lst
398  *
399  *      functions called:
400  *              int     fclose()        c_library
401  *              VOID    exit()          c_library
402  *
403  *      side effects:
404  *              All files closed. Program terminates.
405  */
406
407 VOID
408 lkexit(i)
409 int i;
410 {
411         if (mfp != NULL) fclose(mfp);
412         if (jfp != NULL) fclose(jfp);
413         if (ofp != NULL) fclose(ofp);
414         if (rfp != NULL) fclose(rfp);
415         if (sfp != NULL) fclose(sfp);
416         if (tfp != NULL) fclose(tfp);
417         if (dfp != NULL) fclose(dfp);
418         /*if (dfp != NULL)
419             FILE *xfp = afile(linkp->f_idp,"cdb",1);
420             dfp = freopen("temp.cdb","r",dfp);
421             copyfile(xfp,dfp);
422             fclose(xfp);
423             fclose(dfp);
424             unlink("temp.cdb");
425         }*/
426         exit(i);
427 }
428
429 /*)Function     link_main()
430  *
431  *      The function link_main() evaluates the directives for each line of
432  *      text read from the .rel file(s).  The valid directives processed
433  *      are:
434  *              X, D, Q, H, M, A, S, T, R, and P.
435  *
436  *      local variables:
437  *              int     c               first non blank character of a line
438  *
439  *      global variables:
440  *              head    *headp          The pointer to the first
441  *                                              head structure of a linked list
442  *              head    *hp             Pointer to the current
443  *                                              head structure
444  *              int     pass            linker pass number
445  *              int     radix           current number conversion radix
446  *
447  *      functions called:
448  *              char    endline()       lklex.c
449  *              VOID    module()        lkhead.c
450  *              VOID    newarea()       lkarea.c
451  *              VOID    newhead()       lkhead.c
452  *              sym *   newsym()        lksym.c
453  *              VOID    reloc()         lkreloc.c
454  *
455  *      side effects:
456  *              Head, area, and symbol structures are created and
457  *              the radix is set as the .rel file(s) are read.
458  */
459
460 VOID
461 link_main()
462 {
463         register int c;
464
465         if ((c=endline()) == 0) { return; }
466         switch (c) {
467
468     case 'O': /*For some important sdcc options*/
469         if (pass == 0)
470         {
471             if(strlen(sdccopt)==0)
472             {
473                 strcpy(sdccopt, &ip[1]);
474                 strcpy(sdccopt_module, curr_module);
475             }
476             else
477             {
478                 if(strcmp(sdccopt, &ip[1])!=0)
479                 {
480                                     fprintf(stderr,
481                                     "?ASlink-Warning-Conflicting sdcc options:\n"
482                     "   \"%s\" in module \"%s\" and\n"
483                     "   \"%s\" in module \"%s\".\n",
484                     sdccopt, sdccopt_module, &ip[1], curr_module);
485                                     lkerr++;
486                 }
487             }
488         }
489                 break;
490
491         case 'X':
492                 radix = 16;
493                 break;
494
495         case 'D':
496                 radix = 10;
497                 break;
498
499         case 'Q':
500                 radix = 8;
501                 break;
502
503         case 'H':
504                 if (pass == 0) {
505                         newhead();
506                 } else {
507                         if (hp == 0) {
508                                 hp = headp;
509                         } else {
510                                 hp = hp->h_hp;
511                         }
512                 }
513                 sdp.s_area = NULL;
514                 sdp.s_areax = NULL;
515                 sdp.s_addr = 0;
516                 break;
517
518         case 'M':
519                 if (pass == 0)
520         {
521             strcpy(curr_module, &ip[1]);
522                         module();
523         }
524                 break;
525
526         case 'A':
527                 if (pass == 0)
528                         newarea();
529                 if (sdp.s_area == NULL) {
530                         sdp.s_area = areap;
531                         sdp.s_areax = areap->a_axp;
532                         sdp.s_addr = 0;
533                 }
534                 break;
535
536         case 'S':
537                 if (pass == 0)
538                         newsym();
539                 break;
540
541         case 'T':
542         case 'R':
543         case 'P':
544                 if (pass == 0)
545                         break;
546                 reloc(c);
547                 break;
548
549         default:
550                 break;
551         }
552         if (c == 'X' || c == 'D' || c == 'Q') {
553                 if ((c = get()) == 'H') {
554                         hilo = 1;
555                 } else
556                 if (c == 'L') {
557                         hilo = 0;
558                 }
559         }
560 }
561
562
563 /*)Function     VOID    map()
564  *
565  *      The function map() opens the output map file and calls the various
566  *      routines to
567  *      (1) output the variables in each area,
568  *      (2) list the files processed with module names,
569  *      (3) list the libraries file processed,
570  *      (4) list base address definitions,
571  *      (5) list global variable definitions, and
572  *      (6) list any undefined variables.
573  *
574  *      local variables:
575  *              int             i               counter
576  *              head *  hdp             pointer to head structure
577  *              lbfile *lbfh            pointer to library file structure
578  *
579  *      global variables:
580  *              area    *ap             Pointer to the current
581  *                                              area structure
582  *              area    *areap          The pointer to the first
583  *                                              area structure of a linked list
584  *              base    *basep          The pointer to the first
585  *                                              base structure
586  *              base    *bsp            Pointer to the current
587  *                                              base structure
588  *              lfile   *filep                  The pointer *filep points to the
589  *                                              beginning of a linked list of
590  *                                              lfile structures.
591  *              globl   *globlp         The pointer to the first
592  *                                              globl structure
593  *              globl   *gsp            Pointer to the current
594  *                                              globl structure
595  *              head    *headp          The pointer to the first
596  *                                              head structure of a linked list
597  *              lbfile  *lbfhead        The pointer to the first
598  *                                      lbfile structure of a linked list
599  *              lfile   *linkp          pointer to first lfile structure
600  *                                              containing an input REL file
601  *                                              specification
602  *              int     lop             current line number on page
603  *              FILE    *mfp            Map output file handle
604  *              int     page            current page number
605  *
606  *      functions called:
607  *              FILE *  afile()         lkmain.c
608  *              int     fprintf()       c_library
609  *              VOID    lkexit()        lkmain.c
610  *              VOID    lstarea()       lklist.c
611  *              VOID    newpag()        lklist.c
612  *              VOID    symdef()        lksym.c
613  *
614  *      side effects:
615  *              The map file is created.
616  */
617
618 VOID
619 map()
620 {
621         register int i;
622         register struct head *hdp;
623         register struct lbfile *lbfh;
624
625         /*
626          * Open Map File
627          */
628         mfp = afile(linkp->f_idp, "map", 1);
629         if (mfp == NULL) {
630                 lkexit(1);
631         }
632
633         /*
634          * Output Map Area Lists
635          */
636         page = 0;
637         lop  = NLPP;
638         ap = areap;
639         while (ap) {
640                 lstarea(ap);
641                 ap = ap->a_ap;
642         }
643         /*
644          * List Linked Files
645          */
646         newpag(mfp);
647         fprintf(mfp, "\nFiles Linked      [ module(s) ]\n\n");
648         hdp = headp;
649         filep = linkp;
650         while (filep) {
651                 fprintf(mfp, "%-16s", filep->f_idp);
652                 i = 0;
653                 while ((hdp != NULL) && (hdp->h_lfile == filep)) {
654                         if (i % 5) {
655                             fprintf(mfp, ", %8.8s", hdp->m_id);
656                         } else {
657                             if (i) {
658                                 fprintf(mfp, ",\n%20s%8.8s", "", hdp->m_id);
659                             } else {
660                                 fprintf(mfp, "  [ %8.8s", hdp->m_id);
661                             }
662                         }
663                         hdp = hdp->h_hp;
664                         i++;
665                 }
666                 if (i)
667                         fprintf(mfp, " ]");
668                 fprintf(mfp, "\n");
669                 filep = filep->f_flp;
670         }
671         /*
672          * List Linked Libraries
673          */
674         if (lbfhead != NULL) {
675                 fprintf(mfp,
676         "\nLibraries Linked                    [   object  file   ]\n\n");
677                 for (lbfh=lbfhead; lbfh; lbfh=lbfh->next) {
678                         fprintf(mfp, "%-32s    [ %16.16s ]\n",
679                                 lbfh->libspc, lbfh->relfil);
680                 }
681                 fprintf(mfp, "\n");
682         }
683         /*
684          * List Base Address Definitions
685          */
686         if (basep) {
687                 newpag(mfp);
688                 fprintf(mfp, "\nUser Base Address Definitions\n\n");
689                 bsp = basep;
690                 while (bsp) {
691                         fprintf(mfp, "%s\n", bsp->b_strp);
692                         bsp = bsp->b_base;
693                 }
694         }
695         /*
696          * List Global Definitions
697          */
698         if (globlp) {
699                 newpag(mfp);
700                 fprintf(mfp, "\nUser Global Definitions\n\n");
701                 gsp = globlp;
702                 while (gsp) {
703                         fprintf(mfp, "%s\n", gsp->g_strp);
704                         gsp = gsp->g_globl;
705                 }
706         }
707         fprintf(mfp, "\n\f");
708         symdef(mfp);
709 }
710
711 /*)Function     int     parse()
712  *
713  *      The function parse() evaluates all command line or file input
714  *      linker directives and updates the appropriate variables.
715  *
716  *      local variables:
717  *              int     c               character value
718  *              char    fid[]           file id string
719  *
720  *      global variables:
721  *              char    ctype[]         array of character types, one per
722  *                                              ASCII character
723  *              lfile   *lfp            pointer to current lfile structure
724  *                                              being processed by parse()
725  *              lfile   *linkp          pointer to first lfile structure
726  *                                              containing an input REL file
727  *                                              specification
728  *              int     mflag           Map output flag
729  *              int     oflag           Output file type flag
730  *              int     pflag           print linker command file flag
731  *              FILE *  stderr          c_library
732  *              int     uflag           Relocated listing flag
733  *              int     xflag           Map file radix type flag
734  *
735  *      Functions called:
736  *              VOID    addlib()        lklibr.c
737  *              VOID    addpath()       lklibr.c
738  *              VOID    bassav()        lkmain.c
739  *              int     fprintf()       c_library
740  *              VOID    gblsav()        lkmain.c
741  *              VOID    getfid()        lklex.c
742  *              char    getnb()         lklex.c
743  *              VOID    lkexit()        lkmain.c
744  *              char *  strcpy()        c_library
745  *              int     strlen()        c_library
746  *
747  *      side effects:
748  *              Various linker flags are updated and the linked
749  *              structure lfile is created.
750  */
751
752 int
753 parse()
754 {
755         register int c;
756         char fid[NINPUT];
757
758         while ((c = getnb()) != 0) {
759                 if ( c == '-') {
760                         while (ctype[c=get()] & LETTER) {
761                                 switch(c) {
762
763                                 case 'i':
764                                 case 'I':
765                                         oflag = 1;
766                                         break;
767
768                                 case 's':
769                                 case 'S':
770                                         oflag = 2;
771                                         break;
772
773                                 case 'm':
774                                 case 'M':
775                                         ++mflag;
776                                         break;
777
778                                 case 'y': /*JCF: memory usage summary output*/
779                                 case 'Y':
780                                         ++sflag;
781                                         break;
782
783                                 case 'j':
784                                 case 'J':
785                                         jflag = 1;
786                                         break;
787
788                                 case 'u':
789                                 case 'U':
790                                         uflag = 1;
791                                         break;
792                                 case 'r':
793                                 case 'R':
794                                         rflag = 1;
795                                         break;
796                                 case 'x':
797                                 case 'X':
798                                         xflag = 0;
799                                         break;
800
801                                 case 'q':
802                                 case 'Q':
803                                         xflag = 1;
804                                         break;
805
806                                 case 'd':
807                                 case 'D':
808                                         xflag = 2;
809                                         break;
810
811                                 case 'e':
812                                 case 'E':
813                                         return(1);
814
815                                 case 'n':
816                                 case 'N':
817                                         pflag = 0;
818                                         break;
819
820                                 case 'p':
821                                 case 'P':
822                                         pflag = 1;
823                                         break;
824
825                                 case 'b':
826                                 case 'B':
827                                         bassav();
828                                         return(0);
829
830                                 case 'g':
831                                 case 'G':
832                                         gblsav();
833                                         return(0);
834
835                                 case 'k':
836                                 case 'K':
837                                         addpath();
838                                         return(0);
839
840                                 case 'l':
841                                 case 'L':
842                                         addlib();
843                                         return(0);
844
845                                 case 'a':
846                                 case 'A':
847                                         iramsav();
848                                         return(0);
849
850                                 case 'v':
851                                 case 'V':
852                                         xramsav();
853                                         return(0);
854
855                                 case 'w':
856                                 case 'W':
857                                         codesav();
858                                         return(0);
859
860                                 case 'z':
861                                 case 'Z':
862                                         dflag = 1;                                      
863                                         return(0);
864                                 default:
865                                         fprintf(stderr, "Invalid option\n");
866                                         lkexit(1);
867                                 }
868                         }
869                 } else
870                if (ctype[c] & ILL) {
871                        fprintf(stderr, "Invalid input");
872                        lkexit(1);
873                } else {
874                         if (linkp == NULL) {
875                                 linkp = (struct lfile *)
876                                         new (sizeof (struct lfile));
877                                 lfp = linkp;
878                         } else {
879                                 lfp->f_flp = (struct lfile *)
880                                                 new (sizeof (struct lfile));
881                                 lfp = lfp->f_flp;
882                         }
883                         getfid(fid, c);
884                         lfp->f_idp = (char *) new (strlen(fid)+1);
885                         strcpy(lfp->f_idp, fid);
886                         lfp->f_type = F_REL;
887                 }
888         }
889         return(0);
890 }
891
892 /*)Function     VOID    bassav()
893  *
894  *      The function bassav() creates a linked structure containing
895  *      the base address strings input to the linker.
896  *
897  *      local variables:
898  *              none
899  *
900  *      global variables:
901  *              base    *basep          The pointer to the first
902  *                                              base structure
903  *              base    *bsp            Pointer to the current
904  *                                              base structure
905  *              char    *ip             pointer into the REL file
906  *                                              text line in ib[]
907  *
908  *       functions called:
909  *              char    getnb()         lklex.c
910  *              VOID *  new()           lksym.c
911  *              int     strlen()        c_library
912  *              char *  strcpy()        c_library
913  *              VOID    unget()         lklex.c
914  *
915  *      side effects:
916  *              The basep structure is created.
917  */
918
919 VOID
920 bassav()
921 {
922         if (basep == NULL) {
923                 basep = (struct base *)
924                         new (sizeof (struct base));
925                 bsp = basep;
926         } else {
927                 bsp->b_base = (struct base *)
928                                 new (sizeof (struct base));
929                 bsp = bsp->b_base;
930         }
931         unget(getnb());
932         bsp->b_strp = (char *) new (strlen(ip)+1);
933         strcpy(bsp->b_strp, ip);
934 }
935
936 /*)Function     VOID    setbas()
937  *
938  *      The function setbas() scans the base address lines in hte
939  *      basep structure, evaluates the arguments, and sets beginning
940  *      address of the specified areas.
941  *
942  *      local variables:
943  *              int     v               expression value
944  *              char    id[]            base id string
945  *
946  *      global variables:
947  *              area    *ap             Pointer to the current
948  *                                              area structure
949  *              area    *areap          The pointer to the first
950  *                                              area structure of a linked list
951  *              base    *basep          The pointer to the first
952  *                                              base structure
953  *              base    *bsp            Pointer to the current
954  *                                              base structure
955  *              char    *ip             pointer into the REL file
956  *                                              text line in ib[]
957  *              int     lkerr           error flag
958  *
959  *       functions called:
960  *              Addr_T  expr()          lkeval.c
961  *              int     fprintf()       c_library
962  *              VOID    getid()         lklex.c
963  *              char    getnb()         lklex.c
964  *              int     symeq()         lksym.c
965  *
966  *      side effects:
967  *              The base address of an area is set.
968  */
969
970 VOID
971 setbas()
972 {
973         register int v;
974         char id[NCPS];
975
976         bsp = basep;
977         while (bsp) {
978                 ip = bsp->b_strp;
979                 getid(id, -1);
980                 if (getnb() == '=') {
981                         v = expr(0);
982                         for (ap = areap; ap != NULL; ap = ap->a_ap) {
983                                 if (symeq(id, ap->a_id))
984                                         break;
985                         }
986                         if (ap == NULL) {
987                                 fprintf(stderr,
988                                 "ASlink-Warning-No definition of area %s\n", id);
989                                 lkerr++;
990                         } else {
991                                 ap->a_addr = v;
992                                 ap->a_type = 1; /* JLH: value set */
993                         }
994                 } else {
995                         fprintf(stderr, "ASlink-Warning-No '=' in base expression");
996                         lkerr++;
997                 }
998                 bsp = bsp->b_base;
999         }
1000 }
1001
1002 /*)Function     VOID    gblsav()
1003  *
1004  *      The function gblsav() creates a linked structure containing
1005  *      the global variable strings input to the linker.
1006  *
1007  *      local variable:
1008  *              none
1009  *
1010  *      global variables:
1011  *              globl   *globlp         The pointer to the first
1012  *                                              globl structure
1013  *              globl   *gsp            Pointer to the current
1014  *                                              globl structure
1015  *              char    *ip             pointer into the REL file
1016  *                                              text line in ib[]
1017  *              int     lkerr           error flag
1018  *
1019  *      functions called:
1020  *              char    getnb()         lklex.c
1021  *              VOID *  new()           lksym.c
1022  *              int     strlen()        c_library
1023  *              char *  strcpy()        c_library
1024  *              VOID    unget()         lklex.c
1025  *
1026  *      side effects:
1027  *              The globlp structure is created.
1028  */
1029
1030 VOID
1031 gblsav()
1032 {
1033         if (globlp == NULL) {
1034                 globlp = (struct globl *)
1035                         new (sizeof (struct globl));
1036                 gsp = globlp;
1037         } else {
1038                 gsp->g_globl = (struct globl *)
1039                                 new (sizeof (struct globl));
1040                 gsp = gsp->g_globl;
1041         }
1042         unget(getnb());
1043         gsp->g_strp = (char *) new (strlen(ip)+1);
1044         strcpy(gsp->g_strp, ip);
1045 }
1046         
1047 /*)Function     VOID    setgbl()
1048  *
1049  *      The function setgbl() scans the global variable lines in hte
1050  *      globlp structure, evaluates the arguments, and sets a variable
1051  *      to this value.
1052  *
1053  *      local variables:
1054  *              int     v               expression value
1055  *              char    id[]            base id string
1056  *              sym *   sp              pointer to a symbol structure
1057  *
1058  *      global variables:
1059  *              char    *ip             pointer into the REL file
1060  *                                              text line in ib[]
1061  *              globl   *globlp         The pointer to the first
1062  *                                              globl structure
1063  *              globl   *gsp            Pointer to the current
1064  *                                              globl structure
1065  *              FILE *  stderr          c_library
1066  *              int     lkerr           error flag
1067  *
1068  *       functions called:
1069  *              Addr_T  expr()          lkeval.c
1070  *              int     fprintf()       c_library
1071  *              VOID    getid()         lklex.c
1072  *              char    getnb()         lklex.c
1073  *              sym *   lkpsym()        lksym.c
1074  *
1075  *      side effects:
1076  *              The value of a variable is set.
1077  */
1078
1079 VOID
1080 setgbl()
1081 {
1082         register int v;
1083         register struct sym *sp;
1084         char id[NCPS];
1085
1086         gsp = globlp;
1087         while (gsp) {
1088                 ip = gsp->g_strp;
1089                 getid(id, -1);
1090                 if (getnb() == '=') {
1091                         v = expr(0);
1092                         sp = lkpsym(id, 0);
1093                         if (sp == NULL) {
1094                                 fprintf(stderr,
1095                                 "No definition of symbol %s\n", id);
1096                                 lkerr++;
1097                         } else {
1098                                 if (sp->s_flag & S_DEF) {
1099                                         fprintf(stderr,
1100                                         "Redefinition of symbol %s\n", id);
1101                                         lkerr++;
1102                                         sp->s_axp = NULL;
1103                                 }
1104                                 sp->s_addr = v;
1105                                 sp->s_type |= S_DEF;
1106                         }
1107                 } else {
1108                         fprintf(stderr, "No '=' in global expression");
1109                         lkerr++;
1110                 }
1111                 gsp = gsp->g_globl;
1112         }
1113 }
1114
1115 /*)Function     FILE *  afile(fn,, ft, wf)
1116  *
1117  *              char *  fn              file specification string
1118  *              char *  ft              file type string
1119  *              int     wf              read(0)/write(1) flag
1120  *
1121  *      The function afile() opens a file for reading or writing.
1122  *              (1)     If the file type specification string ft
1123  *                      is not NULL then a file specification is
1124  *                      constructed with the file path\name in fn
1125  *                      and the extension in ft.
1126  *              (2)     If the file type specification string ft
1127  *                      is NULL then the file specification is
1128  *                      constructed from fn.  If fn does not have
1129  *                      a file type then the default .rel file
1130  *                      type is appended to the file specification.
1131  *
1132  *      afile() returns a file handle for the opened file or aborts
1133  *      the assembler on an open error.
1134  *
1135  *      local variables:
1136  *              char    fb[]            constructed file specification string
1137  *              FILE *  fp              filehandle for opened file
1138  *
1139  *      global variables:
1140  *              int     lkerr           error flag
1141  *
1142  *      functions called:
1143  *              FILE *  fopen()         c_library
1144  *              int     fprintf()       c_library
1145  *
1146  *      side effects:
1147  *              File is opened for read or write.
1148  */
1149
1150 FILE *
1151 afile(fn, ft, wf)
1152 char *fn;
1153 char *ft;
1154 {
1155         FILE *fp;
1156         char fb[PATH_MAX];
1157         char *omode = (wf ? (wf == 2 ? "a" : "w") : "r");
1158         int i;
1159
1160         /*Look backward the name path and get rid of the extension, if any*/
1161         i=strlen(fn);
1162         for(; (fn[i]!='.')&&(fn[i]!='\\')&&(fn[i]!='/')&&(i>=0); i--);
1163         if( (fn[i]=='.') && strcmp(ft, "lnk") )
1164         {
1165                 strncpy(fb, fn, i);
1166                 fb[i]=0;
1167         }
1168         else
1169         {
1170                 strcpy(fb, fn);
1171         }
1172
1173         /*Add the extension*/
1174         strcat(fb, ".");
1175         strcat(fb, strlen(ft)?ft:"rel");
1176         
1177         fp = fopen(fb, omode);
1178         if (fp==NULL)
1179         {
1180             if (strcmp(ft,"adb"))/*Do not complaint for optional adb files*/
1181                 {
1182                         fprintf(stderr, "%s: cannot %s.\n", fb, wf?"create":"open");
1183                         lkerr++;
1184             }
1185         }
1186         return (fp);
1187 }
1188
1189 /*)Function     VOID    iramsav()
1190  *
1191  *      The function iramsav() stores the size of the chip's internal RAM.
1192  *      This is used after linking to check that variable assignment to this
1193  *      dataspace didn't overflow into adjoining segments.  Variables in the
1194  *      DSEG, OSEG, and ISEG are assigned to this dataspace.
1195  *
1196  *      local variables:
1197  *              none
1198  *
1199  *      global variables:
1200  *              char    *ip             pointer into the REL file
1201  *                                              text line in ib[]
1202  *              unsigned int            size of chip's internal
1203  *                      iram_size               RAM segment
1204  *
1205  *       functions called:
1206  *              char    getnb()         lklex.c
1207  *              VOID    unget()         lklex.c
1208  *              Addr_T  expr()          lkeval.c
1209  *
1210  *      side effects:
1211  *              The iram_size may be modified.
1212  */
1213
1214 VOID
1215 iramsav()
1216 {
1217   unget(getnb());
1218   if (ip && *ip)
1219     //iram_size = atoi(ip);
1220     iram_size = expr(0);        /* evaluate size expression */
1221   else
1222     iram_size = 128;            /* Default is 128 (0x80) bytes */
1223 }
1224
1225 /*Similar to iramsav but for xram memory*/
1226 VOID
1227 xramsav()
1228 {
1229   unget(getnb());
1230   if (ip && *ip)
1231     xram_size = expr(0);        /* evaluate size expression */
1232   else
1233         xram_size = rflag?0x1000000:0x10000;
1234 }
1235
1236 /*Similar to iramsav but for code memory*/
1237 VOID
1238 codesav()
1239 {
1240   unget(getnb());
1241   if (ip && *ip)
1242     code_size = expr(0);        /* evaluate size expression */
1243   else
1244         code_size = rflag?0x1000000:0x10000;
1245 }
1246
1247
1248 /*)Function     VOID    iramcheck()
1249  *
1250  *      The function iramcheck() is used at the end of linking to check that
1251  *      the internal RAM area wasn't overflowed by too many variable
1252  *      assignments.  Variables in the DSEG, ISEG, and OSEG are assigned to
1253  *      the chip's internal RAM.
1254  *
1255  *      local variables:
1256  *              none
1257  *
1258  *      global variables:
1259  *              unsigned int            size of chip's internal
1260  *                      iram_size               RAM segment
1261  *              struct area             linked list of memory
1262  *                      *areap                  areas
1263  *
1264  *       functions called:
1265  *
1266  *      side effects:
1267  */
1268
1269 VOID
1270 iramcheck()
1271 {
1272   register unsigned int last_addr;
1273   register struct area *ap;
1274
1275   for (ap = areap; ap; ap=ap->a_ap) {
1276     if ((ap->a_size != 0) &&
1277         (!strcmp(ap->a_id, "DSEG") ||
1278          !strcmp(ap->a_id, "OSEG") ||
1279          !strcmp(ap->a_id, "ISEG")
1280         )
1281        )
1282     {
1283       last_addr = ap->a_addr + ap->a_size - 1;
1284       if (last_addr >= iram_size)
1285         fprintf(stderr,
1286                 "\nWARNING! Segment %s extends past the end\n"
1287                 "         of internal RAM.  Check map file.\n",
1288                 ap->a_id);
1289     }
1290   }
1291 }
1292
1293 char *usetxt[] = {
1294         "Startup:",
1295         "  -c   Command line input",
1296         "  -f   file[LNK] File input",
1297         "  -p   Prompt and echo of file[LNK] to stdout (default)",
1298         "  -n   No echo of file[LNK] to stdout",
1299 /*      "Usage: [-Options] file [file ...]", */
1300         "Libraries:",
1301         "  -k   Library path specification, one per -k",
1302         "  -l   Library file specification, one per -l",
1303         "Relocation:",
1304         "  -b   area base address = expression",
1305         "  -g   global symbol = expression",
1306         "Map format:",
1307         "  -m   Map output generated as file[MAP]",
1308         "  -x   Hexadecimal (default),  -d  Decimal,  -q  Octal",
1309         "Output:",
1310         "  -i   Intel Hex as file[IHX]",
1311         "  -s   Motorola S19 as file[S19]",
1312         "  -j   Produce NoICE debug as file[NOI]",
1313         "  -z   Produce SDCdb debug as file[cdb]",
1314 /*      "List:", */
1315         "  -u   Update listing file(s) with link data as file(s)[.RST]",
1316         "Miscellaneous:\n"
1317         "  -a   [iram-size] Check for internal RAM overflow",
1318         "  -v   [xram-size] Check for external RAM overflow",
1319         "  -w   [code-size] Check for code overflow",
1320         "End:",
1321         "  -e   or null line terminates input",
1322         0
1323 };
1324
1325 /*)Function     VOID    usage()
1326  *
1327  *      The function usage() outputs to the stderr device the
1328  *      assembler name and version and a list of valid assembler options.
1329  *
1330  *      local variables:
1331  *              char ** dp              pointer to an array of
1332  *                                      text string pointers.
1333  *
1334  *      global variables:
1335  *              FILE *  stderr          c_library
1336  *
1337  *      functions called:
1338  *              int     fprintf()       c_library
1339  *
1340  *      side effects:
1341  *              none
1342  */
1343
1344 VOID
1345 usage()
1346 {
1347         register char   **dp;
1348
1349         fprintf(stderr, "\nASxxxx Linker %s\n\n", VERSION);
1350         for (dp = usetxt; *dp; dp++)
1351                 fprintf(stderr, "%s\n", *dp);
1352         lkexit(1);
1353 }
1354
1355 /*)Function     VOID    copyfile()
1356  *              
1357  *              FILE    *dest           destination file
1358  *              FILE    *src            source file
1359  *
1360  *      function will copy source file to destination file
1361  *
1362  *
1363  *      functions called:
1364  *              int     fgetc()         c_library
1365  *              int     fputc()         c_library
1366  *
1367  *      side effects:
1368  *              none
1369  */
1370 VOID copyfile (dest,src)
1371 FILE *src,*dest ;
1372 {    
1373     int ch;
1374     while ((ch = fgetc(src)) != EOF) {
1375
1376         fputc(ch,dest);
1377     }
1378 }