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