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