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