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