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