db86ef43a769220ba2fd3add28de647b85d07477
[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         while (ThisLibr)
665     {
666                 /* Iterate through all symbols in an object file */
667                 ThisSym = ThisLibr->symbols->next;
668
669                 while (ThisSym)
670         {
671             //printf("ThisSym->name=%s\n", ThisSym->name);
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                     #ifdef SDK
801                     sprintf(This->filename, "%s%s%co", DirLib, ModName, FSEPX);
802                     #else /* SDK */
803                     sprintf(This->filename, "%s%s%crel", DirLib, ModName, FSEPX);
804                     #endif /* SDK */
805
806                     This->str=This->filename;
807
808                                         ThisSym = This->symbols = (pmlibrarysymbol)malloc( sizeof(mlibrarysymbol));
809                                         ThisSym->next = NULL;
810                                 }
811                 else if(EQ(FLine, "</INDEX>"))
812                                 {
813                                         return This; /*Finish, get out of here*/
814                                 }
815             break;
816             case 2:
817                 if(EQ(FLine, "</MODULE>"))
818                                 {
819                                         This->loaded=0;
820                                         /*Create the index for the next module*/
821                     state=1;
822                                 }
823                 else
824                                 {
825                                         /*Add the symbols*/
826                                         ThisSym->next = (pmlibrarysymbol)malloc(sizeof(mlibrarysymbol));
827                                         ThisSym=ThisSym->next;
828                                         if (ThisSym == NULL)
829                     {
830                                                 printf("panic: can't allocate memory.\n");
831                                                 exit(-2);
832                                         }
833                                         ThisSym->next=NULL;
834                                         strcpy(ThisSym->name, FLine);
835                 }
836             break;
837                         
838                         default:
839                                 return This; /*State machine should never reach this point, but just in case...*/
840                         break;
841         }
842     }
843
844         return This; /*State machine should never reach this point, but just in case...*/
845 }
846
847
848 /* buildlibraryindex - build an in-memory cache of the symbols contained in
849  *                      the libraries
850  */
851 int buildlibraryindex(void)
852 {
853         FILE *libfp, *fp;
854         struct lbname *lbnh;
855         char relfil[NINPUT+2], *str, *path;
856         char buf[NINPUT+2], c;
857         char symname[NINPUT+2];
858         pmlibraryfile This;
859         pmlibrarysymbol ThisSym;
860
861         This=&libr;
862
863         /*
864          * Search through every library in the linked list "lbnhead".
865          */
866
867     for (lbnh=lbnhead; lbnh; lbnh=lbnh->next)
868     {
869                 if ((libfp = fopen(lbnh->libspc, "r")) == NULL)
870                 {
871                         fprintf(stderr, "Cannot open library file %s\n",
872                                 lbnh->libspc);
873                         lkexit(1);
874                 }
875                 path = lbnh->path;
876
877                 /*
878                  * Read in a line from the library file.
879                  * This is the relative file specification
880                  * for a .REL file in this library.
881                  */
882
883         while (fgets(relfil, NINPUT, libfp) != NULL)
884         {
885             relfil[NINPUT+1] = '\0';
886             chop_crlf(relfil);
887             if (path != NULL)
888             {
889                                 str = (char *)new(strlen(path)+strlen(relfil)+6);
890                                 strcpy(str,path);
891 #ifdef  OTHERSYSTEM
892                                 if (str[strlen(str)-1] != '/')
893                                 {
894                                         strcat(str,"/");
895                                 }
896 #endif
897                         }
898             else
899             {
900                                 str = (char *)new(strlen(relfil) + 5);
901                         }
902
903             if(strcmp(relfil, "<SDCCLIB>")==0)
904                         {
905                 /*Get the built in index of a library*/
906                                 This=buildlibraryindex_SdccLib(lbnh->libspc, libfp, str, This);
907                                 free(str);
908                                 fclose(libfp);
909                                 break; /*get the index for next library*/
910                         }
911                 
912             /*From here down, build the index for the original library format*/
913
914                         if (relfil[0] == '\\')
915             {
916                                 strcat(str,relfil+1);
917                         }
918             else
919             {
920                                 strcat(str,relfil);
921                         }
922
923             if(strchr(str, FSEPX) == NULL)
924             {
925                                 sprintf(&str[strlen(str)], "%crel", FSEPX);
926                         }
927                 
928             if ((fp = fopen(str, "r")) != NULL)
929             {
930                 /* Opened OK - create a new libraryfile object for it */
931                 This->next = (pmlibraryfile)new( sizeof( mlibraryfile ));
932                 if (This->next == NULL)
933                 {
934                         printf("panic: can't allocate memory.\n");
935                         exit(-1);
936                 }
937
938                             This=This->next;
939                             This->next = NULL;
940                             This->loaded=-1;
941                 This->offset=-1; /*There should be a rel file*/
942
943                                 strcpy( This->filename, str );
944
945                                 ThisSym = This->symbols = (pmlibrarysymbol)malloc( sizeof(mlibrarysymbol));
946                                 ThisSym->next = NULL;
947
948                                 /*
949                                  * Read in the object file.  Look for lines that
950                                  * begin with "S" and end with "D".  These are
951                                  * symbol table definitions.  If we find one, see
952                                  * if it is our symbol.  Make sure we only read in
953                                  * our object file and don't go into the next one.
954                                  */
955                 
956                                 while (fgets(buf, NINPUT, fp) != NULL)
957                 {
958                                         buf[NINPUT+1] = '\0';
959                                         buf[strlen(buf) - 1] = '\0';
960
961                                         /*
962                                          * Skip everything that's not a symbol record.
963                                          */
964                                         if (buf[0] != 'S') continue;
965
966                                         /*
967                                          * When a 'T line' is found terminate file scan.
968                                          * All 'S line's preceed 'T line's in .REL files.
969                                          */
970                                         if (buf[0] == 'T') break;
971
972                                         sscanf(buf, "S %s %c", symname, &c);
973
974                                         /* If it's an actual symbol, record it */
975                                 if (c == 'D')
976                     {
977                                                 ThisSym->next = (pmlibrarysymbol)malloc(sizeof(mlibrarysymbol));
978                                                 ThisSym=ThisSym->next;
979                                                 if (ThisSym == NULL)
980                         {
981                                                         printf("panic: can't allocate memory.\n");
982                                                         exit(-2);
983                                                 }
984                                                 This->loaded=0;
985                                                 ThisSym->next=NULL;
986                                                 This->str = str;
987                                                 strcpy(This->relfil,relfil);
988                                                 strcpy(ThisSym->name, symname);
989                                                 This->libspc = lbnh->libspc;
990                                         }
991                                 } /* Closes while - read object file */
992                                 fclose(fp);
993                         } /* Closes if object file opened OK */
994                 } /* Ends while - processing all in libr */
995                 fclose(libfp);
996         } /* Ends good open of libr file */
997         return 0;
998 }
999 #else /* INDEXLIB */
1000
1001 int
1002 fndsym(name)
1003 char *name;
1004 {
1005         FILE *libfp, *fp;
1006         struct lbname *lbnh;
1007         struct lbfile *lbfh, *lbf;
1008         char relfil[NINPUT+2];
1009         char buf[NINPUT+2];
1010         char symname[NINPUT];
1011         char *path,*str;
1012         char c;
1013         int result;
1014
1015         /*
1016          * Search through every library in the linked list "lbnhead".
1017          */
1018
1019         for (lbnh=lbnhead; lbnh; lbnh=lbnh->next)
1020         {
1021                 if ((libfp = fopen(lbnh->libspc, "r")) == NULL)
1022                 {
1023                         fprintf(stderr, "Cannot open library file %s\n",
1024                                 lbnh->libspc);
1025                         lkexit(1);
1026                 }
1027                 path = lbnh->path;
1028
1029                 /*
1030                  * Read in a line from the library file.
1031                  * This is the relative file specification
1032                  * for a .REL file in this library.
1033                  */
1034
1035                 while (fgets(relfil, NINPUT, libfp) != NULL)
1036                 {
1037                     relfil[NINPUT+1] = '\0';
1038                     chop_crlf(relfil);
1039                     if (path != NULL)
1040                         {
1041                                 str = (char *) new (strlen(path)+strlen(relfil)+6);
1042                                 strcpy(str,path);
1043 #ifdef  OTHERSYSTEM
1044                                 if (str[strlen(str)-1] != '/')
1045                                 {
1046                                         strcat(str,"/");
1047                                 }
1048 #endif
1049                     }
1050                         else
1051                         {
1052                                 str = (char *) new (strlen(relfil) + 5);
1053                     }
1054
1055                         if(strcmp(relfil, "<SDCCLIB>")==0)
1056                         {
1057                                 result=SdccLib(lbnh->libspc, libfp, str, name);
1058                                 fclose(libfp);
1059                                 if(result) return(1); /*Found the symbol*/
1060                                 free(str);
1061                                 /*The symbol is not in the current library,
1062                                 check the next library in the list*/
1063                                 break; 
1064                         }
1065
1066                         /*From here down is the support for libraries in the original format*/
1067                         if (relfil[0] == '\\')
1068                         {
1069                                 strcat(str,relfil+1);
1070                     }
1071                         else
1072                         {
1073                                 strcat(str,relfil);
1074                     }
1075                     
1076                         if(strchr(relfil, FSEPX) == NULL)
1077                         {
1078                                 sprintf(&str[strlen(str)], "%crel", FSEPX);
1079                     }
1080
1081                         if ((fp = fopen(str, "r")) != NULL)
1082                         {
1083
1084                                 /*
1085                                  * Read in the object file.  Look for lines that
1086                                  * begin with "S" and end with "D".  These are
1087                                  * symbol table definitions.  If we find one, see
1088                                  * if it is our symbol.  Make sure we only read in
1089                                  * our object file and don't go into the next one.
1090                                  */
1091                         
1092                                 while (fgets(buf, NINPUT, fp) != NULL)
1093                                 {
1094                                         buf[NINPUT+1] = '\0';
1095                                         chop_crlf(buf);
1096                                         /*
1097                                          * Skip everything that's not a symbol record.
1098                                          */
1099                                         if (buf[0] != 'S') continue;
1100
1101                                         /*
1102                                         * When a 'T line' is found terminate file scan.
1103                                         * All 'S line's preceed 'T line's in .REL files.
1104                                         */
1105                                         if (buf[0] == 'T') break;
1106
1107                                         sscanf(buf, "S %s %c", symname, &c);
1108
1109                                         /*
1110                                         * If we find a symbol definition for the
1111                                         * symbol we're looking for, load in the
1112                                         * file and add it to lbfhead so it gets
1113                                         * loaded on pass number 2.
1114                                         */
1115                                         if (strncmp(symname, name, NCPS) == 0 && c == 'D')
1116                                         {
1117                                                 lbfh = (struct lbfile *) new (sizeof(struct lbfile));
1118                                                 if (lbfhead == NULL)
1119                                                 {
1120                                                         lbfhead = lbfh;
1121                                                 }
1122                                                 else
1123                                                 {
1124                                                         lbf = lbfhead;
1125                                                         while (lbf->next)
1126                                                         lbf = lbf->next;
1127                                                         lbf->next = lbfh;
1128                                                 }
1129
1130                                                 lbfh->libspc = lbnh->libspc;
1131                                                 lbfh->filspc = str;
1132                                                 lbfh->relfil = (char *) new (strlen(relfil) + 1);
1133                                                 lbfh->offset = -1; /*Stand alone rel file*/
1134                                                 strcpy(lbfh->relfil,relfil);
1135                                                 fclose(fp);
1136                                                 fclose(libfp);                 
1137                         
1138                                                 /* if cdb information required & adb file present */
1139                                                 if (dflag && dfp)
1140                                                 {
1141                                                         FILE *xfp = afile(str,"adb",0); //JCF: Nov 30, 2002
1142                                                         if (xfp)
1143                                                         {
1144                                                                 SaveLinkedFilePath(str);
1145                                                                 copyfile(dfp,xfp);
1146                                                                 fclose(xfp);
1147                                                         }
1148                                                 }
1149                                                 loadfile(str);
1150                                                 return (1);
1151                                         }
1152                                 }
1153                                 fclose(fp);
1154                         }
1155                         free(str);
1156                 }
1157                 fclose(libfp);
1158         }
1159         return(0);
1160 }
1161
1162 #endif /*INDEXLIB*/
1163
1164 void loadfile_SdccLib(char * libspc, char * module, long offset)
1165 {
1166         FILE *fp;
1167
1168         if ((fp = fopen(libspc,"r")) != NULL)
1169         {
1170                 fseek(fp, offset, SEEK_SET);
1171                 LoadRel(fp, module);
1172                 fclose(fp);
1173         }
1174 }
1175
1176 /*)Function     VOID    library()
1177  *
1178  *      The function library() links all the library object files
1179  *      contained in the lbfile structures.
1180  *
1181  *      local variables:
1182  *              lbfile  *lbfh           pointer to lbfile structure
1183  *
1184  *      global variables:
1185  *              lbfile  *lbfhead        pointer to first lbfile structure
1186  *
1187  *       functions called:
1188  *              VOID    loadfile        lklibr.c
1189  *
1190  *      side effects:
1191  *              Links all files contained in the lbfile structures.
1192  */
1193
1194 VOID
1195 library()
1196 {
1197         struct lbfile *lbfh;
1198
1199         for (lbfh=lbfhead; lbfh; lbfh=lbfh->next)
1200         {
1201                 if(lbfh->offset<0)
1202                 {
1203                         /*Stand alone rel file (original lib format)*/
1204                         loadfile(lbfh->filspc);
1205                 }
1206                 else
1207                 {
1208                         /*rel file embedded in lib (new lib format)*/
1209                         loadfile_SdccLib(lbfh->libspc, lbfh->relfil, lbfh->offset);
1210                 }
1211         }
1212 }
1213
1214 /*)Function     VOID    loadfile(filspc)
1215  *
1216  *              char    *filspc         library object file specification
1217  *
1218  *      The function loadfile() links the library object module.
1219  *
1220  *      local variables:
1221  *              FILE    *fp             file handle
1222  *              int     i               input line length
1223  *              char    str[]           file input line
1224  *
1225  *      global variables:
1226  *              char    *ip             pointer to linker input string
1227  *
1228  *       functions called:
1229  *              int     fclose()        c_library
1230  *              int     fgets()         c_library
1231  *              FILE *  fopen()         c_library
1232  *              VOID    link_main()     lkmain.c
1233  *              int     strlen()        c_library
1234  *
1235  *      side effects:
1236  *              If file exists it is linked.
1237  */
1238
1239 VOID
1240 loadfile(filspc)
1241 char *filspc;
1242 {
1243         FILE *fp;
1244         char str[NINPUT+2];
1245
1246         if ((fp = fopen(filspc,"r")) != NULL) {
1247                 while (fgets(str, NINPUT, fp) != NULL) {
1248                         str[NINPUT+1] = '\0';
1249                         chop_crlf(str);
1250                         ip = str;
1251                         link_main();
1252                 }
1253                 fclose(fp);
1254         }
1255 }