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