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