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