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