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