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