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