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