* as/hc08/lkaomf51.c (OutputName): made name unsigned char,
[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 (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] == '/')
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));
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 (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 (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 }
1302