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