* src/SDCCmain.c (linkEdit): Added support for passing a legacy command line through...
[fw/sdcc] / as / mcs51 / lklibr.c
1 /* lklibr.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  * With contributions for the
12  * object libraries from
13  * Ken Hornstein
14  * kenh@cmf.nrl.navy.mil
15  *
16  */
17
18 #if defined(__APPLE__) && defined(__MACH__)
19 #include <sys/types.h>
20 #include <sys/malloc.h>
21 #else
22 #include <malloc.h>
23 #endif
24 #include <stdio.h>
25 #include <string.h>
26 #include "aslink.h"
27
28 /*)Module       lklibr.c
29  *
30  *      The module lklibr.c contains the functions which
31  *      (1) specify the path(s) to library files [.LIB]
32  *      (2) specify the library file(s) [.LIB] to search
33  *      (3) search the library files for specific symbols
34  *          and link the module containing this symbol
35  *
36  *      lklibr.c contains the following functions:
37  *              VOID    addpath()
38  *              VOID    addlib()
39  *              VOID    addfile()
40  *              VOID    search()
41  *              VOID    fndsym()
42  *              VOID    library()
43  *              VOID    loadfile()
44  *
45  */
46
47 /*)Function     VOID    addpath()
48  *
49  *      The function addpath() creates a linked structure containing
50  *      the paths to various object module library files.
51  *
52  *      local variables:
53  *              lbpath  *lbph           pointer to new path structure
54  *              lbpath  *lbp            temporary pointer
55  *
56  *      global variables:
57  *              lbpath  *lbphead        The pointer to the first
58  *                                      path structure
59  *
60  *       functions called:
61  *              char    getnb()         lklex.c
62  *              VOID *  new()           lksym.c
63  *              int     strlen()        c_library
64  *              char *  strcpy()        c_library
65  *              VOID    unget()         lklex.c
66  *
67  *      side effects:
68  *              An lbpath structure may be created.
69  */
70
71 VOID
72 addpath()
73 {
74         struct lbpath *lbph, *lbp;
75
76         lbph = (struct lbpath *) new (sizeof(struct lbpath));
77         if (lbphead == NULL) {
78                 lbphead = lbph;
79         } else {
80                 lbp = lbphead;
81                 while (lbp->next)
82                         lbp = lbp->next;
83                 lbp->next = lbph;
84         }
85         unget(getnb());
86         lbph->path = (char *) new (strlen(ip)+1);
87         strcpy(lbph->path, ip);
88 }
89
90 /*)Function     VOID    addlib()
91  *
92  *      The function addlib() tests for the existance of a
93  *      library path structure to determine the method of
94  *      adding this library file to the library search structure.
95  *
96  *      This function calls the function addfile() to actually
97  *      add the library file to the search list.
98  *
99  *      local variables:
100  *              lbpath  *lbph           pointer to path structure
101  *
102  *      global variables:
103  *              lbpath  *lbphead        The pointer to the first
104  *                                      path structure
105  *
106  *       functions called:
107  *              VOID    addfile()       lklibr.c
108  *              char    getnb()         lklex.c
109  *              VOID    unget()         lklex.c
110  *
111  *      side effects:
112  *              The function addfile() may add the file to
113  *              the library search list.
114  */
115
116 VOID
117 addlib()
118 {
119         struct lbpath *lbph;
120
121         unget(getnb());
122
123         if (lbphead == NULL) {
124                 addfile(NULL,ip);
125                 return;
126         }       
127         for (lbph=lbphead; lbph; lbph=lbph->next) {
128                 addfile(lbph->path,ip);
129         }
130 }
131
132 /*)Function     VOID    addfile(path,libfil)
133  *
134  *              char    *path           library path specification
135  *              char    *libfil         library file specification
136  *
137  *      The function addfile() searches for the library file
138  *      by concatenating the path and libfil specifications.
139  *      if the library is found, an lbname structure is created
140  *      and linked to any previously defined structures.  This
141  *      linked list is used by the function fndsym() to attempt
142  *      to find any undefined symbols.
143  *
144  *      The function does not give report an error on invalid
145  *      path / file specifications or if the file is not found.
146  *
147  *      local variables:
148  *              lbname  *lbnh           pointer to new name structure
149  *              lbname  *lbn            temporary pointer
150  *
151  *      global variables:
152  *              lbname  *lbnhead        The pointer to the first
153  *                                      path structure
154  *
155  *       functions called:
156  *              char    getnb()         lklex.c
157  *              VOID *  new()           lksym.c
158  *              int     strlen()        c_library
159  *              char *  strcpy()        c_library
160  *              VOID    unget()         lklex.c
161  *
162  *      side effects:
163  *              An lbname structure may be created.
164  */
165
166 VOID
167 addfile(path,libfil)
168 char *path;
169 char *libfil;
170 {
171         FILE *fp;
172         char *str;
173         struct lbname *lbnh, *lbn;
174
175         if ((path != NULL) && (strchr(libfil,':') == NULL)){
176                 str = (char *) new (strlen(path) + strlen(libfil) + 6);
177                 strcpy(str,path);
178 #ifdef  OTHERSYSTEM
179                 if (str[strlen(str)-1] != '/') {
180                         strcat(str,"/");
181                 }
182 #endif
183         } else {
184                 str = (char *) new (strlen(libfil) + 5);
185         }
186 #ifdef  OTHERSYSTEM
187         if (libfil[0] == '/') { libfil++; }
188 #endif
189         strcat(str,libfil);
190         if(strchr(libfil,FSEPX) == NULL) {
191                 sprintf(&str[strlen(str)], "%clib", FSEPX);
192         }
193         if ((fp = fopen(str, "r")) != NULL) {
194                 fclose(fp);
195                 lbnh = (struct lbname *) new (sizeof(struct lbname));
196                 if (lbnhead == NULL) {
197                         lbnhead = lbnh;
198                 } else {
199                         lbn = lbnhead;
200                         while (lbn->next)
201                                 lbn = lbn->next;
202                         lbn->next = lbnh;
203                 }
204                 if ((path != NULL) && (strchr(libfil,':') == NULL)){
205                         lbnh->path = path;
206                 }
207                 lbnh->libfil = (char *) new (strlen(libfil) + 1);
208                 strcpy(lbnh->libfil,libfil);
209                 lbnh->libspc = str;
210         } else {
211                 free(str);
212         }
213 }
214
215 /*)Function     VOID    search()
216  *
217  *      The function search() looks through all the symbol tables
218  *      at the end of pass 1.  If any undefined symbols are found
219  *      then the function fndsym() is called. Function fndsym()
220  *      searches any specified library files to automagically
221  *      import the object modules containing the needed symbol.
222  *
223  *      After a symbol is found and imported by the function
224  *      fndsym() the symbol tables are again searched.  The
225  *      symbol tables are search until no more symbols can be
226  *      resolved within the library files.  This ensures that
227  *      back references from one library module to another are
228  *      also resolved.
229  *
230  *      local variables:
231  *              int     i               temporary counter
232  *              sym     *sp             pointer to a symbol structure
233  *              int     symfnd          found a symbol flag
234  *
235  *      global variables:
236  *              sym     *symhash[]      array of pointers to symbol tables
237  *
238  *       functions called:
239  *              int     fndsym()        lklibr.c
240  *
241  *      side effects:
242  *              If a symbol is found then the library object module
243  *              containing the symbol will be imported and linked.
244  */
245
246 VOID
247 search()
248 {
249         register struct sym *sp;
250         register int i,symfnd;
251
252         /*
253          * Look for undefined symbols.  Keep
254          * searching until no more symbols are resolved.
255          */
256         symfnd = 1;
257         while (symfnd) {
258                 symfnd = 0;
259                 /*
260                  * Look through all the symbols
261                  */
262                 for (i=0; i<NHASH; ++i) {
263                         sp = symhash[i];
264                         while (sp) {
265                                 /* If we find an undefined symbol
266                                  * (one where S_DEF is not set), then
267                                  * try looking for it.  If we find it
268                                  * in any of the libraries then
269                                  * increment symfnd.  This will force
270                                  * another pass of symbol searching and
271                                  * make sure that back references work.
272                                  */
273                                 if ((sp->s_type & S_DEF) == 0) {
274                                         if (fndsym(sp->s_id)) {
275                                                 symfnd++;
276                                         }
277                                 }
278                                 sp = sp->s_sp;
279                         }
280                 }
281         }
282 }
283
284 /*)Function     VOID    fndsym(name)
285  *
286  *              char    *name           symbol name to find
287  *
288  *      The function fndsym() searches through all combinations of the
289  *      library path specifications (input by the -k option) and the
290  *      library file specifications (input by the -l option) that
291  *      lead to an existing file.
292  *
293  *      The file specicifation may be formed in one of two ways:
294  *
295  *      (1)     If the library file contained an absolute
296  *              path/file specification then this becomes filspc.
297  *              (i.e. C:\...)
298  *
299  *      (2)     If the library file contains a relative path/file
300  *              specification then the concatenation of the path
301  *              and this file specification becomes filspc.
302  *              (i.e. \...)
303  *
304  *      The structure lbfile is created for the first library
305  *      object file which contains the definition for the
306  *      specified undefined symbol.
307  *
308  *      If the library file [.LIB] contains file specifications for
309  *      non existant files, no errors are returned.
310  *
311  *      local variables:
312  *              char    buf[]           [.REL] file input line
313  *              char    c               [.REL] file input character
314  *              FILE    *fp             file handle for object file
315  *              lbfile  *lbf            temporary pointer
316  *              lbfile  *lbfh           pointer to lbfile structure
317  *              FILE    *libfp          file handle for library file
318  *              lbname  *lbnh           pointer to lbname structure
319  *              char    *path           file specification path
320  *              char    relfil[]        [.REL] file specification
321  *              char    *str            combined path and file specification
322  *              char    symname[]       [.REL] file symbol string
323  *
324  *      global variables:
325  *              lbname  *lbnhead        The pointer to the first
326  *                                      name structure
327  *              lbfile  *lbfhead        The pointer to the first
328  *                                      file structure
329  *
330  *       functions called:
331  *              int     fclose()        c_library
332  *              int     fgets()         c_library
333  *              FILE    *fopen()        c_library
334  *              VOID    free()          c_library
335  *              char    getnb()         lklex.c
336  *              VOID    lkexit()        lkmain.c
337  *              VOID    loadfile()      lklibr.c
338  *              VOID *  new()           lksym.c
339  *              char *  sprintf()       c_library
340  *              int     sscanf()        c_library
341  *              char *  strcat()        c_library
342  *              char *  strchr()        c_library
343  *              char *  strcpy()        c_library
344  *              int     strlen()        c_library
345  *              int     strncmp()       c_library
346  *              VOID    unget()         lklex.c
347  *
348  *      side effects:
349  *              If the symbol is found then a new lbfile structure
350  *              is created and added to the linked list of lbfile
351  *              structures.  The file containing the found symbol
352  *              is linked.
353  */
354
355 int
356 fndsym(name)
357 char *name;
358 {
359         FILE *libfp, *fp;
360         struct lbname *lbnh;
361         struct lbfile *lbfh, *lbf;
362         char relfil[NINPUT+2];
363         char buf[NINPUT+2];
364         char symname[NINPUT];
365         char *path,*str;
366         char c;
367
368         /*
369          * Search through every library in the linked list "lbnhead".
370          */
371
372 /*1*/   for (lbnh=lbnhead; lbnh; lbnh=lbnh->next) {
373                 if ((libfp = fopen(lbnh->libspc, "r")) == NULL) {
374                         fprintf(stderr, "Cannot open library file %s\n",
375                                 lbnh->libspc);
376                         lkexit(1);
377                 }
378                 path = lbnh->path;
379
380                 /*
381                  * Read in a line from the library file.
382                  * This is the relative file specification
383                  * for a .REL file in this library.
384                  */
385
386 /*2*/           while (fgets(relfil, NINPUT, libfp) != NULL) {
387                     relfil[NINPUT+1] = '\0';
388                     chop_crlf(relfil);
389                     if (path != NULL) {
390                         str = (char *) new (strlen(path)+strlen(relfil)+6);
391                         strcpy(str,path);
392 #ifdef  OTHERSYSTEM
393                         if (str[strlen(str)-1] != '/') {
394                                 strcat(str,"/");
395                         }
396 #endif
397                     } else {
398                         str = (char *) new (strlen(relfil) + 5);
399                     }
400                     if (relfil[0] == '\\') {
401                         strcat(str,relfil+1);
402                     } else {
403                         strcat(str,relfil);
404                     }
405                     if(strchr(relfil,FSEPX) == NULL) {
406                         sprintf(&str[strlen(str)], "%crel", FSEPX);
407                     }
408 /*3*/               if ((fp = fopen(str, "r")) != NULL) {
409
410                         /*
411                          * Read in the object file.  Look for lines that
412                          * begin with "S" and end with "D".  These are
413                          * symbol table definitions.  If we find one, see
414                          * if it is our symbol.  Make sure we only read in
415                          * our object file and don't go into the next one.
416                          */
417                         
418 /*4*/                   while (fgets(buf, NINPUT, fp) != NULL) {
419
420                         buf[NINPUT+1] = '\0';
421                         chop_crlf(buf);
422
423                         /*
424                          * Skip everything that's not a symbol record.
425                          */
426                         if (buf[0] != 'S')
427                                 continue;
428
429                         /*
430                          * When a 'T line' is found terminate file scan.
431                          * All 'S line's preceed 'T line's in .REL files.
432                          */
433                         if (buf[0] == 'T')
434                                 break;
435
436                         sscanf(buf, "S %s %c", symname, &c);
437
438                         /*
439                          * If we find a symbol definition for the
440                          * symbol we're looking for, load in the
441                          * file and add it to lbfhead so it gets
442                          * loaded on pass number 2.
443                          */
444 /*5*/                   if (strncmp(symname, name, NCPS) == 0 && c == 'D') {
445
446                         lbfh = (struct lbfile *) new (sizeof(struct lbfile));
447                         if (lbfhead == NULL) {
448                                 lbfhead = lbfh;
449                         } else {
450                                 lbf = lbfhead;
451                                 while (lbf->next)
452                                         lbf = lbf->next;
453                                 lbf->next = lbfh;
454                         }
455                         lbfh->libspc = lbnh->libspc;
456                         lbfh->filspc = str;
457                         lbfh->relfil = (char *) new (strlen(relfil) + 1);
458                         strcpy(lbfh->relfil,relfil);
459                         fclose(fp);
460                         fclose(libfp);                 
461                         /* if cdb information required & cdb file present */
462                         if (dflag && dfp) {
463                             FILE *xfp = afile(str,"cdb",0);
464                             if (xfp) {
465                                 copyfile(dfp,xfp);
466                                 fclose(xfp);
467                             }
468                         }
469                         loadfile(str);
470                         return (1);
471
472 /*5*/                   }
473
474 /*4*/                   }
475                     fclose(fp);
476 /*3*/               }
477
478                     free(str);
479 /*2*/           }
480                 fclose(libfp);
481 /*1*/   }
482         return(0);
483 }
484
485 /*)Function     VOID    library()
486  *
487  *      The function library() links all the library object files
488  *      contained in the lbfile structures.
489  *
490  *      local variables:
491  *              lbfile  *lbfh           pointer to lbfile structure
492  *
493  *      global variables:
494  *              lbfile  *lbfhead        pointer to first lbfile structure
495  *
496  *       functions called:
497  *              VOID    loadfile        lklibr.c
498  *
499  *      side effects:
500  *              Links all files contained in the lbfile structures.
501  */
502
503 VOID
504 library()
505 {
506         struct lbfile *lbfh;
507
508         for (lbfh=lbfhead; lbfh; lbfh=lbfh->next) {
509                 loadfile(lbfh->filspc);
510         }
511 }
512
513 /*)Function     VOID    loadfile(filspc)
514  *
515  *              char    *filspc         library object file specification
516  *
517  *      The function loadfile() links the library object module.
518  *
519  *      local variables:
520  *              FILE    *fp             file handle
521  *              int     i               input line length
522  *              char    str[]           file input line
523  *
524  *      global variables:
525  *              char    *ip             pointer to linker input string
526  *
527  *       functions called:
528  *              int     fclose()        c_library
529  *              int     fgets()         c_library
530  *              FILE *  fopen()         c_library
531  *              VOID    link_main()     lkmain.c
532  *              int     strlen()        c_library
533  *
534  *      side effects:
535  *              If file exists it is linked.
536  */
537
538 VOID
539 loadfile(filspc)
540 char *filspc;
541 {
542         FILE *fp;
543         char str[NINPUT+2];
544
545         if ((fp = fopen(filspc,"r")) != NULL) {
546                 while (fgets(str, NINPUT, fp) != NULL) {
547                         str[NINPUT+1] = '\0';
548                         chop_crlf(str);
549                         ip = str;
550                         link_main();
551                 }
552                 fclose(fp);
553         }
554 }