b4e287ef8a308d9796da06198b6b947ada480bbb
[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                 fprintf(stderr,"library file %s\n",str);
211         } else {
212                 free(str);
213         }
214 }
215
216 /*)Function     VOID    search()
217  *
218  *      The function search() looks through all the symbol tables
219  *      at the end of pass 1.  If any undefined symbols are found
220  *      then the function fndsym() is called. Function fndsym()
221  *      searches any specified library files to automagically
222  *      import the object modules containing the needed symbol.
223  *
224  *      After a symbol is found and imported by the function
225  *      fndsym() the symbol tables are again searched.  The
226  *      symbol tables are search until no more symbols can be
227  *      resolved within the library files.  This ensures that
228  *      back references from one library module to another are
229  *      also resolved.
230  *
231  *      local variables:
232  *              int     i               temporary counter
233  *              sym     *sp             pointer to a symbol structure
234  *              int     symfnd          found a symbol flag
235  *
236  *      global variables:
237  *              sym     *symhash[]      array of pointers to symbol tables
238  *
239  *       functions called:
240  *              int     fndsym()        lklibr.c
241  *
242  *      side effects:
243  *              If a symbol is found then the library object module
244  *              containing the symbol will be imported and linked.
245  */
246
247 VOID
248 search()
249 {
250         register struct sym *sp;
251         register int i,symfnd;
252
253         /*
254          * Look for undefined symbols.  Keep
255          * searching until no more symbols are resolved.
256          */
257         symfnd = 1;
258         while (symfnd) {
259                 symfnd = 0;
260                 /*
261                  * Look through all the symbols
262                  */
263                 for (i=0; i<NHASH; ++i) {
264                         sp = symhash[i];
265                         while (sp) {
266                                 /* If we find an undefined symbol
267                                  * (one where S_DEF is not set), then
268                                  * try looking for it.  If we find it
269                                  * in any of the libraries then
270                                  * increment symfnd.  This will force
271                                  * another pass of symbol searching and
272                                  * make sure that back references work.
273                                  */
274                                 if ((sp->s_type & S_DEF) == 0) {
275                                         if (fndsym(sp->s_id)) {
276                                                 symfnd++;
277                                         }
278                                 }
279                                 sp = sp->s_sp;
280                         }
281                 }
282         }
283 }
284
285 /*)Function     VOID    fndsym(name)
286  *
287  *              char    *name           symbol name to find
288  *
289  *      The function fndsym() searches through all combinations of the
290  *      library path specifications (input by the -k option) and the
291  *      library file specifications (input by the -l option) that
292  *      lead to an existing file.
293  *
294  *      The file specicifation may be formed in one of two ways:
295  *
296  *      (1)     If the library file contained an absolute
297  *              path/file specification then this becomes filspc.
298  *              (i.e. C:\...)
299  *
300  *      (2)     If the library file contains a relative path/file
301  *              specification then the concatenation of the path
302  *              and this file specification becomes filspc.
303  *              (i.e. \...)
304  *
305  *      The structure lbfile is created for the first library
306  *      object file which contains the definition for the
307  *      specified undefined symbol.
308  *
309  *      If the library file [.LIB] contains file specifications for
310  *      non existant files, no errors are returned.
311  *
312  *      local variables:
313  *              char    buf[]           [.REL] file input line
314  *              char    c               [.REL] file input character
315  *              FILE    *fp             file handle for object file
316  *              lbfile  *lbf            temporary pointer
317  *              lbfile  *lbfh           pointer to lbfile structure
318  *              FILE    *libfp          file handle for library file
319  *              lbname  *lbnh           pointer to lbname structure
320  *              char    *path           file specification path
321  *              char    relfil[]        [.REL] file specification
322  *              char    *str            combined path and file specification
323  *              char    symname[]       [.REL] file symbol string
324  *
325  *      global variables:
326  *              lbname  *lbnhead        The pointer to the first
327  *                                      name structure
328  *              lbfile  *lbfhead        The pointer to the first
329  *                                      file structure
330  *
331  *       functions called:
332  *              int     fclose()        c_library
333  *              int     fgets()         c_library
334  *              FILE    *fopen()        c_library
335  *              VOID    free()          c_library
336  *              char    getnb()         lklex.c
337  *              VOID    lkexit()        lkmain.c
338  *              VOID    loadfile()      lklibr.c
339  *              VOID *  new()           lksym.c
340  *              char *  sprintf()       c_library
341  *              int     sscanf()        c_library
342  *              char *  strcat()        c_library
343  *              char *  strchr()        c_library
344  *              char *  strcpy()        c_library
345  *              int     strlen()        c_library
346  *              int     strncmp()       c_library
347  *              VOID    unget()         lklex.c
348  *
349  *      side effects:
350  *              If the symbol is found then a new lbfile structure
351  *              is created and added to the linked list of lbfile
352  *              structures.  The file containing the found symbol
353  *              is linked.
354  */
355
356 int
357 fndsym(name)
358 char *name;
359 {
360         FILE *libfp, *fp;
361         struct lbname *lbnh;
362         struct lbfile *lbfh, *lbf;
363         char relfil[NINPUT+2];
364         char buf[NINPUT+2];
365         char symname[NINPUT];
366         char *path,*str;
367         char c;
368
369         /*
370          * Search through every library in the linked list "lbnhead".
371          */
372
373 /*1*/   for (lbnh=lbnhead; lbnh; lbnh=lbnh->next) {
374                 if ((libfp = fopen(lbnh->libspc, "r")) == NULL) {
375                         fprintf(stderr, "Cannot open library file %s\n",
376                                 lbnh->libspc);
377                         lkexit(1);
378                 }
379                 path = lbnh->path;
380
381                 /*
382                  * Read in a line from the library file.
383                  * This is the relative file specification
384                  * for a .REL file in this library.
385                  */
386
387 /*2*/           while (fgets(relfil, NINPUT, libfp) != NULL) {
388                     relfil[NINPUT+1] = '\0';
389                     chop_crlf(relfil);
390                     if (path != NULL) {
391                         str = (char *) new (strlen(path)+strlen(relfil)+6);
392                         strcpy(str,path);
393 #ifdef  OTHERSYSTEM
394                         if (str[strlen(str)-1] != '/') {
395                                 strcat(str,"/");
396                         }
397 #endif
398                     } else {
399                         str = (char *) new (strlen(relfil) + 5);
400                     }
401                     if (relfil[0] == '\\') {
402                         strcat(str,relfil+1);
403                     } else {
404                         strcat(str,relfil);
405                     }
406                     if(strchr(relfil,FSEPX) == NULL) {
407                         sprintf(&str[strlen(str)], "%crel", FSEPX);
408                     }
409 /*3*/               if ((fp = fopen(str, "r")) != NULL) {
410
411                         /*
412                          * Read in the object file.  Look for lines that
413                          * begin with "S" and end with "D".  These are
414                          * symbol table definitions.  If we find one, see
415                          * if it is our symbol.  Make sure we only read in
416                          * our object file and don't go into the next one.
417                          */
418                         
419 /*4*/                   while (fgets(buf, NINPUT, fp) != NULL) {
420
421                         buf[NINPUT+1] = '\0';
422                         chop_crlf(buf);
423
424                         /*
425                          * Skip everything that's not a symbol record.
426                          */
427                         if (buf[0] != 'S')
428                                 continue;
429
430                         /*
431                          * When a 'T line' is found terminate file scan.
432                          * All 'S line's preceed 'T line's in .REL files.
433                          */
434                         if (buf[0] == 'T')
435                                 break;
436
437                         sscanf(buf, "S %s %c", symname, &c);
438
439                         /*
440                          * If we find a symbol definition for the
441                          * symbol we're looking for, load in the
442                          * file and add it to lbfhead so it gets
443                          * loaded on pass number 2.
444                          */
445 /*5*/                   if (strncmp(symname, name, NCPS) == 0 && c == 'D') {
446
447                         lbfh = (struct lbfile *) new (sizeof(struct lbfile));
448                         if (lbfhead == NULL) {
449                                 lbfhead = lbfh;
450                         } else {
451                                 lbf = lbfhead;
452                                 while (lbf->next)
453                                         lbf = lbf->next;
454                                 lbf->next = lbfh;
455                         }
456                         lbfh->libspc = lbnh->libspc;
457                         lbfh->filspc = str;
458                         lbfh->relfil = (char *) new (strlen(relfil) + 1);
459                         strcpy(lbfh->relfil,relfil);
460                         fclose(fp);
461                         fclose(libfp);                 
462                         /* if cdb information required & cdb file present */
463                         if (dflag && dfp) {
464                             FILE *xfp = afile(str,"cdb",0);
465                             if (xfp) {
466                                 copyfile(dfp,xfp);
467                                 fclose(xfp);
468                             }
469                         }
470                         loadfile(str);
471                         return (1);
472
473 /*5*/                   }
474
475 /*4*/                   }
476                     fclose(fp);
477 /*3*/               }
478
479                     free(str);
480 /*2*/           }
481                 fclose(libfp);
482 /*1*/   }
483         return(0);
484 }
485
486 /*)Function     VOID    library()
487  *
488  *      The function library() links all the library object files
489  *      contained in the lbfile structures.
490  *
491  *      local variables:
492  *              lbfile  *lbfh           pointer to lbfile structure
493  *
494  *      global variables:
495  *              lbfile  *lbfhead        pointer to first lbfile structure
496  *
497  *       functions called:
498  *              VOID    loadfile        lklibr.c
499  *
500  *      side effects:
501  *              Links all files contained in the lbfile structures.
502  */
503
504 VOID
505 library()
506 {
507         struct lbfile *lbfh;
508
509         for (lbfh=lbfhead; lbfh; lbfh=lbfh->next) {
510                 loadfile(lbfh->filspc);
511         }
512 }
513
514 /*)Function     VOID    loadfile(filspc)
515  *
516  *              char    *filspc         library object file specification
517  *
518  *      The function loadfile() links the library object module.
519  *
520  *      local variables:
521  *              FILE    *fp             file handle
522  *              int     i               input line length
523  *              char    str[]           file input line
524  *
525  *      global variables:
526  *              char    *ip             pointer to linker input string
527  *
528  *       functions called:
529  *              int     fclose()        c_library
530  *              int     fgets()         c_library
531  *              FILE *  fopen()         c_library
532  *              VOID    link_main()     lkmain.c
533  *              int     strlen()        c_library
534  *
535  *      side effects:
536  *              If file exists it is linked.
537  */
538
539 VOID
540 loadfile(filspc)
541 char *filspc;
542 {
543         FILE *fp;
544         char str[NINPUT+2];
545
546         if ((fp = fopen(filspc,"r")) != NULL) {
547                 while (fgets(str, NINPUT, fp) != NULL) {
548                         str[NINPUT+1] = '\0';
549                         chop_crlf(str);
550                         ip = str;
551                         link_main();
552                 }
553                 fclose(fp);
554         }
555 }