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