* src/SDCCglue.c (printIvalType, printIvalBitFields): fixed bug 1856409
[fw/sdcc] / as / link / mcs51 / lklibr.c
1 /* lklibr.c */
2
3 /*
4  * (C) Copyright 1989-1995
5  * All Rights Reserved
6  *
7  * Alan R. Baldwin
8  * 721 Berkeley St.
9  * Kent, Ohio  44240
10  *
11  * With contributions for the
12  * object libraries from
13  * Ken Hornstein
14  * kenh@cmf.nrl.navy.mil
15  *
16  */
17
18 #define EQ(A,B) !strcmp((A),(B))
19 #define MAXLINE 254 /*when using fgets*/
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <string.h>
24 #include <ctype.h>
25 #include "aslink.h"
26
27 /*)Module   lklibr.c
28  *
29  *  The module lklibr.c contains the functions which
30  *  (1) specify the path(s) to library files [.LIB]
31  *  (2) specify the library file(s) [.LIB] to search
32  *  (3) search the library files for specific symbols
33  *      and link the module containing this symbol
34  *
35  *  lklibr.c contains the following functions:
36  *      VOID    addpath()
37  *      VOID    addlib()
38  *      VOID    addfile()
39  *      VOID    search()
40  *      VOID    fndsym()
41  *      VOID    library()
42  *      VOID    loadfile()
43  *
44  */
45
46 #ifdef INDEXLIB
47 typedef struct slibrarysymbol mlibrarysymbol;
48 typedef struct slibrarysymbol *pmlibrarysymbol;
49
50 struct slibrarysymbol {
51     char * name; /*Warning: allocate memory before using*/
52     pmlibrarysymbol next;
53 };
54
55 typedef struct slibraryfile mlibraryfile;
56 typedef struct slibraryfile *pmlibraryfile;
57
58 struct slibraryfile {
59     int loaded;
60     char * libspc;
61     char * relfil; /*Warning: allocate memory before using*/
62     char * filename; /*Warning: allocate memory before using*/
63     long offset; //if > 0, the embedded file offset in the library file libspc
64     pmlibrarysymbol symbols;
65     pmlibraryfile next;
66 };
67
68 /* First entry in the library object symbol cache */
69 pmlibraryfile libr=NULL;
70
71 int buildlibraryindex(void);
72 void freelibraryindex (void);
73 #endif /* INDEXLIB */
74
75 /*)Function VOID    addpath()
76  *
77  *  The function addpath() creates a linked structure containing
78  *  the paths to various object module library files.
79  *
80  *  local variables:
81  *      lbpath  *lbph       pointer to new path structure
82  *      lbpath  *lbp        temporary pointer
83  *
84  *  global variables:
85  *      lbpath  *lbphead    The pointer to the first
86  *                          path structure
87  *
88  *   functions called:
89  *      char    getnb()     lklex.c
90  *      VOID *  new()       lksym.c
91  *      int     strlen()    c_library
92  *      char *  strcpy()    c_library
93  *      VOID    unget()     lklex.c
94  *
95  *  side effects:
96  *      An lbpath structure may be created.
97  */
98
99 VOID
100 addpath(void)
101 {
102     struct lbpath *lbph, *lbp;
103
104     lbph = (struct lbpath *) new (sizeof(struct lbpath));
105     if (lbphead == NULL) {
106         lbphead = lbph;
107     } else {
108         lbp = lbphead;
109         while (lbp->next)
110         {
111             lbp = lbp->next;
112         }
113         lbp->next = lbph;
114     }
115     unget(getnb());
116     lbph->path = (char *) new (strlen(ip)+1);
117     strcpy(lbph->path, ip);
118 }
119
120 /*)Function VOID    addlib()
121  *
122  *  The function addlib() tests for the existance of a
123  *  library path structure to determine the method of
124  *  adding this library file to the library search structure.
125  *
126  *  This function calls the function addfile() to actually
127  *  add the library file to the search list.
128  *
129  *  local variables:
130  *      lbpath  *lbph       pointer to path structure
131  *
132  *  global variables:
133  *      lbpath  *lbphead    The pointer to the first
134  *                          path structure
135  *      ip a pointer to the library name
136  *
137  *   functions called:
138  *      VOID    addfile()   lklibr.c
139  *      char    getnb()     lklex.c
140  *      VOID    unget()     lklex.c
141  *
142  *  side effects:
143  *      The function addfile() may add the file to
144  *      the library search list.
145  */
146
147 VOID
148 addlib(void)
149 {
150     struct lbpath *lbph;
151     int foundcount=0;
152
153     unget(getnb());
154
155     if (lbphead == NULL)
156     {
157         foundcount=addfile(NULL, ip);
158     }
159     else
160     {
161         for (lbph=lbphead; lbph; lbph=lbph->next)
162         {
163             foundcount+=addfile(lbph->path, ip);
164         }
165     }
166     if(foundcount == 0)
167     {
168         fprintf(stderr, "?ASlink-Warning-Couldn't find library '%s'\n", ip);
169     }
170 }
171
172 /*)Function int addfile(path,libfil)
173  *
174  *      char    *path       library path specification
175  *      char    *libfil     library file specification
176  *
177  *  The function addfile() searches for the library file
178  *  by concatenating the path and libfil specifications.
179  *  if the library is found, an lbname structure is created
180  *  and linked to any previously defined structures.  This
181  *  linked list is used by the function fndsym() to attempt
182  *  to find any undefined symbols.
183  *
184  *  The function does not give report an error on invalid
185  *  path / file specifications or if the file is not found.
186  *
187  *  local variables:
188  *      lbname  *lbnh       pointer to new name structure
189  *      lbname  *lbn        temporary pointer
190  *
191  *  global variables:
192  *      lbname  *lbnhead    The pointer to the first
193  *                          path structure
194  *
195  *   functions called:
196  *      char    getnb()     lklex.c
197  *      VOID *  new()       lksym.c
198  *      int     strlen()    c_library
199  *      char *  strcpy()    c_library
200  *      VOID    unget()     lklex.c
201  *
202  *  side effects:
203  *      An lbname structure may be created.
204  *
205  *  return:
206  *      1: the library was found
207  *      0: the library was not found
208  */
209
210 int addfile(char * path, char * libfil)
211 {
212     FILE *fp;
213     char *str;
214     struct lbname *lbnh, *lbn;
215 #ifdef  OTHERSYSTEM
216     int libfilinc=0;
217 #endif
218
219     if (path != NULL)
220     {
221         str = (char *) new (strlen(path) + strlen(libfil) + 6);
222         strcpy(str, path);
223 #ifdef  OTHERSYSTEM
224         if (strlen(str) && (str[strlen(str)-1] != '/') && (str[strlen(str)-1] != LKDIRSEP))
225         {
226             strcat(str, LKDIRSEPSTR);
227         }
228 #endif
229     }
230     else
231     {
232         str = (char *) new (strlen(libfil) + 5);
233     }
234
235 #ifdef  OTHERSYSTEM
236     if ((libfil[0] == '/') || (libfil[0] == LKDIRSEP))
237     {
238         libfil++;
239         libfilinc=1;
240     }
241 #endif
242
243     strcat(str, libfil);
244     if(strchr(libfil, FSEPX) == NULL)
245     {
246         sprintf(&str[strlen(str)], "%clib", FSEPX);
247     }
248
249     fp=fopen(str, "r");
250     if(fp == NULL)
251     {
252         /*Ok, that didn't work.  Try with the 'libfil' name only*/
253 #ifdef  OTHERSYSTEM
254         if(libfilinc) libfil--;
255 #endif
256         fp=fopen(libfil, "r");
257         if(fp != NULL)
258         {
259             /*Bingo!  'libfil' is the absolute path of the library*/
260             strcpy(str, libfil);
261             path=NULL;/*This way 'libfil' and 'path' will be rebuilt from 'str'*/
262         }
263     }
264
265     if(path==NULL)
266     {
267         /*'path' can not be null since it is needed to find the object files associated with
268         the library.  So, get 'path' from 'str' and then chop it off and recreate 'libfil'.
269         That way putting 'path' and 'libfil' together will result into the original filepath
270         as contained in 'str'.*/
271         int j;
272         path = (char *) new (strlen(str) + 1);
273         strcpy(path, str);
274         for(j=strlen(path)-1; j>=0; j--)
275         {
276             if((path[j] == '/') || (path[j] == LKDIRSEP))
277             {
278                 strcpy(libfil, &path[j+1]);
279                 path[j+1]=0;
280                 break;
281             }
282         }
283         if(j<=0) path[0]=0;
284     }
285
286     if (fp != NULL)
287     {
288         fclose(fp);
289         lbnh = (struct lbname *) new (sizeof(struct lbname));
290         if (lbnhead == NULL)
291         {
292             lbnhead = lbnh;
293         }
294         else
295         {
296             lbn = lbnhead;
297             while (lbn->next)
298             {
299                 lbn = lbn->next;
300             }
301             lbn->next = lbnh;
302         }
303
304         lbnh->path = path;
305         lbnh->libfil = (char *) new (strlen(libfil) + 1);
306         strcpy(lbnh->libfil, libfil);
307         lbnh->libspc = str;
308         return 1;
309     }
310     else
311     {
312         free(str);
313         return 0;
314     }
315 }
316
317 /*)Function VOID    search()
318  *
319  *  The function search() looks through all the symbol tables
320  *  at the end of pass 1.  If any undefined symbols are found
321  *  then the function fndsym() is called. Function fndsym()
322  *  searches any specified library files to automagically
323  *  import the object modules containing the needed symbol.
324  *
325  *  After a symbol is found and imported by the function
326  *  fndsym() the symbol tables are again searched.  The
327  *  symbol tables are search until no more symbols can be
328  *  resolved within the library files.  This ensures that
329  *  back references from one library module to another are
330  *  also resolved.
331  *
332  *  local variables:
333  *      int     i           temporary counter
334  *      sym     *sp         pointer to a symbol structure
335  *      int     symfnd      found a symbol flag
336  *
337  *  global variables:
338  *      sym     *symhash[]  array of pointers to symbol tables
339  *
340  *   functions called:
341  *      int     fndsym()    lklibr.c
342  *
343  *  side effects:
344  *      If a symbol is found then the library object module
345  *      containing the symbol will be imported and linked.
346  */
347
348 VOID
349 search(void)
350 {
351     register struct sym *sp;
352     register int i, symfnd;
353
354     /*
355      * Look for undefined symbols.  Keep
356      * searching until no more symbols are resolved.
357      */
358     symfnd = 1;
359     while (symfnd) {
360         symfnd = 0;
361         /*
362          * Look through all the symbols
363          */
364         for (i=0; i<NHASH; ++i) {
365             sp = symhash[i];
366             while (sp) {
367                 /* If we find an undefined symbol
368                  * (one where S_DEF is not set), then
369                  * try looking for it.  If we find it
370                  * in any of the libraries then
371                  * increment symfnd.  This will force
372                  * another pass of symbol searching and
373                  * make sure that back references work.
374                  */
375                 if ((sp->s_type & S_DEF) == 0) {
376                     if (fndsym(sp->s_id)) {
377                         symfnd++;
378                     }
379                 }
380                 sp = sp->s_sp;
381             }
382         }
383     }
384 }
385
386 /*Load a .rel file embedded in a sdcclib file*/
387 void LoadRel(char * libfname, FILE * libfp, char * ModName)
388 {
389     char str[NINPUT+2];
390     int state=0;
391
392     while (fgets(str, NINPUT, libfp) != NULL)
393     {
394         str[NINPUT+1] = '\0';
395         chop_crlf(str);
396         switch(state)
397         {
398             case 0:
399                 if(EQ(str, "<FILE>"))
400                 {
401                     fgets(str, NINPUT, libfp);
402                     str[NINPUT+1] = '\0';
403                     chop_crlf(str);
404                     if(EQ(str, ModName)) state=1;
405                     else
406                     {
407                         fprintf(stderr, "?ASlink-Error-Bad offset in library file %s(%s)\n",
408                             libfname, ModName);
409                         lkexit(1);
410                     }
411                 }
412             break;
413             case 1:
414                 if(EQ(str, "<REL>")) state=2;
415             break;
416             case 2:
417                 if(EQ(str, "</REL>")) return;
418                 ip = str;
419                 link_main();
420             break;
421         }
422     }
423 }
424
425 /*Load an .adb file embedded in a sdcclib file. If there is
426 something between <ADB> and </ADB> returns 1, otherwise returns 0.
427 This way the aomf51 will not have useless empty modules. */
428
429 int LoadAdb(FILE * libfp)
430 {
431     char str[MAXLINE+1];
432     int state=0;
433     int ToReturn=0;
434
435     while (fgets(str, MAXLINE, libfp) != NULL)
436     {
437         str[NINPUT+1] = '\0';
438         chop_crlf(str);
439         switch(state)
440         {
441             case 0:
442                 if(EQ(str, "<ADB>")) state=1;
443             break;
444             case 1:
445                 if(EQ(str, "</ADB>")) return ToReturn;
446                 fprintf(dfp, "%s\n", str);
447                 ToReturn=1;
448             break;
449         }
450     }
451     return ToReturn;
452 }
453
454 /*Check for a symbol in a SDCC library. If found, add the embedded .rel and
455 .adb files from the library.  The library must be created with the SDCC
456 librarian 'sdcclib' since the linking process depends on the correct file offsets
457 embedded in the library file.*/
458
459 int SdccLib(char * PathLib, FILE * libfp, char * DirLib, char * SymName)
460 {
461     struct lbfile *lbfh, *lbf;
462     char ModName[NCPS]="";
463     char FLine[MAXLINE+1];
464     int state=0;
465     long IndexOffset=0, FileOffset;
466
467     while(!feof(libfp))
468     {
469         FLine[0]=0;
470         fgets(FLine, MAXLINE, libfp);
471         chop_crlf(FLine);
472
473         switch(state)
474         {
475             case 0:
476                 if(EQ(FLine, "<INDEX>"))
477                 {
478                     /*The next line has the size of the index*/
479                     FLine[0]=0;
480                     fgets(FLine, MAXLINE, libfp);
481                     chop_crlf(FLine);
482                     IndexOffset=atol(FLine);
483                     state=1;
484                 }
485             break;
486             case 1:
487                 if(EQ(FLine, "<MODULE>"))
488                 {
489                     /*The next line has the name of the module and the offset
490                     of the corresponding embedded file in the library*/
491                     FLine[0]=0;
492                     fgets(FLine, MAXLINE, libfp);
493                     chop_crlf(FLine);
494                     sscanf(FLine, "%s %ld", ModName, &FileOffset);
495                     state=2;
496                 }
497                 else if(EQ(FLine, "</INDEX>"))
498                 {
499                     /*Reached the end of the index.  The symbol is not in this library.*/
500                     return 0;
501                 }
502             break;
503             case 2:
504                 if(EQ(FLine, "</MODULE>"))
505                 {
506                     /*The symbol is not in this module, try the next one*/
507                     state=1;
508                 }
509                 else
510                 {
511                     /*Check if this is the symbol we are looking for.*/
512                     if (strncmp(SymName, FLine, NCPS)==0)
513                     {
514                         /*The symbol is in this module.*/
515
516                         /*As in the original library format, it is assumed that the .rel
517                         files reside in the same directory as the lib files.*/
518                         strcat(DirLib, ModName);
519                         sprintf(&DirLib[strlen(DirLib)], "%c%s", FSEPX, LKOBJEXT);
520
521                         /*If this module has been loaded already don't load it again.*/
522                         lbf = lbfhead;
523                         while (lbf)
524                         {
525                             if(EQ(DirLib, lbf->filspc)) return 1;/*Already loaded*/
526                             lbf=lbf->next;
527                         }
528
529                         /*Add the embedded file to the list of files to be loaded in
530                         the second pass.  That is performed latter by the function
531                         library() below.*/
532                         lbfh = (struct lbfile *) new (sizeof(struct lbfile));
533                         if (lbfhead == NULL)
534                         {
535                             lbfhead = lbfh;
536                         }
537                         else
538                         {
539                             lbf = lbfhead;
540                             while (lbf->next)
541                             {
542                                 lbf = lbf->next;
543                             }
544                             lbf->next = lbfh;
545                         }
546
547                         lbfh->libspc = PathLib;
548                         lbfh->filspc = DirLib;
549                         lbfh->relfil = (char *) new (strlen(ModName) + 1);
550                         strcpy(lbfh->relfil, ModName);
551                         /*Library embedded file, so lbfh->offset must be >=0*/
552                         lbfh->offset = IndexOffset+FileOffset;
553
554                         /*Jump to where the .rel begins and load it.*/
555                         fseek(libfp, lbfh->offset, SEEK_SET);
556                         LoadRel(PathLib, libfp, ModName);
557
558                         /* if cdb information required & .adb file present */
559                         if (dflag && dfp)
560                         {
561                             if(LoadAdb(libfp))
562                                 SaveLinkedFilePath(DirLib);
563                         }
564                         return 1; /*Found the symbol, so success!*/
565                     }
566                 }
567             break;
568
569             default:
570                 return 0; /*It should never reach this point, but just in case...*/
571             break;
572         }
573     }
574
575     return 0; /*The symbol is not in this library*/
576 }
577
578 /*)Function VOID    fndsym(name)
579  *
580  *      char    *name       symbol name to find
581  *
582  *  The function fndsym() searches through all combinations of the
583  *  library path specifications (input by the -k option) and the
584  *  library file specifications (input by the -l option) that
585  *  lead to an existing file.
586  *
587  *  The file specicifation may be formed in one of two ways:
588  *
589  *  (1) If the library file contained an absolute
590  *      path/file specification then this becomes filspc.
591  *      (i.e. C:\...)
592  *
593  *  (2) If the library file contains a relative path/file
594  *      specification then the concatenation of the path
595  *      and this file specification becomes filspc.
596  *      (i.e. \...)
597  *
598  *  The structure lbfile is created for the first library
599  *  object file which contains the definition for the
600  *  specified undefined symbol.
601  *
602  *  If the library file [.LIB] contains file specifications for
603  *  non existant files, no errors are returned.
604  *
605  *  local variables:
606  *      char    buf[]       [.REL] file input line
607  *      char    c           [.REL] file input character
608  *      FILE    *fp         file handle for object file
609  *      lbfile  *lbf        temporary pointer
610  *      lbfile  *lbfh       pointer to lbfile structure
611  *      FILE    *libfp      file handle for library file
612  *      lbname  *lbnh       pointer to lbname structure
613  *      char    *path       file specification path
614  *      char    relfil[]    [.REL] file specification
615  *      char    *str        combined path and file specification
616  *      char    symname[]   [.REL] file symbol string
617  *
618  *  global variables:
619  *      lbname  *lbnhead    The pointer to the first
620  *                          name structure
621  *      lbfile  *lbfhead    The pointer to the first
622  *                          file structure
623  *
624  *   functions called:
625  *      int     fclose()    c_library
626  *      int     fgets()     c_library
627  *      FILE    *fopen()    c_library
628  *      VOID    free()      c_library
629  *      char    getnb()     lklex.c
630  *      VOID    lkexit()    lkmain.c
631  *      VOID    loadfile()  lklibr.c
632  *      VOID *  new()       lksym.c
633  *      char *  sprintf()   c_library
634  *      int     sscanf()    c_library
635  *      char *  strcat()    c_library
636  *      char *  strchr()    c_library
637  *      char *  strcpy()    c_library
638  *      int     strlen()    c_library
639  *      int     strncmp()   c_library
640  *      VOID    unget()     lklex.c
641  *
642  *  side effects:
643  *      If the symbol is found then a new lbfile structure
644  *      is created and added to the linked list of lbfile
645  *      structures.  The file containing the found symbol
646  *      is linked.
647  */
648
649 #ifdef INDEXLIB
650
651 int fndsym( char *name )
652 {
653     struct lbfile *lbfh, *lbf;
654     pmlibraryfile ThisLibr;
655     pmlibrarysymbol ThisSym = NULL;
656
657     pmlibraryfile FirstFound;
658     int numfound=0;
659
660     /* Build the index if this is the first call to fndsym */
661     if (libr==NULL) buildlibraryindex();
662
663     /* Iterate through all library object files */
664     ThisLibr = libr;
665     FirstFound = libr; /*So gcc stops whining*/
666     while (ThisLibr)
667     {
668         /* Iterate through all symbols in an object file */
669         ThisSym = ThisLibr->symbols;
670
671         while (ThisSym)
672         {
673             if (!strcmp(ThisSym->name, name))
674             {
675                 if ((!ThisLibr->loaded) && (numfound==0))
676                 {
677                     /* Object file is not loaded - add it to the list */
678                     lbfh = (struct lbfile *) new (sizeof(struct lbfile));
679                     if (lbfhead == NULL)
680                     {
681                         lbfhead = lbfh;
682                     }
683                     else
684                     {
685                         lbf = lbfhead;
686                         while (lbf->next)
687                         {
688                             lbf = lbf->next;
689                         }
690                         lbf->next = lbfh;
691                     }
692                     lbfh->libspc = ThisLibr->libspc;
693                     lbfh->filspc = ThisLibr->filename;
694                     lbfh->relfil = (char *) new (strlen(ThisLibr->relfil) + 1);
695                     strcpy(lbfh->relfil, ThisLibr->relfil);
696                     lbfh->offset = ThisLibr->offset;
697                     if(lbfh->offset>0)
698                     { /*For an embedded object file in a library*/
699                         void loadfile_SdccLib(char * libspc, char * module, long offset);
700                         loadfile_SdccLib(lbfh->libspc, lbfh->relfil, lbfh->offset);
701                     }
702                     else
703                     { /*For a stand alone object file*/
704                         /* if cdb information required & adb file present */
705                         if (dflag && dfp)
706                         {
707                             FILE *xfp = afile(lbfh->filspc, "adb",0);
708                             if (xfp)
709                             {
710                                 SaveLinkedFilePath(lbfh->filspc);
711                                 copyfile(dfp, xfp);
712                                 fclose(xfp);
713                             }
714                         }
715                         loadfile(lbfh->filspc);
716                     }
717                     ThisLibr->loaded=1;
718                 }
719
720                 if(numfound==0)
721                 {
722                     numfound++;
723                     FirstFound=ThisLibr;
724                 }
725                 else
726                 {
727                     char absPath1[PATH_MAX];
728                     char absPath2[PATH_MAX];
729 #if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
730                     int j;
731
732                     _fullpath(absPath1, FirstFound->libspc, PATH_MAX);
733                     _fullpath(absPath2, ThisLibr->libspc, PATH_MAX);
734                     for(j=0; absPath1[j]!=0; j++) absPath1[j]=tolower((unsigned char)absPath1[j]);
735                     for(j=0; absPath2[j]!=0; j++) absPath2[j]=tolower((unsigned char)absPath2[j]);
736 #else
737                     realpath(FirstFound->libspc, absPath1);
738                     realpath(ThisLibr->libspc, absPath2);
739 #endif
740                     if( !( EQ(absPath1, absPath2) && EQ(FirstFound->relfil, ThisLibr->relfil) ) )
741                     {
742                         if(numfound==1)
743                         {
744                             fprintf(stderr, "?ASlink-Warning-Definition of public symbol '%s'"
745                                    " found more than once:\n", name);
746                             fprintf(stderr, "   Library: '%s', Module: '%s'\n",
747                                     FirstFound->libspc, FirstFound->relfil);
748                         }
749                         fprintf(stderr, "   Library: '%s', Module: '%s'\n",
750                                 ThisLibr->libspc, ThisLibr->relfil);
751                         numfound++;
752                     }
753                 }
754             }
755             ThisSym=ThisSym->next;  /* Next sym in library */
756         }
757         ThisLibr=ThisLibr->next; /* Next library in list */
758     }
759     return numfound;
760 }
761
762 pmlibraryfile buildlibraryindex_SdccLib(char * PathLib, FILE * libfp, char * DirLib, pmlibraryfile This)
763 {
764     char ModName[NCPS]="";
765     char FLine[MAXLINE+1];
766     char buff[PATH_MAX];
767     int state=0;
768     long IndexOffset=0, FileOffset;
769     pmlibrarysymbol ThisSym = NULL;
770
771     while(!feof(libfp))
772     {
773         FLine[0]=0;
774         fgets(FLine, MAXLINE, libfp);
775         chop_crlf(FLine);
776
777         switch(state)
778         {
779             case 0:
780                 if(EQ(FLine, "<INDEX>"))
781                 {
782                     /*The next line has the size of the index*/
783                     FLine[0]=0;
784                     fgets(FLine, MAXLINE, libfp);
785                     chop_crlf(FLine);
786                     IndexOffset=atol(FLine);
787                     state=1;
788                 }
789             break;
790             case 1:
791                 if(EQ(FLine, "<MODULE>"))
792                 {
793                     /*The next line has the name of the module and the offset
794                     of the corresponding embedded file in the library*/
795                     FLine[0]=0;
796                     fgets(FLine, MAXLINE, libfp);
797                     chop_crlf(FLine);
798                     sscanf(FLine, "%s %ld", ModName, &FileOffset);
799                     state=2;
800
801                     /*Create a new libraryfile object for this module*/
802                     if(libr==NULL)
803                     {
804                         libr=This=(pmlibraryfile)new( sizeof( mlibraryfile ));
805                     }
806                     else
807                     {
808                         This->next=(pmlibraryfile)new( sizeof( mlibraryfile ));
809                         This=This->next;
810                     }
811                     This->next = NULL;
812                     This->loaded=-1;
813                     This->offset=FileOffset+IndexOffset;
814                     This->libspc=PathLib;
815
816                     This->relfil=(char *)new(strlen(ModName)+1);
817                     strcpy(This->relfil, ModName);
818
819                     sprintf(buff, "%s%s%c%s", DirLib, ModName, FSEPX, LKOBJEXT);
820                     This->filename=(char *)new(strlen(buff)+1);
821                     strcpy(This->filename, buff);
822
823                     This->symbols=ThisSym=NULL; /*Start a new linked list of symbols*/
824                 }
825                 else if(EQ(FLine, "</INDEX>"))
826                 {
827                     return This; /*Finish, get out of here*/
828                 }
829             break;
830             case 2:
831                 if(EQ(FLine, "</MODULE>"))
832                 {
833                     This->loaded=0;
834                     /*Create the index for the next module*/
835                     state=1;
836                 }
837                 else
838                 {
839                     /*Add the symbols*/
840                     if(ThisSym==NULL) /*First symbol of the current module*/
841                     {
842                         ThisSym=This->symbols=(pmlibrarysymbol)new(sizeof(mlibrarysymbol));
843                     }
844                     else
845                     {
846                         ThisSym->next = (pmlibrarysymbol)new(sizeof(mlibrarysymbol));
847                         ThisSym=ThisSym->next;
848                     }
849                     ThisSym->next=NULL;
850                     ThisSym->name=(char *)new(strlen(FLine)+1);
851                     strcpy(ThisSym->name, FLine);
852                 }
853             break;
854
855             default:
856                 return This; /*State machine should never reach this point, but just in case...*/
857             break;
858         }
859     }
860
861     return This; /*State machine should never reach this point, but just in case...*/
862 }
863
864
865 /* buildlibraryindex - build an in-memory cache of the symbols contained in
866  *                     the libraries
867  */
868 int buildlibraryindex(void)
869 {
870     FILE *libfp, *fp;
871     struct lbname *lbnh;
872     char relfil[NINPUT+2], str[PATH_MAX], *path;
873     char buf[NINPUT+2], c;
874     char symname[NINPUT+2];
875     pmlibraryfile This=NULL;
876     pmlibrarysymbol ThisSym;
877
878     /*
879      * Search through every library in the linked list "lbnhead".
880      */
881     for (lbnh=lbnhead; lbnh; lbnh=lbnh->next)
882     {
883         if ((libfp = fopen(lbnh->libspc, "r")) == NULL)
884         {
885             fprintf(stderr, "?ASlink-Error-Cannot open library file %s\n",
886                 lbnh->libspc);
887             lkexit(1);
888         }
889         path = lbnh->path;
890
891         /*
892          * Read in a line from the library file.
893          * This is the relative file specification
894          * for a .REL file in this library.
895          */
896
897         while (fgets(relfil, NINPUT, libfp) != NULL)
898         {
899             relfil[NINPUT+1] = '\0';
900             chop_crlf(relfil);
901             if (path != NULL)
902             {
903                 strcpy(str, path);
904 #ifdef  OTHERSYSTEM
905                 if (strlen(str) && (str[strlen(str)-1] != '/') && (str[strlen(str)-1] != LKDIRSEP))
906                 {
907                     strcat(str, LKDIRSEPSTR);
908                 }
909 #endif
910             }
911             else
912             {
913                 strcpy(str, "");
914             }
915
916             if(strcmp(relfil, "<SDCCLIB>")==0)
917             {
918                 /*Get the built in index of this library*/
919                 This=buildlibraryindex_SdccLib(lbnh->libspc, libfp, str, This);
920                 break; /*get the index for next library*/
921             }
922
923             /*From here down, build the index for the original library format*/
924
925             if ((relfil[0] == '/') || (relfil[0] == LKDIRSEP))
926             {
927                 strcat(str, relfil+1);
928             }
929             else
930             {
931                 strcat(str, relfil);
932             }
933
934             if(strchr(relfil, FSEPX) == NULL)
935             {
936                 sprintf(&str[strlen(str)], "%c%s", FSEPX, LKOBJEXT);
937             }
938
939             if ((fp = fopen(str, "r")) != NULL)
940             {
941                 /* Opened OK - create a new libraryfile object for it */
942                 if(libr==NULL)
943                 {
944                     libr=This=(pmlibraryfile)new( sizeof( mlibraryfile ));
945                 }
946                 else
947                 {
948                     This->next=(pmlibraryfile)new( sizeof( mlibraryfile ));
949                     This=This->next;
950                 }
951                 This->next = NULL;
952                 This->loaded=-1;
953                 This->offset=-1; /*We have a stand alone .rel file*/
954                 This->libspc = lbnh->libspc;
955
956                 This->relfil=(char *)new(strlen(relfil)+1);
957                 strcpy(This->relfil, relfil);
958
959                 This->filename=(char *)new(strlen(str)+1);
960                 strcpy(This->filename, str);
961
962                 /*Start a new linked list of symbols for this module:*/
963                 This->symbols = ThisSym = NULL;
964
965                 /*
966                  * Read in the object file.  Look for lines that
967                  * begin with "S" and end with "D".  These are
968                  * symbol table definitions.  If we find one, see
969                  * if it is our symbol.  Make sure we only read in
970                  * our object file and don't go into the next one.
971                  */
972
973                 while (fgets(buf, NINPUT, fp) != NULL)
974                 {
975                     buf[NINPUT+1] = '\0';
976                     buf[strlen(buf) - 1] = '\0';
977
978                     /*
979                      * Skip everything that's not a symbol record.
980                      */
981                     if (buf[0] != 'S') continue;
982
983                     /*
984                      * When a 'T line' is found terminate file scan.
985                      * All 'S line's preceed 'T line's in .REL files.
986                      */
987                     if (buf[0] == 'T') break;
988
989                     sscanf(buf, "S %s %c", symname, &c);
990
991                     /* If it's an actual symbol, record it */
992                     if (c == 'D')
993                     {
994                         if(ThisSym==NULL)
995                         {
996                             ThisSym=This->symbols=(pmlibrarysymbol)new(sizeof(mlibrarysymbol));
997                         }
998                         else
999                         {
1000                             ThisSym->next=(pmlibrarysymbol)new(sizeof(mlibrarysymbol));
1001                             ThisSym=ThisSym->next;
1002                         }
1003                         This->loaded=0;
1004                         ThisSym->next=NULL;
1005                         ThisSym->name=(char *)new(strlen(symname)+1);
1006                         strcpy(ThisSym->name, symname);
1007                     }
1008                 } /* Closes while - read object file */
1009                 fclose(fp);
1010             } /* Closes if object file opened OK */
1011             else
1012             {
1013                 fprintf(stderr, "?ASlink-Warning-Cannot open library module %s\n", str);
1014             }
1015         } /* Ends while - processing all in libr */
1016         fclose(libfp);
1017     } /* Ends good open of libr file */
1018     return 0;
1019 }
1020
1021 /*Release all memory allocated for the in-memory library index*/
1022 void freelibraryindex (void)
1023 {
1024     pmlibraryfile ThisLibr, ThisLibr2Free;
1025     pmlibrarysymbol ThisSym, ThisSym2Free;
1026
1027     ThisLibr = libr;
1028
1029     while (ThisLibr)
1030     {
1031         ThisSym = ThisLibr->symbols;
1032
1033         while (ThisSym)
1034         {
1035             free(ThisSym->name);
1036             ThisSym2Free=ThisSym;
1037             ThisSym=ThisSym->next;
1038             free(ThisSym2Free);
1039         }
1040         free(ThisLibr->filename);
1041         free(ThisLibr->relfil);
1042         ThisLibr2Free=ThisLibr;
1043         ThisLibr=ThisLibr->next;
1044         free(ThisLibr2Free);
1045     }
1046
1047     libr=NULL;
1048 }
1049
1050 #else /* INDEXLIB */
1051
1052 int
1053 fndsym(char *name)
1054 {
1055     FILE *libfp, *fp;
1056     struct lbname *lbnh;
1057     struct lbfile *lbfh, *lbf;
1058     char relfil[NINPUT+2];
1059     char buf[NINPUT+2];
1060     char symname[NINPUT];
1061     char *path,*str;
1062     char c;
1063     int result;
1064
1065     /*
1066      * Search through every library in the linked list "lbnhead".
1067      */
1068
1069     for (lbnh=lbnhead; lbnh; lbnh=lbnh->next)
1070     {
1071         if ((libfp = fopen(lbnh->libspc, "r")) == NULL)
1072         {
1073             fprintf(stderr, "?ASlink-Error-Cannot open library file %s\n",
1074                 lbnh->libspc);
1075             lkexit(1);
1076         }
1077         path = lbnh->path;
1078
1079         /*
1080          * Read in a line from the library file.
1081          * This is the relative file specification
1082          * for a .REL file in this library.
1083          */
1084
1085         while (fgets(relfil, NINPUT, libfp) != NULL)
1086         {
1087             relfil[NINPUT+1] = '\0';
1088             chop_crlf(relfil);
1089             if (path != NULL)
1090             {
1091                 str = (char *) new (strlen(path)+strlen(relfil)+6);
1092                 strcpy(str,path);
1093 #ifdef  OTHERSYSTEM
1094                 if (strlen(str) && (str[strlen(str)-1] != '/') && (str[strlen(str)-1] != LKDIRSEP))
1095                 {
1096                     strcat(str, LKDIRSEPSTR);
1097                 }
1098 #endif
1099             }
1100             else
1101             {
1102                 str = (char *) new (strlen(relfil) + 5);
1103             }
1104
1105             /*See if this is a library with embedded files*/
1106             if(strcmp(relfil, "<SDCCLIB>")==0)
1107             {
1108                 result=SdccLib(lbnh->libspc, libfp, str, name);
1109                 if(result) return(1); /*Found the symbol*/
1110                 free(str);
1111                 /*The symbol is not in the current library,
1112                 check the next library in the list*/
1113                 break;
1114             }
1115
1116             /*From here down is the support for libraries in the original format*/
1117             if ((relfil[0] == '/') || (relfil[0] == LKDIRSEP))
1118             {
1119                 strcat(str, relfil+1);
1120             }
1121             else
1122             {
1123                 strcat(str, relfil);
1124             }
1125
1126             if(strchr(relfil, FSEPX) == NULL)
1127             {
1128                 sprintf(&str[strlen(str)], "%c%s", FSEPX, LKOBJEXT);
1129             }
1130
1131             if ((fp = fopen(str, "r")) != NULL)
1132             {
1133                 /*
1134                  * Read in the object file.  Look for lines that
1135                  * begin with "S" and end with "D".  These are
1136                  * symbol table definitions.  If we find one, see
1137                  * if it is our symbol.  Make sure we only read in
1138                  * our object file and don't go into the next one.
1139                  */
1140
1141                 while (fgets(buf, NINPUT, fp) != NULL)
1142                 {
1143                     buf[NINPUT+1] = '\0';
1144                     chop_crlf(buf);
1145                     /*
1146                      * Skip everything that's not a symbol record.
1147                      */
1148                     if (buf[0] != 'S')
1149                         continue;
1150
1151                     /*
1152                      * When a 'T line' is found terminate file scan.
1153                      * All 'S line's preceed 'T line's in .REL files.
1154                      */
1155                     if (buf[0] == 'T')
1156                         break;
1157
1158                     sscanf(buf, "S %s %c", symname, &c);
1159
1160                     /*
1161                      * If we find a symbol definition for the
1162                      * symbol we're looking for, load in the
1163                      * file and add it to lbfhead so it gets
1164                      * loaded on pass number 2.
1165                      */
1166                     if (strncmp(symname, name, NCPS) == 0 && c == 'D')
1167                     {
1168                         lbfh = (struct lbfile *) new (sizeof(struct lbfile));
1169                         if (lbfhead == NULL)
1170                         {
1171                             lbfhead = lbfh;
1172                         }
1173                         else
1174                         {
1175                             lbf = lbfhead;
1176                             while (lbf->next)
1177                             {
1178                                 lbf = lbf->next;
1179                             }
1180                             lbf->next = lbfh;
1181                         }
1182
1183                         lbfh->libspc = lbnh->libspc;
1184                         lbfh->filspc = str;
1185                         lbfh->relfil = (char *) new (strlen(relfil) + 1);
1186                         lbfh->offset = -1; /*Stand alone rel file*/
1187                         strcpy(lbfh->relfil,relfil);
1188                         fclose(fp);
1189                         fclose(libfp);
1190
1191                         /* if cdb information required & adb file present */
1192                         if (dflag && dfp)
1193                         {
1194                             FILE *xfp = afile(str,"adb",0); //JCF: Nov 30, 2002
1195                             if (xfp)
1196                             {
1197                                 SaveLinkedFilePath(str);
1198                                 copyfile(dfp,xfp);
1199                                 fclose(xfp);
1200                             }
1201                         }
1202                         loadfile(str);
1203                         return (1);
1204                     }
1205                 } /* Closes while - read object file */
1206                 fclose(fp);
1207             } /* Closes if object file opened OK */
1208             else
1209             {
1210                 fprintf(stderr, "?ASlink-Warning-Cannot open library module %s\n", str);
1211             }
1212             free(str);
1213         } /* Ends while - processing all in libr */
1214         fclose(libfp);
1215     } /* Ends good open of libr file */
1216     return(0);
1217 }
1218
1219 #endif /* INDEXLIB */
1220
1221 void loadfile_SdccLib(char * libspc, char * module, long offset)
1222 {
1223     FILE *fp;
1224
1225 #ifdef __CYGWIN__
1226     char posix_path[PATH_MAX];
1227     void cygwin_conv_to_full_posix_path(char * win_path, char * posix_path);
1228     cygwin_conv_to_full_posix_path(libspc, posix_path);
1229     fp = fopen(posix_path, "r");
1230 #else
1231     fp = fopen(libspc,"r");
1232 #endif
1233
1234     if (fp != NULL)
1235     {
1236         fseek(fp, offset, SEEK_SET);
1237         LoadRel(libspc, fp, module);
1238         fclose(fp);
1239     }
1240     else
1241     {
1242         fprintf(stderr, "?ASlink-Error-Opening library '%s'\n", libspc);
1243         lkexit(1);
1244     }
1245 }
1246
1247 /*)Function VOID    library()
1248  *
1249  *  The function library() links all the library object files
1250  *  contained in the lbfile structures.
1251  *
1252  *  local variables:
1253  *      lbfile  *lbfh       pointer to lbfile structure
1254  *
1255  *  global variables:
1256  *      lbfile  *lbfhead    pointer to first lbfile structure
1257  *
1258  *   functions called:
1259  *      VOID    loadfile    lklibr.c
1260  *
1261  *  side effects:
1262  *      Links all files contained in the lbfile structures.
1263  */
1264
1265 VOID
1266 library(void)
1267 {
1268     struct lbfile *lbfh;
1269
1270     for (lbfh=lbfhead; lbfh; lbfh=lbfh->next)
1271     {
1272         if(lbfh->offset<0)
1273         {
1274             /*Stand alone rel file (original lib format)*/
1275             loadfile(lbfh->filspc);
1276         }
1277         else
1278         {
1279             /*rel file embedded in lib (new lib format)*/
1280             loadfile_SdccLib(lbfh->libspc, lbfh->relfil, lbfh->offset);
1281         }
1282     }
1283 #ifdef INDEXLIB
1284     freelibraryindex();
1285 #endif
1286 }
1287
1288 /*)Function VOID    loadfile(filspc)
1289  *
1290  *      char    *filspc     library object file specification
1291  *
1292  *  The function loadfile() links the library object module.
1293  *
1294  *  local variables:
1295  *      FILE    *fp         file handle
1296  *      int     i           input line length
1297  *      char    str[]       file input line
1298  *
1299  *  global variables:
1300  *      char    *ip         pointer to linker input string
1301  *
1302  *   functions called:
1303  *      int     fclose()    c_library
1304  *      int     fgets()     c_library
1305  *      FILE *  fopen()     c_library
1306  *      VOID    link_main() lkmain.c
1307  *      int     strlen()    c_library
1308  *
1309  *  side effects:
1310  *      If file exists it is linked.
1311  */
1312
1313 VOID
1314 loadfile(char *filspc)
1315 {
1316     FILE *fp;
1317     char str[NINPUT+2];
1318
1319 #ifdef __CYGWIN__
1320     char posix_path[PATH_MAX];
1321     void cygwin_conv_to_full_posix_path(char * win_path, char * posix_path);
1322     cygwin_conv_to_full_posix_path(filspc, posix_path);
1323     fp = fopen(posix_path, "r");
1324 #else
1325     fp = fopen(filspc,"r");
1326 #endif
1327
1328     if (fp != NULL)
1329     {
1330         while (fgets(str, NINPUT, fp) != NULL)
1331         {
1332             str[NINPUT+1] = '\0';
1333             chop_crlf(str);
1334             ip = str;
1335             link_main();
1336         }
1337         fclose(fp);
1338     }
1339     else
1340     {
1341         fprintf(stderr, "?ASlink-Error-Opening library '%s'\n", filspc);
1342         lkexit(1);
1343     }
1344 }