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