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