When checking for duplicated modules use absolute library paths
[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 "aslink.h"
29
30 #ifdef  OTHERSYSTEM
31 #ifdef SDK
32 #ifdef UNIX
33     #define LKDIRSEP '/'
34     #define LKDIRSEPSTR "/"
35 #else /* UNIX */
36         #define LKDIRSEP '\\'
37         #define LKDIRSEPSTR "\\"
38 #endif /* UNIX */
39 #else /* SDK */
40         #define LKDIRSEP '\\'
41         #define LKDIRSEPSTR "\\"
42 #endif /* SDK */
43 #endif
44
45 #ifdef __CYGWIN__
46 void ToCygWin(char * filspc)
47 {
48     char posix_path[PATH_MAX];
49     void cygwin_conv_to_full_posix_path(char * win_path, char * posix_path);
50     cygwin_conv_to_full_posix_path(filspc, posix_path);
51     strcpy(filspc, posix_path);
52 }
53 #endif
54
55 /*)Module       lklibr.c
56  *
57  *      The module lklibr.c contains the functions which
58  *      (1) specify the path(s) to library files [.LIB]
59  *      (2) specify the library file(s) [.LIB] to search
60  *      (3) search the library files for specific symbols
61  *          and link the module containing this symbol
62  *
63  *      lklibr.c contains the following functions:
64  *              VOID    addpath()
65  *              VOID    addlib()
66  *              VOID    addfile()
67  *              VOID    search()
68  *              VOID    fndsym()
69  *              VOID    library()
70  *              VOID    loadfile()
71  *
72  */
73
74 #ifdef INDEXLIB
75 typedef struct slibrarysymbol mlibrarysymbol;
76 typedef struct slibrarysymbol *pmlibrarysymbol;
77
78 struct slibrarysymbol {
79         char name[NCPS];
80         pmlibrarysymbol next;
81 };
82
83 typedef struct slibraryfile mlibraryfile;
84 typedef struct slibraryfile *pmlibraryfile;
85
86 struct slibraryfile {
87         int loaded;
88         char *libspc;
89         char *str;
90         char relfil[FILSPC];
91         char filename[FILSPC];
92     long offset; //if > 0, the embedded file offset in the library file libspc
93         pmlibrarysymbol symbols;
94         pmlibraryfile next;
95 };
96
97 int buildlibraryindex();
98 #endif /* INDEXLIB */
99
100 /*)Function     VOID    addpath()
101  *
102  *      The function addpath() creates a linked structure containing
103  *      the paths to various object module library files.
104  *
105  *      local variables:
106  *              lbpath  *lbph           pointer to new path structure
107  *              lbpath  *lbp            temporary pointer
108  *
109  *      global variables:
110  *              lbpath  *lbphead        The pointer to the first
111  *                                      path structure
112  *
113  *       functions called:
114  *              char    getnb()         lklex.c
115  *              VOID *  new()           lksym.c
116  *              int     strlen()        c_library
117  *              char *  strcpy()        c_library
118  *              VOID    unget()         lklex.c
119  *
120  *      side effects:
121  *              An lbpath structure may be created.
122  */
123
124 VOID
125 addpath()
126 {
127         struct lbpath *lbph, *lbp;
128
129         lbph = (struct lbpath *) new (sizeof(struct lbpath));
130         if (lbphead == NULL) {
131                 lbphead = lbph;
132         } else {
133                 lbp = lbphead;
134                 while (lbp->next)
135                         lbp = lbp->next;
136                 lbp->next = lbph;
137         }
138         unget(getnb());
139         lbph->path = (char *) new (strlen(ip)+1);
140         strcpy(lbph->path, ip);
141 }
142
143 /*)Function     VOID    addlib()
144  *
145  *      The function addlib() tests for the existance of a
146  *      library path structure to determine the method of
147  *      adding this library file to the library search structure.
148  *
149  *      This function calls the function addfile() to actually
150  *      add the library file to the search list.
151  *
152  *      local variables:
153  *              lbpath  *lbph           pointer to path structure
154  *
155  *      global variables:
156  *              lbpath  *lbphead        The pointer to the first
157  *                                      path structure
158  *      ip a pointer to the library name
159  *
160  *       functions called:
161  *              VOID    addfile()       lklibr.c
162  *              char    getnb()         lklex.c
163  *              VOID    unget()         lklex.c
164  *
165  *      side effects:
166  *              The function addfile() may add the file to
167  *              the library search list.
168  */
169
170 VOID
171 addlib()
172 {
173         struct lbpath *lbph;
174     int foundcount=0;
175
176         unget(getnb());
177
178         if (lbphead == NULL)
179     {
180                 foundcount=addfile(NULL, ip);
181         }
182     else
183     {
184             for (lbph=lbphead; lbph; lbph=lbph->next)
185         {
186                     foundcount+=addfile(lbph->path, ip);
187             }
188     }
189     if(foundcount == 0)
190     {
191         printf("\n?ASlink-Warning-Couldn't find library '%s'", ip);
192     }
193 }
194
195 /*)Function     int     addfile(path,libfil)
196  *
197  *              char    *path           library path specification
198  *              char    *libfil         library file specification
199  *
200  *      The function addfile() searches for the library file
201  *      by concatenating the path and libfil specifications.
202  *      if the library is found, an lbname structure is created
203  *      and linked to any previously defined structures.  This
204  *      linked list is used by the function fndsym() to attempt
205  *      to find any undefined symbols.
206  *
207  *      The function does not give report an error on invalid
208  *      path / file specifications or if the file is not found.
209  *
210  *      local variables:
211  *              lbname  *lbnh           pointer to new name structure
212  *              lbname  *lbn            temporary pointer
213  *
214  *      global variables:
215  *              lbname  *lbnhead        The pointer to the first
216  *                                      path structure
217  *
218  *       functions called:
219  *              char    getnb()         lklex.c
220  *              VOID *  new()           lksym.c
221  *              int     strlen()        c_library
222  *              char *  strcpy()        c_library
223  *              VOID    unget()         lklex.c
224  *
225  *      side effects:
226  *              An lbname structure may be created.
227  *
228  *  return:
229  *      1: the library was found
230  *      0: the library was not found
231  */
232
233 int addfile(char * path, char * libfil)
234 {
235         FILE *fp;
236         char *str;
237         struct lbname *lbnh, *lbn;
238     int libfilinc=0;
239
240         if (path != NULL)
241     {
242                 str = (char *) new (strlen(path) + strlen(libfil) + 6);
243                 strcpy(str, path);
244
245         if (str[strlen(str)-1] != LKDIRSEP)
246         {
247                         strcat(str, LKDIRSEPSTR);
248                 }
249         }
250     else
251     {
252                 str = (char *) new (strlen(libfil) + 5);
253         }
254
255         if (libfil[0] == LKDIRSEP)
256     {
257         libfil++;
258         libfilinc=1;
259     }
260         
261     strcat(str, libfil);
262
263         if(strchr(libfil, FSEPX) == NULL)
264     {
265                 sprintf(&str[strlen(str)], "%clib", FSEPX);
266         }
267
268     fp=fopen(str, "r");
269     if(fp == NULL)
270     {
271         /*Ok, that didn't work.  Try with the 'libfil' name only*/
272         if(libfilinc) libfil--;
273         fp=fopen(libfil, "r");
274         if(fp != NULL) 
275         {
276             /*Bingo!  'libfil' is the absolute path of the library*/
277             strcpy(str, libfil);
278             path=NULL;/*This way 'libfil' and 'path' will be rebuilt from 'str'*/
279         }
280     }
281
282     if(path==NULL)
283     {
284         /*'path' can not be null since it is needed to find the '.o' files associated with
285         the library.  So, get 'path' from 'str' and then chop it off and recreate 'libfil'.
286         That way putting 'path' and 'libfil' together will result into the original filepath
287         as contained in 'str'.*/
288         int j;
289         path = (char *) new (strlen(str));
290         strcpy(path, str);
291         for(j=strlen(path)-1; j>=0; j--)
292         {
293             if((path[j]=='\\')||(path[j]=='/'))
294             {
295                 strcpy(libfil, &path[j+1]);
296                 path[j+1]=0;
297                 break;
298             }
299         }
300         if(j<=0) path[0]=0;
301     }
302
303         if (fp != NULL)
304     {
305                 fclose(fp);
306                 lbnh = (struct lbname *) new (sizeof(struct lbname));
307                 if (lbnhead == NULL)
308         {
309                         lbnhead = lbnh;
310                 }
311         else
312         {
313                         lbn = lbnhead;
314                         while (lbn->next)
315                                 lbn = lbn->next;
316                         lbn->next = lbnh;
317                 }
318
319                 lbnh->path = path;
320                 lbnh->libfil = (char *) new (strlen(libfil) + 1);
321                 strcpy(lbnh->libfil, libfil);
322                 lbnh->libspc = str;
323         return 1;
324         }
325     else
326     {
327                 free(str);
328         return 0;
329         }
330 }
331
332 /*)Function     VOID    search()
333  *
334  *      The function search() looks through all the symbol tables
335  *      at the end of pass 1.  If any undefined symbols are found
336  *      then the function fndsym() is called. Function fndsym()
337  *      searches any specified library files to automagically
338  *      import the object modules containing the needed symbol.
339  *
340  *      After a symbol is found and imported by the function
341  *      fndsym() the symbol tables are again searched.  The
342  *      symbol tables are search until no more symbols can be
343  *      resolved within the library files.  This ensures that
344  *      back references from one library module to another are
345  *      also resolved.
346  *
347  *      local variables:
348  *              int     i               temporary counter
349  *              sym     *sp             pointer to a symbol structure
350  *              int     symfnd          found a symbol flag
351  *
352  *      global variables:
353  *              sym     *symhash[]      array of pointers to symbol tables
354  *
355  *       functions called:
356  *              int     fndsym()        lklibr.c
357  *
358  *      side effects:
359  *              If a symbol is found then the library object module
360  *              containing the symbol will be imported and linked.
361  */
362
363 VOID
364 search()
365 {
366         register struct sym *sp;
367         register int i, symfnd;
368
369         /*
370          * Look for undefined symbols.  Keep
371          * searching until no more symbols are resolved.
372          */
373         symfnd = 1;
374         while (symfnd) {
375                 symfnd = 0;
376                 /*
377                  * Look through all the symbols
378                  */
379                 for (i=0; i<NHASH; ++i) {
380                         sp = symhash[i];
381                         while (sp) {
382                                 /* If we find an undefined symbol
383                                  * (one where S_DEF is not set), then
384                                  * try looking for it.  If we find it
385                                  * in any of the libraries then
386                                  * increment symfnd.  This will force
387                                  * another pass of symbol searching and
388                                  * make sure that back references work.
389                                  */
390                                 if ((sp->s_type & S_DEF) == 0) {
391                                         if (fndsym(sp->s_id)) {
392                                                 symfnd++;
393                                         }
394                                 }
395                                 sp = sp->s_sp;
396                         }
397                 }
398         }
399 }
400
401 /*Load a .rel file embedded in a sdcclib file*/
402 void LoadRel(FILE * libfp, char * ModName)
403 {
404         char str[NINPUT+2];
405         int state=0;
406
407         while (fgets(str, NINPUT, libfp) != NULL)
408         {
409                 str[NINPUT+1] = '\0';
410                 chop_crlf(str);
411                 switch(state)
412                 {
413                         case 0:
414                                 if(EQ(str, "<FILE>"))
415                                 {
416                                         fgets(str, NINPUT, libfp);
417                                         str[NINPUT+1] = '\0';
418                                         chop_crlf(str);
419                                         if(EQ(str, ModName)) state=1;
420                                         else
421                                         {
422                                                 printf("Bad offset in library file str=%s, Modname=%s\n", str, ModName);
423                                                 lkexit(1);
424                                         }
425                                 }
426                         break;
427                         case 1:
428                                 if(EQ(str, "<REL>")) state=2;
429                         break;
430                         case 2:
431                                 if(EQ(str, "</REL>")) return;
432                                 ip = str;
433                                 link();
434                         break;
435                 }
436         }
437 }
438
439 /*)Function     VOID    fndsym(name)
440  *
441  *              char    *name           symbol name to find
442  *
443  *      The function fndsym() searches through all combinations of the
444  *      library path specifications (input by the -k option) and the
445  *      library file specifications (input by the -l option) that
446  *      lead to an existing file.
447  *
448  *      The file specicifation may be formed in one of two ways:
449  *
450  *      (1)     If the library file contained an absolute
451  *              path/file specification then this becomes filspc.
452  *              (i.e. C:\...)
453  *
454  *      (2)     If the library file contains a relative path/file
455  *              specification then the concatenation of the path
456  *              and this file specification becomes filspc.
457  *              (i.e. \...)
458  *
459  *      The structure lbfile is created for the first library
460  *      object file which contains the definition for the
461  *      specified undefined symbol.
462  *
463  *      If the library file [.LIB] contains file specifications for
464  *      non existant files, no errors are returned.
465  *
466  *      local variables:
467  *              char    buf[]           [.REL] file input line
468  *              char    c               [.REL] file input character
469  *              FILE    *fp             file handle for object file
470  *              lbfile  *lbf            temporary pointer
471  *              lbfile  *lbfh           pointer to lbfile structure
472  *              FILE    *libfp          file handle for library file
473  *              lbname  *lbnh           pointer to lbname structure
474  *              char    *path           file specification path
475  *              char    relfil[]        [.REL] file specification
476  *              char    *str            combined path and file specification
477  *              char    symname[]       [.REL] file symbol string
478  *
479  *      global variables:
480  *              lbname  *lbnhead        The pointer to the first
481  *                                      name structure
482  *              lbfile  *lbfhead        The pointer to the first
483  *                                      file structure
484  *
485  *       functions called:
486  *              int     fclose()        c_library
487  *              int     fgets()         c_library
488  *              FILE    *fopen()        c_library
489  *              VOID    free()          c_library
490  *              char    getnb()         lklex.c
491  *              VOID    lkexit()        lkmain.c
492  *              VOID    loadfile()      lklibr.c
493  *              VOID *  new()           lksym.c
494  *              char *  sprintf()       c_library
495  *              int     sscanf()        c_library
496  *              char *  strcat()        c_library
497  *              char *  strchr()        c_library
498  *              char *  strcpy()        c_library
499  *              int     strlen()        c_library
500  *              int     strncmp()       c_library
501  *              VOID    unget()         lklex.c
502  *
503  *      side effects:
504  *              If the symbol is found then a new lbfile structure
505  *              is created and added to the linked list of lbfile
506  *              structures.  The file containing the found symbol
507  *              is linked.
508  */
509
510 #ifdef INDEXLIB
511
512 /* First entry in the library object symbol cache */
513 mlibraryfile libr;
514
515 int fndsym( char *name )
516 {
517         struct lbfile *lbfh, *lbf;
518         pmlibraryfile ThisLibr;
519         pmlibrarysymbol ThisSym = NULL;
520
521     pmlibraryfile FirstFound;
522     int numfound=0;
523
524         /* Build the index if this is the first call to fndsym */
525         if (libr.next==NULL)
526                 buildlibraryindex();
527         
528         /* Iterate through all library object files */
529         ThisLibr = libr.next;
530     FirstFound = libr.next; /*So gcc stops whining*/
531         while (ThisLibr)
532     {
533                 /* Iterate through all symbols in an object file */
534                 ThisSym = ThisLibr->symbols->next;
535
536                 while (ThisSym)
537         {
538             //printf("ThisSym->name=%s\n", ThisSym->name);
539                         if (!strcmp(ThisSym->name, name))
540             {
541                                 if ((!ThisLibr->loaded) && (numfound==0))
542                 {
543                                         /* Object file is not loaded - add it to the list */
544                                         lbfh = (struct lbfile *) new (sizeof(struct lbfile));
545                                         if (lbfhead == NULL)
546                     {
547                                                 lbfhead = lbfh;
548                                         }
549                     else
550                     {
551                                                 lbf = lbfhead;
552                                                 while (lbf->next)
553                                                 lbf = lbf->next;
554                                                 lbf->next = lbfh;
555                                         }
556                                         lbfh->libspc = ThisLibr->libspc;
557                                         lbfh->filspc = ThisLibr->str;
558                                         lbfh->relfil = (char *) new (strlen(ThisLibr->relfil) + 1);
559                                         strcpy(lbfh->relfil,ThisLibr->relfil);
560                     lbfh->offset = ThisLibr->offset;
561                     if(lbfh->offset>0)
562                     { /*For an embedded object file in a library*/
563                         void loadfile_SdccLib(char * libspc, char * module, long offset);
564                         loadfile_SdccLib(lbfh->libspc, lbfh->relfil, lbfh->offset);
565                     }
566                     else
567                     { /*For a stand alone object file*/
568                                             loadfile(lbfh->filspc);
569                     }
570                                         ThisLibr->loaded=1;
571                                 }
572
573                 if(numfound==0)
574                 {
575                     numfound++;
576                     FirstFound=ThisLibr;
577                 }
578                 else
579                 {
580                     char absPath1[PATH_MAX];
581                     char absPath2[PATH_MAX];
582 #if defined(__BORLANDC__) || defined(_MSC_VER)
583                     int j;
584
585                     _fullpath(absPath1, FirstFound->libspc, PATH_MAX);
586                     _fullpath(absPath2, ThisLibr->libspc, PATH_MAX);
587                     for(j=0; absPath1[j]!=0; j++) absPath1[j]=tolower(absPath1[j]);
588                     for(j=0; absPath2[j]!=0; j++) absPath2[j]=tolower(absPath2[j]);
589 #else
590                     realpath(FirstFound->libspc, absPath1);
591                     realpath(ThisLibr->libspc, absPath2);
592 #endif
593                     if( !( EQ(absPath1, absPath2) && EQ(FirstFound->relfil, ThisLibr->relfil) ) )
594                     {
595                         if(numfound==1)
596                         {
597                             printf("?Aslink-Warning-Definition of public symbol '%s'"
598                                    " found more than once:\n", name);
599                             printf("   Library: '%s', Module: '%s'\n",
600                                     FirstFound->libspc, FirstFound->relfil);
601                         }
602                         printf("   Library: '%s', Module: '%s'\n",
603                                 ThisLibr->libspc, ThisLibr->relfil);
604                         numfound++;
605                     }
606                 }
607                         }
608                         ThisSym=ThisSym->next;  /* Next sym in library */
609                 }
610                 ThisLibr=ThisLibr->next; /* Next library in list */
611         }
612         return numfound;
613 }
614
615 pmlibraryfile buildlibraryindex_SdccLib(char * PathLib, FILE * libfp, char * DirLib, pmlibraryfile This)
616 {
617         char ModName[NCPS]="";
618         char FLine[MAXLINE+1];
619         int state=0;
620         long IndexOffset=0, FileOffset;
621     pmlibrarysymbol ThisSym = NULL;
622
623         while(!feof(libfp))
624     {
625         FLine[0]=0;
626         fgets(FLine, MAXLINE, libfp);
627         chop_crlf(FLine);
628
629         switch(state)
630         {
631             case 0:
632                 if(EQ(FLine, "<INDEX>"))
633                 {
634                                         /*The next line has the size of the index*/
635                     FLine[0]=0;
636                     fgets(FLine, MAXLINE, libfp);
637                     chop_crlf(FLine);
638                                         IndexOffset=atol(FLine);
639                                         state=1;
640                 }
641             break;
642             case 1:
643                 if(EQ(FLine, "<MODULE>"))
644                                 {
645                                         /*The next line has the name of the module and the offset
646                                         of the corresponding embedded file in the library*/
647                     FLine[0]=0;
648                     fgets(FLine, MAXLINE, libfp);
649                     chop_crlf(FLine);
650                                         sscanf(FLine, "%s %ld", ModName, &FileOffset);
651                                         state=2;
652
653                     /*create a new libraryfile object for this module*/
654                                         This->next = (pmlibraryfile)new( sizeof( mlibraryfile ));
655                                         if (This->next == NULL)
656                     {
657                                                 printf("panic: can't allocate memory.\n");
658                                                 exit(-1);
659                                         }
660
661                                         This=This->next;
662                                         This->next = NULL;
663                                         This->loaded=-1; /*Kind of useless, but...*/
664                     This->offset=FileOffset+IndexOffset;
665                                         This->libspc=PathLib;
666                                         strcpy(This->relfil, ModName);
667
668                     #ifdef SDK
669                     sprintf(This->filename, "%s%s%co", DirLib, ModName, FSEPX);
670                     #else /* SDK */
671                     sprintf(This->filename, "%s%s%crel", DirLib, ModName, FSEPX);
672                     #endif /* SDK */
673
674                     This->str=This->filename;
675
676                                         ThisSym = This->symbols = (pmlibrarysymbol)malloc( sizeof(mlibrarysymbol));
677                                         ThisSym->next = NULL;
678                                 }
679                 else if(EQ(FLine, "</INDEX>"))
680                                 {
681                                         return This; /*Finish, get out of here*/
682                                 }
683             break;
684             case 2:
685                 if(EQ(FLine, "</MODULE>"))
686                                 {
687                                         This->loaded=0;
688                                         /*Create the index for the next module*/
689                     state=1;
690                                 }
691                 else
692                                 {
693                                         /*Add the symbols*/
694                                         ThisSym->next = (pmlibrarysymbol)malloc(sizeof(mlibrarysymbol));
695                                         ThisSym=ThisSym->next;
696                                         if (ThisSym == NULL)
697                     {
698                                                 printf("panic: can't allocate memory.\n");
699                                                 exit(-2);
700                                         }
701                                         ThisSym->next=NULL;
702                                         strcpy(ThisSym->name, FLine);
703                 }
704             break;
705                         
706                         default:
707                                 return This; /*State machine should never reach this point, but just in case...*/
708                         break;
709         }
710     }
711
712         return This; /*State machine should never reach this point, but just in case...*/
713 }
714
715
716 /* buildlibraryindex - build an in-memory cache of the symbols contained in
717  *                      the libraries
718  */
719 int buildlibraryindex(void)
720 {
721         FILE *libfp, *fp;
722         struct lbname *lbnh;
723         char relfil[NINPUT+2], *str, *path;
724         char buf[NINPUT+2], c;
725         char symname[NINPUT+2];
726         pmlibraryfile This;
727         pmlibrarysymbol ThisSym;
728
729         This=&libr;
730
731         /* Iterate through all library files */
732 /*1*/   for (lbnh=lbnhead; lbnh; lbnh=lbnh->next) {
733                 libfp = fopen( lbnh->libspc, "r" );
734                 if (libfp) {
735                         path=lbnh->path;
736
737                         /*
738                          * Read in a line from the library file.
739                          * This is the relative file specification
740                          * for a .REL file in this library.
741                          */
742
743 /*2*/                   while (fgets(relfil, NINPUT, libfp) != NULL) {
744                                 relfil[NINPUT+1] = '\0';
745                                 chop_crlf(relfil);
746                                 if (path != NULL) {
747                                         str = (char *)new(strlen(path)+strlen(relfil)+6);
748                                         strcpy(str,path);
749 #ifdef  OTHERSYSTEM
750 #ifdef SDK
751 #ifdef UNIX
752                                         if (str[strlen(str)-1] != '/') {
753                                                 strcat(str,"/");
754 #else /* UNIX */
755                                         if (str[strlen(str)-1] != '\\') {
756                                                 strcat(str,"\\");
757 #endif /* UNIX */
758 #else /* SDK */
759                                         if (str[strlen(str)-1] != '\\') {
760                                                 strcat(str,"\\");
761 #endif /* SDK */
762                                         }
763 #endif
764                                 } else {
765                                         str = (char *)new(strlen(relfil) + 5);
766                                 }
767
768                 if(strcmp(relfil, "<SDCCLIB>")==0)
769                             {
770                     /*Get the built in index of a library*/
771                                     This=buildlibraryindex_SdccLib(lbnh->libspc, libfp, str, This);
772                                     free(str);
773                                     fclose(libfp);
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                                 fclose(libfp);
1055                                 if(result) return(1); /*Found the symbol*/
1056                                 free(str);
1057                                 /*The symbol is not in the current library,
1058                                 check the next library in the list*/
1059                                 break; 
1060                         }
1061
1062                         /*From here down is the support for libraries in the original format*/
1063 #ifdef SDK
1064 #ifdef UNIX
1065                     if (relfil[0] == '/') {
1066 #else /* UNIX */
1067                     if (relfil[0] == '\\') {
1068 #endif /* UNIX */
1069 #else /* SDK */
1070                     if (relfil[0] == '\\') {
1071 #endif /* SDK */
1072                         strcat(str,relfil+1);
1073                     } else {
1074                         strcat(str,relfil);
1075                     }
1076                     if(strchr(relfil, FSEPX) == NULL) {
1077 #ifdef SDK
1078                         sprintf(&str[strlen(str)], "%co", FSEPX);
1079 #else /* SDK */
1080                         sprintf(&str[strlen(str)], "%crel", FSEPX);
1081 #endif /* SDK */
1082                     }
1083 /*3*/               if ((fp = fopen(str, "r")) != NULL) {
1084
1085                         /*
1086                          * Read in the object file.  Look for lines that
1087                          * begin with "S" and end with "D".  These are
1088                          * symbol table definitions.  If we find one, see
1089                          * if it is our symbol.  Make sure we only read in
1090                          * our object file and don't go into the next one.
1091                          */
1092                         
1093 /*4*/                   while (fgets(buf, NINPUT, fp) != NULL) {
1094
1095                         buf[NINPUT+1] = '\0';
1096                         buf[strlen(buf) - 1] = '\0';
1097
1098                         /*
1099                          * Skip everything that's not a symbol record.
1100                          */
1101                         if (buf[0] != 'S')
1102                                 continue;
1103
1104                         /*
1105                          * When a 'T line' is found terminate file scan.
1106                          * All 'S line's preceed 'T line's in .REL files.
1107                          */
1108                         if (buf[0] == 'T')
1109                                 break;
1110
1111                         sscanf(buf, "S %s %c", symname, &c);
1112
1113                         /*
1114                          * If we find a symbol definition for the
1115                          * symbol we're looking for, load in the
1116                          * file and add it to lbfhead so it gets
1117                          * loaded on pass number 2.
1118                          */
1119 /*5*/                   if (strncmp(symname, name, NCPS) == 0 && c == 'D') {
1120
1121                         lbfh = (struct lbfile *) new (sizeof(struct lbfile));
1122                         if (lbfhead == NULL) {
1123                                 lbfhead = lbfh;
1124                         } else {
1125                                 lbf = lbfhead;
1126                                 while (lbf->next)
1127                                         lbf = lbf->next;
1128                                 lbf->next = lbfh;
1129                         }
1130                         lbfh->libspc = lbnh->libspc;
1131                         lbfh->filspc = str;
1132                         lbfh->relfil = (char *) new (strlen(relfil) + 1);
1133                         lbfh->offset = -1; /*Stand alone rel file*/
1134                         strcpy(lbfh->relfil,relfil);
1135                         fclose(fp);
1136                         fclose(libfp);
1137                         loadfile(str);
1138                         return (1);
1139
1140 /*5*/                   }
1141
1142 /*4*/                   }
1143                     fclose(fp);
1144 /*3*/               }
1145
1146                     free(str);
1147 /*2*/           }
1148                 fclose(libfp);
1149 /*1*/   }
1150         return(0);
1151 }
1152 #endif /* INDEXLIB */
1153
1154 void loadfile_SdccLib(char * libspc, char * module, long offset)
1155 {
1156         FILE *fp;
1157
1158 #ifdef __CYGWIN__
1159     ToCygWin(libspc);
1160 #endif
1161
1162         if ((fp = fopen(libspc,"r")) != NULL)
1163         {
1164                 fseek(fp, offset, SEEK_SET);
1165                 LoadRel(fp, module);
1166                 fclose(fp);
1167         }
1168 }
1169
1170 /*)Function     VOID    library()
1171  *
1172  *      The function library() links all the library object files
1173  *      contained in the lbfile structures.
1174  *
1175  *      local variables:
1176  *              lbfile  *lbfh           pointer to lbfile structure
1177  *
1178  *      global variables:
1179  *              lbfile  *lbfhead        pointer to first lbfile structure
1180  *
1181  *       functions called:
1182  *              VOID    loadfile        lklibr.c
1183  *
1184  *      side effects:
1185  *              Links all files contained in the lbfile structures.
1186  */
1187
1188 VOID
1189 library()
1190 {
1191         struct lbfile *lbfh;
1192
1193         for (lbfh=lbfhead; lbfh; lbfh=lbfh->next)
1194         {
1195                 if(lbfh->offset<0)
1196                 {
1197                         /*Stand alone rel file (original lib format)*/
1198                         loadfile(lbfh->filspc);
1199                 }
1200                 else
1201                 {
1202                         /*rel file embedded in lib (new lib format)*/
1203                         loadfile_SdccLib(lbfh->libspc, lbfh->relfil, lbfh->offset);
1204                 }
1205         }
1206 }
1207
1208 /*)Function     VOID    loadfile(filspc)
1209  *
1210  *              char    *filspc         library object file specification
1211  *
1212  *      The function loadfile() links the library object module.
1213  *
1214  *      local variables:
1215  *              FILE    *fp             file handle
1216  *              int     i               input line length
1217  *              char    str[]           file input line
1218  *
1219  *      global variables:
1220  *              char    *ip             pointer to linker input string
1221  *
1222  *       functions called:
1223  *              int     fclose()        c_library
1224  *              int     fgets()         c_library
1225  *              FILE *  fopen()         c_library
1226  *              VOID    link()          lkmain.c
1227  *              int     strlen()        c_library
1228  *
1229  *      side effects:
1230  *              If file exists it is linked.
1231  */
1232
1233 VOID
1234 loadfile(filspc)
1235 char *filspc;
1236 {
1237         FILE *fp;
1238         char str[NINPUT+2];
1239         int i;
1240
1241 #ifdef __CYGWIN__
1242     ToCygWin(filspc);
1243 #endif
1244
1245         if ((fp = fopen(filspc,"r")) != NULL) {
1246                 while (fgets(str, NINPUT, fp) != NULL) {
1247                         str[NINPUT+1] = '\0';
1248                         i = strlen(str) - 1;
1249                         if (str[i] == '\n')
1250                                 str[i] = '\0';
1251                         ip = str;
1252                         link();
1253                 }
1254                 fclose(fp);
1255         }
1256     else
1257     {
1258         printf("Couldn't find file %s\n", filspc);
1259         exit(-4);
1260     }
1261 }