Generate a warning when a library file is not found.
[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 #define EQ(A,B) !strcmp((A),(B))
19 #define MAXLINE 254 /*when using fgets*/
20
21 #if defined(__APPLE__) && defined(__MACH__)
22 #include <sys/types.h>
23 #include <sys/malloc.h>
24 #else
25 #include <malloc.h>
26 #endif
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include "aslink.h"
31
32 /*)Module       lklibr.c
33  *
34  *      The module lklibr.c contains the functions which
35  *      (1) specify the path(s) to library files [.LIB]
36  *      (2) specify the library file(s) [.LIB] to search
37  *      (3) search the library files for specific symbols
38  *          and link the module containing this symbol
39  *
40  *      lklibr.c contains the following functions:
41  *              VOID    addpath()
42  *              VOID    addlib()
43  *              VOID    addfile()
44  *              VOID    search()
45  *              VOID    fndsym()
46  *              VOID    library()
47  *              VOID    loadfile()
48  *
49  */
50
51 /*)Function     VOID    addpath()
52  *
53  *      The function addpath() creates a linked structure containing
54  *      the paths to various object module library files.
55  *
56  *      local variables:
57  *              lbpath  *lbph           pointer to new path structure
58  *              lbpath  *lbp            temporary pointer
59  *
60  *      global variables:
61  *              lbpath  *lbphead        The pointer to the first
62  *                                      path structure
63  *
64  *       functions called:
65  *              char    getnb()         lklex.c
66  *              VOID *  new()           lksym.c
67  *              int     strlen()        c_library
68  *              char *  strcpy()        c_library
69  *              VOID    unget()         lklex.c
70  *
71  *      side effects:
72  *              An lbpath structure may be created.
73  */
74
75 VOID
76 addpath()
77 {
78         struct lbpath *lbph, *lbp;
79
80         lbph = (struct lbpath *) new (sizeof(struct lbpath));
81         if (lbphead == NULL) {
82                 lbphead = lbph;
83         } else {
84                 lbp = lbphead;
85                 while (lbp->next)
86                         lbp = lbp->next;
87                 lbp->next = lbph;
88         }
89         unget(getnb());
90         lbph->path = (char *) new (strlen(ip)+1);
91         strcpy(lbph->path, ip);
92 }
93
94 /*)Function     VOID    addlib()
95  *
96  *      The function addlib() tests for the existance of a
97  *      library path structure to determine the method of
98  *      adding this library file to the library search structure.
99  *
100  *      This function calls the function addfile() to actually
101  *      add the library file to the search list.
102  *
103  *      local variables:
104  *              lbpath  *lbph           pointer to path structure
105  *
106  *      global variables:
107  *              lbpath  *lbphead        The pointer to the first
108  *                                      path structure
109  *      ip a pointer to the library name
110  *
111  *       functions called:
112  *              VOID    addfile()       lklibr.c
113  *              char    getnb()         lklex.c
114  *              VOID    unget()         lklex.c
115  *
116  *      side effects:
117  *              The function addfile() may add the file to
118  *              the library search list.
119  */
120
121 VOID
122 addlib()
123 {
124         struct lbpath *lbph;
125     int foundcount=0;
126
127         unget(getnb());
128
129         if (lbphead == NULL) {
130                 addfile(NULL,ip);
131                 return;
132         }       
133         for (lbph=lbphead; lbph; lbph=lbph->next) {
134                 foundcount+=addfile(lbph->path,ip);
135         }
136     if(foundcount==0)
137     {
138         printf("?ASlink-Warning-Couldn't find library '%s'\n", ip);
139     }
140 }
141
142 /*)Function     int     addfile(path,libfil)
143  *
144  *              char    *path           library path specification
145  *              char    *libfil         library file specification
146  *
147  *      The function addfile() searches for the library file
148  *      by concatenating the path and libfil specifications.
149  *      if the library is found, an lbname structure is created
150  *      and linked to any previously defined structures.  This
151  *      linked list is used by the function fndsym() to attempt
152  *      to find any undefined symbols.
153  *
154  *      The function does not give report an error on invalid
155  *      path / file specifications or if the file is not found.
156  *
157  *      local variables:
158  *              lbname  *lbnh           pointer to new name structure
159  *              lbname  *lbn            temporary pointer
160  *
161  *      global variables:
162  *              lbname  *lbnhead        The pointer to the first
163  *                                      path structure
164  *
165  *       functions called:
166  *              char    getnb()         lklex.c
167  *              VOID *  new()           lksym.c
168  *              int     strlen()        c_library
169  *              char *  strcpy()        c_library
170  *              VOID    unget()         lklex.c
171  *
172  *      side effects:
173  *              An lbname structure may be created.
174  *
175  *  return:
176  *      1: the library was found
177  *      0: the library was not found
178  */
179
180 int addfile(char * path, char * libfil)
181 {
182         FILE *fp;
183         char *str;
184         struct lbname *lbnh, *lbn;
185 #ifdef  OTHERSYSTEM
186     int libfilinc=0;
187 #endif
188
189         if (path != NULL)
190     {
191                 str = (char *) new (strlen(path) + strlen(libfil) + 6);
192                 strcpy(str,path);
193 #ifdef  OTHERSYSTEM
194                 if (str[strlen(str)-1] != '/')
195         {
196                         strcat(str,"/");
197                 }
198 #endif
199         }
200     else
201     {
202                 str = (char *) new (strlen(libfil) + 5);
203         }
204
205 #ifdef  OTHERSYSTEM
206         if (libfil[0] == '/')
207     {
208         libfil++;
209         libfilinc=1;
210     }
211 #endif
212         
213     strcat(str, libfil);
214         if(strchr(libfil, FSEPX) == NULL)
215     {
216                 sprintf(&str[strlen(str)], "%clib", FSEPX);
217         }
218
219     fp=fopen(str, "r");
220     if(fp == NULL)
221     {
222         /*Ok, that didn't work.  Try with the 'libfil' name only*/
223 #ifdef  OTHERSYSTEM
224         if(libfilinc) libfil--;
225 #endif
226         fp=fopen(libfil, "r");
227         if(fp != NULL) 
228         {
229             /*Bingo!  'libfil' is the absolute path of the library*/
230             strcpy(str, libfil);
231             path=NULL;/*This way 'libfil' and 'path' will be rebuilt from 'str'*/
232         }
233     }
234
235     if(path==NULL)
236     {
237         /*'path' can not be null since it is needed to find the '.o' files associated with
238         the library.  So, get 'path' from 'str' and then chop it off and recreate 'libfil'.
239         That way putting 'path' and 'libfil' together will result into the original filepath
240         as contained in 'str'.*/
241         int j;
242         path = (char *) new (strlen(str));
243         strcpy(path, str);
244         for(j=strlen(path)-1; j>=0; j--)
245         {
246             if((path[j]=='\\')||(path[j]=='/'))
247             {
248                 strcpy(libfil, &path[j+1]);
249                 path[j+1]=0;
250                 break;
251             }
252         }
253         if(j<=0) path[0]=0;
254     }
255
256         if (fp != NULL)
257     {
258                 fclose(fp);
259                 lbnh = (struct lbname *) new (sizeof(struct lbname));
260                 if (lbnhead == NULL)
261         {
262                         lbnhead = lbnh;
263                 }
264         else
265         {
266                         lbn = lbnhead;
267                         while (lbn->next)
268                                 lbn = lbn->next;
269                         lbn->next = lbnh;
270                 }
271                 
272         lbnh->path = path;
273                 lbnh->libfil = (char *) new (strlen(libfil) + 1);
274                 strcpy(lbnh->libfil,libfil);
275                 lbnh->libspc = str;
276         return 1;
277         } 
278     else 
279     {
280                 free(str);
281         return 0;
282         }
283 }
284
285 /*)Function     VOID    search()
286  *
287  *      The function search() looks through all the symbol tables
288  *      at the end of pass 1.  If any undefined symbols are found
289  *      then the function fndsym() is called. Function fndsym()
290  *      searches any specified library files to automagically
291  *      import the object modules containing the needed symbol.
292  *
293  *      After a symbol is found and imported by the function
294  *      fndsym() the symbol tables are again searched.  The
295  *      symbol tables are search until no more symbols can be
296  *      resolved within the library files.  This ensures that
297  *      back references from one library module to another are
298  *      also resolved.
299  *
300  *      local variables:
301  *              int     i               temporary counter
302  *              sym     *sp             pointer to a symbol structure
303  *              int     symfnd          found a symbol flag
304  *
305  *      global variables:
306  *              sym     *symhash[]      array of pointers to symbol tables
307  *
308  *       functions called:
309  *              int     fndsym()        lklibr.c
310  *
311  *      side effects:
312  *              If a symbol is found then the library object module
313  *              containing the symbol will be imported and linked.
314  */
315
316 VOID
317 search()
318 {
319         register struct sym *sp;
320         register int i,symfnd;
321
322         /*
323          * Look for undefined symbols.  Keep
324          * searching until no more symbols are resolved.
325          */
326         symfnd = 1;
327         while (symfnd) {
328                 symfnd = 0;
329                 /*
330                  * Look through all the symbols
331                  */
332                 for (i=0; i<NHASH; ++i) {
333                         sp = symhash[i];
334                         while (sp) {
335                                 /* If we find an undefined symbol
336                                  * (one where S_DEF is not set), then
337                                  * try looking for it.  If we find it
338                                  * in any of the libraries then
339                                  * increment symfnd.  This will force
340                                  * another pass of symbol searching and
341                                  * make sure that back references work.
342                                  */
343                                 if ((sp->s_type & S_DEF) == 0) {
344                                         if (fndsym(sp->s_id)) {
345                                                 symfnd++;
346                                         }
347                                 }
348                                 sp = sp->s_sp;
349                         }
350                 }
351         }
352 }
353
354 /*Load a .rel file embedded in a sdcclib file*/
355 void LoadRel(FILE * libfp, char * ModName)
356 {
357         char str[NINPUT+2];
358         int state=0;
359
360         while (fgets(str, NINPUT, libfp) != NULL)
361         {
362                 str[NINPUT+1] = '\0';
363                 chop_crlf(str);
364                 switch(state)
365                 {
366                         case 0:
367                                 if(EQ(str, "<FILE>"))
368                                 {
369                                         fgets(str, NINPUT, libfp);
370                                         str[NINPUT+1] = '\0';
371                                         chop_crlf(str);
372                                         if(EQ(str, ModName)) state=1;
373                                         else
374                                         {
375                                                 printf("Bad offset in library file str=%s, Modname=%s\n", str, ModName);
376                                                 lkexit(1);
377                                         }
378                                 }
379                         break;
380                         case 1:
381                                 if(EQ(str, "<REL>")) state=2;
382                         break;
383                         case 2:
384                                 if(EQ(str, "</REL>")) return;
385                                 ip = str;
386                                 link_main();
387                         break;
388                 }
389         }
390 }
391
392 /*Load an .adb file embedded in a sdcclib file.  If there is
393 something between <ADB> and </ADB> returns 1, otherwise returns 0.
394 This way the aomf51 will not have uselless empty modules. */
395
396 int LoadAdb(FILE * libfp)
397 {
398         char str[MAXLINE+1];
399         int state=0;
400         int ToReturn=0;
401
402         while (fgets(str, MAXLINE, libfp) != NULL)
403         {
404                 str[NINPUT+1] = '\0';
405                 chop_crlf(str);
406                 switch(state)
407                 {
408                         case 0:
409                                 if(EQ(str, "<ADB>")) state=1;
410                         break;
411                         case 1:
412                                 if(EQ(str, "</ADB>")) return ToReturn;
413                                 fprintf(dfp, "%s\n", str);
414                                 ToReturn=1;
415                         break;
416                 }
417         }
418         return ToReturn;
419 }
420
421 /*Check for a symbol in a SDCC library.  If found, add the embedded .rel and
422 .adb files from the library.  The library must be created with the SDCC
423 librarian 'sdcclib' since the linking process depends on the correct file offsets
424 embedded in the library file.*/
425
426 int SdccLib(char * PathLib, FILE * libfp, char * DirLib, char * SymName)
427 {
428         struct lbfile *lbfh, *lbf;
429         char ModName[NCPS]="";
430         char FLine[MAXLINE+1];
431         int state=0;
432         long IndexOffset=0, FileOffset;
433
434         while(!feof(libfp))
435     {
436         FLine[0]=0;
437         fgets(FLine, MAXLINE, libfp);
438         chop_crlf(FLine);
439
440         switch(state)
441         {
442             case 0:
443                 if(EQ(FLine, "<INDEX>"))
444                 {
445                                         /*The next line has the size of the index*/
446                     FLine[0]=0;
447                     fgets(FLine, MAXLINE, libfp);
448                     chop_crlf(FLine);
449                                         IndexOffset=atol(FLine);
450                                         state=1;
451                 }
452             break;
453             case 1:
454                 if(EQ(FLine, "<MODULE>"))
455                                 {
456                                         /*The next line has the name of the module and the offset
457                                         of the corresponding embedded file in the library*/
458                     FLine[0]=0;
459                     fgets(FLine, MAXLINE, libfp);
460                     chop_crlf(FLine);
461                                         sscanf(FLine, "%s %ld", ModName, &FileOffset);
462                                         state=2;
463                                 }
464                 else if(EQ(FLine, "</INDEX>"))
465                                 {
466                                         /*Reached the end of the index.  The symbol is not in this library.*/
467                                         return 0;
468                                 }
469             break;
470             case 2:
471                 if(EQ(FLine, "</MODULE>"))
472                                 {
473                                         /*The symbol is not in this module, try the next one*/
474                     state=1;
475                                 }
476                 else
477                                 {
478                                         /*Check if this is the symbol we are looking for.*/
479                                         if (strncmp(SymName, FLine, NCPS)==0)
480                                         {
481                                                 /*The symbol is in this module.*/
482
483                                                 /*As in the original library format, it is assumed that the .rel
484                                                 files reside in the same directory as the lib files.*/
485                                                 strcat(DirLib, ModName);
486                                         sprintf(&DirLib[strlen(DirLib)], "%crel", FSEPX);
487
488                                                 /*If this module has been loaded already don't load it again.*/
489                                                 lbf = lbfhead;
490                                                 while (lbf)
491                                                 {
492                                                         if(EQ(DirLib, lbf->filspc)) return 1;/*Already loaded*/
493                                                         lbf=lbf->next;
494                                                 }
495                                                 
496                                                 /*Add the embedded file to the list of files to be loaded in
497                                                 the second pass.  That is performed latter by the function
498                                                 library() below.*/
499                                                 lbfh = (struct lbfile *) new (sizeof(struct lbfile));
500                                                 if (lbfhead == NULL)
501                                                 {
502                                                         lbfhead = lbfh;
503                                                 }
504                                                 else
505                                                 {
506                                                         lbf = lbfhead;
507                                                         while (lbf->next)
508                                                         lbf = lbf->next;
509                                                         lbf->next = lbfh;
510                                                 }
511
512                                                 lbfh->libspc = PathLib;
513                                                 lbfh->filspc = DirLib;
514                                                 lbfh->relfil = (char *) new (strlen(ModName) + 1);
515                                                 strcpy(lbfh->relfil, ModName);
516                                                 /*Library embedded file, so lbfh->offset must be >=0*/
517                                                 lbfh->offset = IndexOffset+FileOffset;
518                                                 
519                                                 /*Jump to where the .rel begins and load it.*/
520                                                 fseek(libfp, lbfh->offset, SEEK_SET);
521                                                 LoadRel(libfp, ModName);
522
523                                                 /* if cdb information required & .adb file present */
524                                                 if (dflag && dfp)
525                                                 {
526                                                         if(LoadAdb(libfp))
527                                                                 SaveLinkedFilePath(DirLib);
528                                                 }
529                                                 return 1; /*Found the symbol, so success!*/
530                                         }
531                                 }
532             break;
533                         
534                         default:
535                                 return 0; /*It should never reach this point, but just in case...*/
536                         break;
537         }
538     }
539
540         return 0; /*The symbol is not in this library*/
541 }
542
543 /*)Function     VOID    fndsym(name)
544  *
545  *              char    *name           symbol name to find
546  *
547  *      The function fndsym() searches through all combinations of the
548  *      library path specifications (input by the -k option) and the
549  *      library file specifications (input by the -l option) that
550  *      lead to an existing file.
551  *
552  *      The file specicifation may be formed in one of two ways:
553  *
554  *      (1)     If the library file contained an absolute
555  *              path/file specification then this becomes filspc.
556  *              (i.e. C:\...)
557  *
558  *      (2)     If the library file contains a relative path/file
559  *              specification then the concatenation of the path
560  *              and this file specification becomes filspc.
561  *              (i.e. \...)
562  *
563  *      The structure lbfile is created for the first library
564  *      object file which contains the definition for the
565  *      specified undefined symbol.
566  *
567  *      If the library file [.LIB] contains file specifications for
568  *      non existant files, no errors are returned.
569  *
570  *      local variables:
571  *              char    buf[]           [.REL] file input line
572  *              char    c               [.REL] file input character
573  *              FILE    *fp             file handle for object file
574  *              lbfile  *lbf            temporary pointer
575  *              lbfile  *lbfh           pointer to lbfile structure
576  *              FILE    *libfp          file handle for library file
577  *              lbname  *lbnh           pointer to lbname structure
578  *              char    *path           file specification path
579  *              char    relfil[]        [.REL] file specification
580  *              char    *str            combined path and file specification
581  *              char    symname[]       [.REL] file symbol string
582  *
583  *      global variables:
584  *              lbname  *lbnhead        The pointer to the first
585  *                                      name structure
586  *              lbfile  *lbfhead        The pointer to the first
587  *                                      file structure
588  *
589  *       functions called:
590  *              int     fclose()        c_library
591  *              int     fgets()         c_library
592  *              FILE    *fopen()        c_library
593  *              VOID    free()          c_library
594  *              char    getnb()         lklex.c
595  *              VOID    lkexit()        lkmain.c
596  *              VOID    loadfile()      lklibr.c
597  *              VOID *  new()           lksym.c
598  *              char *  sprintf()       c_library
599  *              int     sscanf()        c_library
600  *              char *  strcat()        c_library
601  *              char *  strchr()        c_library
602  *              char *  strcpy()        c_library
603  *              int     strlen()        c_library
604  *              int     strncmp()       c_library
605  *              VOID    unget()         lklex.c
606  *
607  *      side effects:
608  *              If the symbol is found then a new lbfile structure
609  *              is created and added to the linked list of lbfile
610  *              structures.  The file containing the found symbol
611  *              is linked.
612  */
613
614 int
615 fndsym(name)
616 char *name;
617 {
618         FILE *libfp, *fp;
619         struct lbname *lbnh;
620         struct lbfile *lbfh, *lbf;
621         char relfil[NINPUT+2];
622         char buf[NINPUT+2];
623         char symname[NINPUT];
624         char *path,*str;
625         char c;
626         int result;
627
628         /*
629          * Search through every library in the linked list "lbnhead".
630          */
631
632         for (lbnh=lbnhead; lbnh; lbnh=lbnh->next)
633         {
634                 if ((libfp = fopen(lbnh->libspc, "r")) == NULL)
635                 {
636                         fprintf(stderr, "Cannot open library file %s\n",
637                                 lbnh->libspc);
638                         lkexit(1);
639                 }
640                 path = lbnh->path;
641
642                 /*
643                  * Read in a line from the library file.
644                  * This is the relative file specification
645                  * for a .REL file in this library.
646                  */
647
648                 while (fgets(relfil, NINPUT, libfp) != NULL)
649                 {
650                     relfil[NINPUT+1] = '\0';
651                     chop_crlf(relfil);
652                     if (path != NULL)
653                         {
654                                 str = (char *) new (strlen(path)+strlen(relfil)+6);
655                                 strcpy(str,path);
656 #ifdef  OTHERSYSTEM
657                                 if (str[strlen(str)-1] != '/')
658                                 {
659                                         strcat(str,"/");
660                                 }
661 #endif
662                     }
663                         else
664                         {
665                                 str = (char *) new (strlen(relfil) + 5);
666                     }
667
668                         if(strcmp(relfil, "<SDCCLIB>")==0)
669                         {
670                                 result=SdccLib(lbnh->libspc, libfp, str, name);
671                                 fclose(libfp);
672                                 if(result) return(1); /*Found the symbol*/
673                                 free(str);
674                                 /*The symbol is not in the current library,
675                                 check the next library in the list*/
676                                 break; 
677                         }
678
679                         /*From here down is the support for libraries in the original format*/
680                         if (relfil[0] == '\\')
681                         {
682                                 strcat(str,relfil+1);
683                     }
684                         else
685                         {
686                                 strcat(str,relfil);
687                     }
688                     
689                         if(strchr(relfil, FSEPX) == NULL)
690                         {
691                                 sprintf(&str[strlen(str)], "%crel", FSEPX);
692                     }
693
694                         if ((fp = fopen(str, "r")) != NULL)
695                         {
696
697                                 /*
698                                  * Read in the object file.  Look for lines that
699                                  * begin with "S" and end with "D".  These are
700                                  * symbol table definitions.  If we find one, see
701                                  * if it is our symbol.  Make sure we only read in
702                                  * our object file and don't go into the next one.
703                                  */
704                         
705                                 while (fgets(buf, NINPUT, fp) != NULL)
706                                 {
707                                         buf[NINPUT+1] = '\0';
708                                         chop_crlf(buf);
709                                         /*
710                                          * Skip everything that's not a symbol record.
711                                          */
712                                         if (buf[0] != 'S') continue;
713
714                                         /*
715                                         * When a 'T line' is found terminate file scan.
716                                         * All 'S line's preceed 'T line's in .REL files.
717                                         */
718                                         if (buf[0] == 'T') break;
719
720                                         sscanf(buf, "S %s %c", symname, &c);
721
722                                         /*
723                                         * If we find a symbol definition for the
724                                         * symbol we're looking for, load in the
725                                         * file and add it to lbfhead so it gets
726                                         * loaded on pass number 2.
727                                         */
728                                         if (strncmp(symname, name, NCPS) == 0 && c == 'D')
729                                         {
730                                                 lbfh = (struct lbfile *) new (sizeof(struct lbfile));
731                                                 if (lbfhead == NULL)
732                                                 {
733                                                         lbfhead = lbfh;
734                                                 }
735                                                 else
736                                                 {
737                                                         lbf = lbfhead;
738                                                         while (lbf->next)
739                                                         lbf = lbf->next;
740                                                         lbf->next = lbfh;
741                                                 }
742
743                                                 lbfh->libspc = lbnh->libspc;
744                                                 lbfh->filspc = str;
745                                                 lbfh->relfil = (char *) new (strlen(relfil) + 1);
746                                                 lbfh->offset = -1; /*Stand alone rel file*/
747                                                 strcpy(lbfh->relfil,relfil);
748                                                 fclose(fp);
749                                                 fclose(libfp);                 
750                         
751                                                 /* if cdb information required & adb file present */
752                                                 if (dflag && dfp)
753                                                 {
754                                                         FILE *xfp = afile(str,"adb",0); //JCF: Nov 30, 2002
755                                                         if (xfp)
756                                                         {
757                                                                 SaveLinkedFilePath(str);
758                                                                 copyfile(dfp,xfp);
759                                                                 fclose(xfp);
760                                                         }
761                                                 }
762                                                 loadfile(str);
763                                                 return (1);
764                                         }
765                                 }
766                                 fclose(fp);
767                         }
768                         free(str);
769                 }
770                 fclose(libfp);
771         }
772         return(0);
773 }
774
775 void loadfile_SdccLib(char * libspc, char * module, long offset)
776 {
777         FILE *fp;
778
779         if ((fp = fopen(libspc,"r")) != NULL)
780         {
781                 fseek(fp, offset, SEEK_SET);
782                 LoadRel(fp, module);
783                 fclose(fp);
784         }
785 }
786
787 /*)Function     VOID    library()
788  *
789  *      The function library() links all the library object files
790  *      contained in the lbfile structures.
791  *
792  *      local variables:
793  *              lbfile  *lbfh           pointer to lbfile structure
794  *
795  *      global variables:
796  *              lbfile  *lbfhead        pointer to first lbfile structure
797  *
798  *       functions called:
799  *              VOID    loadfile        lklibr.c
800  *
801  *      side effects:
802  *              Links all files contained in the lbfile structures.
803  */
804
805 VOID
806 library()
807 {
808         struct lbfile *lbfh;
809
810         for (lbfh=lbfhead; lbfh; lbfh=lbfh->next)
811         {
812                 if(lbfh->offset<0)
813                 {
814                         /*Stand alone rel file (original lib format)*/
815                         loadfile(lbfh->filspc);
816                 }
817                 else
818                 {
819                         /*rel file embedded in lib (new lib format)*/
820                         loadfile_SdccLib(lbfh->libspc, lbfh->relfil, lbfh->offset);
821                 }
822         }
823 }
824
825 /*)Function     VOID    loadfile(filspc)
826  *
827  *              char    *filspc         library object file specification
828  *
829  *      The function loadfile() links the library object module.
830  *
831  *      local variables:
832  *              FILE    *fp             file handle
833  *              int     i               input line length
834  *              char    str[]           file input line
835  *
836  *      global variables:
837  *              char    *ip             pointer to linker input string
838  *
839  *       functions called:
840  *              int     fclose()        c_library
841  *              int     fgets()         c_library
842  *              FILE *  fopen()         c_library
843  *              VOID    link_main()     lkmain.c
844  *              int     strlen()        c_library
845  *
846  *      side effects:
847  *              If file exists it is linked.
848  */
849
850 VOID
851 loadfile(filspc)
852 char *filspc;
853 {
854         FILE *fp;
855         char str[NINPUT+2];
856
857         if ((fp = fopen(filspc,"r")) != NULL) {
858                 while (fgets(str, NINPUT, fp) != NULL) {
859                         str[NINPUT+1] = '\0';
860                         chop_crlf(str);
861                         ip = str;
862                         link_main();
863                 }
864                 fclose(fp);
865         }
866 }