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