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