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