* as/hc08/lkaomf51.c (OutputName): made name unsigned char,
[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 SDK
47     #define LKOBJEXT "o"
48 #else /* SDK */
49     #define LKOBJEXT "rel"
50 #endif /* SDK */
51
52 /*)Module       lklibr.c
53  *
54  *      The module lklibr.c contains the functions which
55  *      (1) specify the path(s) to library files [.LIB]
56  *      (2) specify the library file(s) [.LIB] to search
57  *      (3) search the library files for specific symbols
58  *          and link the module containing this symbol
59  *
60  *      lklibr.c contains the following functions:
61  *              VOID    addpath()
62  *              VOID    addlib()
63  *              VOID    addfile()
64  *              VOID    search()
65  *              VOID    fndsym()
66  *              VOID    library()
67  *              VOID    loadfile()
68  *
69  */
70
71 #ifdef INDEXLIB
72 typedef struct slibrarysymbol mlibrarysymbol;
73 typedef struct slibrarysymbol *pmlibrarysymbol;
74
75 struct slibrarysymbol {
76         char * name; /*Warning: allocate memory before using*/
77         pmlibrarysymbol next;
78 };
79
80 typedef struct slibraryfile mlibraryfile;
81 typedef struct slibraryfile *pmlibraryfile;
82
83 struct slibraryfile {
84         int loaded;
85         char * libspc;
86         char * relfil; /*Warning: allocate memory before using*/
87         char * filename; /*Warning: allocate memory before using*/
88     long offset; //if > 0, the embedded file offset in the library file libspc
89         pmlibrarysymbol symbols;
90         pmlibraryfile next;
91 };
92
93 /* First entry in the library object symbol cache */
94 pmlibraryfile libr=NULL;
95
96 int buildlibraryindex();
97 void freelibraryindex (void);
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         fprintf(stderr, "\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(char * libfname, 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                                                 fprintf(stderr, "?Aslink-Error-Bad offset in library file %s(%s)\n",
423                             libfname, 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 int fndsym( char *name )
514 {
515         struct lbfile *lbfh, *lbf;
516         pmlibraryfile ThisLibr;
517         pmlibrarysymbol ThisSym = NULL;
518
519     pmlibraryfile FirstFound;
520     int numfound=0;
521
522         /* Build the index if this is the first call to fndsym */
523         if (libr==NULL) buildlibraryindex();
524         
525         /* Iterate through all library object files */
526         ThisLibr = libr;
527     FirstFound = libr; /*So gcc stops whining*/
528         while (ThisLibr)
529     {
530                 /* Iterate through all symbols in an object file */
531                 ThisSym = ThisLibr->symbols;
532
533                 while (ThisSym)
534         {
535             //printf("ThisSym->name=%s\n", ThisSym->name);
536                         if (!strcmp(ThisSym->name, name))
537             {
538                                 if ((!ThisLibr->loaded) && (numfound==0))
539                 {
540                                         /* Object file is not loaded - add it to the list */
541                                         lbfh = (struct lbfile *) new (sizeof(struct lbfile));
542                                         if (lbfhead == NULL)
543                     {
544                                                 lbfhead = lbfh;
545                                         }
546                     else
547                     {
548                                                 lbf = lbfhead;
549                                                 while (lbf->next)
550                                                 lbf = lbf->next;
551                                                 lbf->next = lbfh;
552                                         }
553                                         lbfh->libspc = ThisLibr->libspc;
554                                         lbfh->filspc = ThisLibr->filename;
555                                         lbfh->relfil = (char *) new (strlen(ThisLibr->relfil) + 1);
556                                         strcpy(lbfh->relfil,ThisLibr->relfil);
557                     lbfh->offset = ThisLibr->offset;
558                     if(lbfh->offset>0)
559                     { /*For an embedded object file in a library*/
560                         void loadfile_SdccLib(char * libspc, char * module, long offset);
561                         loadfile_SdccLib(lbfh->libspc, lbfh->relfil, lbfh->offset);
562                     }
563                     else
564                     { /*For a stand alone object file*/
565                                             loadfile(lbfh->filspc);
566                     }
567                                         ThisLibr->loaded=1;
568                                 }
569
570                 if(numfound==0)
571                 {
572                     numfound++;
573                     FirstFound=ThisLibr;
574                 }
575                 else
576                 {
577                     char absPath1[PATH_MAX];
578                     char absPath2[PATH_MAX];
579 #if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
580                     int j;
581
582                     _fullpath(absPath1, FirstFound->libspc, PATH_MAX);
583                     _fullpath(absPath2, ThisLibr->libspc, PATH_MAX);
584                     for(j=0; absPath1[j]!=0; j++) absPath1[j]=tolower((unsigned char)absPath1[j]);
585                     for(j=0; absPath2[j]!=0; j++) absPath2[j]=tolower((unsigned char)absPath2[j]);
586 #else
587                     realpath(FirstFound->libspc, absPath1);
588                     realpath(ThisLibr->libspc, absPath2);
589 #endif
590                     if( !( EQ(absPath1, absPath2) && EQ(FirstFound->relfil, ThisLibr->relfil) ) )
591                     {
592                         if(numfound==1)
593                         {
594                             fprintf(stderr, "?Aslink-Warning-Definition of public symbol '%s'"
595                                    " found more than once:\n", name);
596                             fprintf(stderr, "   Library: '%s', Module: '%s'\n",
597                                     FirstFound->libspc, FirstFound->relfil);
598                         }
599                         fprintf(stderr, "   Library: '%s', Module: '%s'\n",
600                                 ThisLibr->libspc, ThisLibr->relfil);
601                         numfound++;
602                     }
603                 }
604                         }
605                         ThisSym=ThisSym->next;  /* Next sym in library */
606                 }
607                 ThisLibr=ThisLibr->next; /* Next library in list */
608         }
609         return numfound;
610 }
611
612 pmlibraryfile buildlibraryindex_SdccLib(char * PathLib, FILE * libfp, char * DirLib, pmlibraryfile This)
613 {
614         char ModName[NCPS]="";
615         char FLine[MAXLINE+1];
616     char buff[PATH_MAX];
617         int state=0;
618         long IndexOffset=0, FileOffset;
619     pmlibrarysymbol ThisSym = NULL;
620
621         while(!feof(libfp))
622     {
623         FLine[0]=0;
624         fgets(FLine, MAXLINE, libfp);
625         chop_crlf(FLine);
626
627         switch(state)
628         {
629             case 0:
630                 if(EQ(FLine, "<INDEX>"))
631                 {
632                                         /*The next line has the size of the index*/
633                     FLine[0]=0;
634                     fgets(FLine, MAXLINE, libfp);
635                     chop_crlf(FLine);
636                                         IndexOffset=atol(FLine);
637                                         state=1;
638                 }
639             break;
640             case 1:
641                 if(EQ(FLine, "<MODULE>"))
642                                 {
643                                         /*The next line has the name of the module and the offset
644                                         of the corresponding embedded file in the library*/
645                     FLine[0]=0;
646                     fgets(FLine, MAXLINE, libfp);
647                     chop_crlf(FLine);
648                                         sscanf(FLine, "%s %ld", ModName, &FileOffset);
649                                         state=2;
650
651                     /*Create a new libraryfile object for this module*/
652                     if(libr==NULL)
653                     {
654                         libr=This=(pmlibraryfile)new( sizeof( mlibraryfile ));
655                     }
656                     else
657                     {
658                                             This->next=(pmlibraryfile)new( sizeof( mlibraryfile ));
659                                             This=This->next;
660                     }
661                                         This->next = NULL;
662                                         This->loaded=-1;
663                     This->offset=FileOffset+IndexOffset;
664                                         This->libspc=PathLib;
665                     
666                     This->relfil=(char *)new(strlen(ModName)+1);
667                                         strcpy(This->relfil, ModName);
668
669                     sprintf(buff, "%s%s%c%s", DirLib, ModName, FSEPX, LKOBJEXT);
670                     This->filename=(char *)new(strlen(buff)+1);
671                     strcpy(This->filename, buff);
672
673                     This->symbols=ThisSym=NULL; /*Start a new linked list of symbols*/
674                                 }
675                 else if(EQ(FLine, "</INDEX>"))
676                                 {
677                                         return This; /*Finish, get out of here*/
678                                 }
679             break;
680             case 2:
681                 if(EQ(FLine, "</MODULE>"))
682                                 {
683                                         This->loaded=0;
684                                         /*Create the index for the next module*/
685                     state=1;
686                                 }
687                 else
688                                 {
689                                         /*Add the symbols*/
690                     if(ThisSym==NULL) /*First symbol of the current module*/
691                     {
692                                             ThisSym=This->symbols=(pmlibrarysymbol)new(sizeof(mlibrarysymbol));
693                     }
694                     else
695                     {
696                                             ThisSym->next = (pmlibrarysymbol)new(sizeof(mlibrarysymbol));
697                                         ThisSym=ThisSym->next;
698                     }
699                                         ThisSym->next=NULL;
700                     ThisSym->name=(char *)new(strlen(FLine)+1);
701                                         strcpy(ThisSym->name, FLine);
702                 }
703             break;
704                         
705                         default:
706                                 return This; /*State machine should never reach this point, but just in case...*/
707                         break;
708         }
709     }
710
711         return This; /*State machine should never reach this point, but just in case...*/
712 }
713
714
715 /* buildlibraryindex - build an in-memory cache of the symbols contained in
716  *                      the libraries
717  */
718 int buildlibraryindex(void)
719 {
720         FILE *libfp, *fp;
721         struct lbname *lbnh;
722         char relfil[NINPUT+2], str[PATH_MAX], *path;
723         char buf[NINPUT+2], c;
724         char symname[NINPUT+2];
725         pmlibraryfile This=NULL;
726         pmlibrarysymbol ThisSym;
727
728         /* Iterate through all library files */
729     for (lbnh=lbnhead; lbnh; lbnh=lbnh->next)
730     {
731                 if ((libfp = fopen(lbnh->libspc, "r")) == NULL)
732                 {
733                         fprintf(stderr, "?Aslink-Error-Cannot open library file %s\n",
734                                 lbnh->libspc);
735                         lkexit(1);
736                 }
737
738         path=lbnh->path;
739
740                 /*
741                  * Read in a line from the library file.
742                  * This is the relative file specification
743                  * for a .REL file in this library.
744                  */
745
746         while (fgets(relfil, NINPUT, libfp) != NULL)
747         {
748             relfil[NINPUT+1] = '\0';
749             chop_crlf(relfil);
750             if (path != NULL)
751             {
752                 strcpy(str, path);
753 #ifdef  OTHERSYSTEM
754                                 if (str[strlen(str)-1] != LKDIRSEP)
755                 {
756                                         strcat(str, LKDIRSEPSTR);
757                 }
758 #endif
759                         }
760             else
761             {
762                 strcpy(str, "");
763                         }
764
765             if(strcmp(relfil, "<SDCCLIB>")==0)
766                         {
767                 /*Get the built in index of a library*/
768                                 This=buildlibraryindex_SdccLib(lbnh->libspc, libfp, str, This);
769                                 break; /*get the index for next library*/
770                         }
771             
772             /*From here down, build the index for the original library format*/
773
774             if (relfil[0] == LKDIRSEP)
775             {
776                                 strcat(str, relfil+1);
777                         }
778             else
779             {
780                                 strcat(str, relfil);
781                         }
782                                 
783             if(strchr(relfil, FSEPX) == NULL)
784             {
785                                 sprintf(&str[strlen(str)], "%c%s", FSEPX, LKOBJEXT);
786                         }
787
788             if ((fp = fopen(str, "r")) != NULL)
789             {
790                 /* Opened OK - create a new libraryfile object for it */
791                 if(libr==NULL)
792                 {
793                     libr=This=(pmlibraryfile)new( sizeof( mlibraryfile ));
794                 }
795                 else
796                 {
797                                         This->next=(pmlibraryfile)new( sizeof( mlibraryfile ));
798                                 This=This->next;
799                 }
800
801                                 This->next = NULL;
802                                 This->loaded=-1;
803                 This->offset=-1; /*There should be a rel file*/
804                                 This->libspc = lbnh->libspc;
805                 This->relfil=(char *)new(strlen(relfil)+1);
806                                 strcpy(This->relfil, relfil);
807                 This->filename=(char *)new(strlen(str)+1);
808                                 strcpy(This->filename, str);
809
810                                 ThisSym = This->symbols = NULL;
811
812                                 /*
813                                  * Read in the object file.  Look for lines that
814                                  * begin with "S" and end with "D".  These are
815                                  * symbol table definitions.  If we find one, see
816                                  * if it is our symbol.  Make sure we only read in
817                                  * our object file and don't go into the next one.
818                                  */
819                         
820                                 while (fgets(buf, NINPUT, fp) != NULL)
821                 {
822                                         buf[NINPUT+1] = '\0';
823                                         buf[strlen(buf) - 1] = '\0';
824
825                                         /*
826                                          * Skip everything that's not a symbol record.
827                                          */
828                                         if (buf[0] != 'S') continue;
829
830                                         /*
831                                          * When a 'T line' is found terminate file scan.
832                                          * All 'S line's preceed 'T line's in .REL files.
833                                          */
834                                         if (buf[0] == 'T') break;
835
836                                         sscanf(buf, "S %s %c", symname, &c);
837
838                     /* If it's an actual symbol, record it */
839                                 if (c == 'D')
840                     {
841                         if(ThisSym==NULL)
842                         {
843                                             ThisSym=This->symbols=(pmlibrarysymbol)new(sizeof(mlibrarysymbol));
844                         }
845                         else
846                         {
847                                                     ThisSym->next=(pmlibrarysymbol)new(sizeof(mlibrarysymbol));
848                                                     ThisSym=ThisSym->next;
849                         }
850                                                 This->loaded=0;
851                                                 ThisSym->next=NULL;
852                         ThisSym->name=(char *)new(strlen(symname)+1);
853                                                 strcpy(ThisSym->name, symname);
854                     }
855                                 } /* Closes while - read object file */
856                                 fclose(fp);
857                         } /* Closes if object file opened OK */
858                 } /* Ends while - processing all in libr */
859                 fclose(libfp);
860         } /* Ends good open of libr file */
861         return 0;
862 }
863
864 /*Release all memory allocated for the in-memory library index*/
865 void freelibraryindex (void)
866 {
867         pmlibraryfile ThisLibr, ThisLibr2Free;
868         pmlibrarysymbol ThisSym, ThisSym2Free;
869
870         ThisLibr = libr;
871
872     while (ThisLibr)
873     {
874                 ThisSym = ThisLibr->symbols;
875
876                 while (ThisSym)
877         {
878             free(ThisSym->name);
879             ThisSym2Free=ThisSym;
880             ThisSym=ThisSym->next;
881             free(ThisSym2Free);
882         }
883         free(ThisLibr->filename);
884         free(ThisLibr->relfil);
885         ThisLibr2Free=ThisLibr;
886         ThisLibr=ThisLibr->next;
887         free(ThisLibr2Free);
888     }
889     
890     libr=NULL;
891 }
892
893 #else /* INDEXLIB */
894
895
896 /*Check for a symbol in a SDCC library.  If found, add the embedded .rel.
897 The library must be created with the SDCC librarian 'sdcclib' since the
898 linking process depends on the correct file offsets embedded in the library
899 file.*/
900
901 int SdccLib(char * PathLib, FILE * libfp, char * DirLib, char * SymName)
902 {
903         struct lbfile *lbfh, *lbf;
904         char ModName[NCPS]="";
905         char FLine[MAXLINE+1];
906         int state=0;
907         long IndexOffset=0, FileOffset;
908
909         while(!feof(libfp))
910     {
911         FLine[0]=0;
912         fgets(FLine, MAXLINE, libfp);
913         chop_crlf(FLine);
914
915         switch(state)
916         {
917             case 0:
918                 if(EQ(FLine, "<INDEX>"))
919                 {
920                                         /*The next line has the size of the index*/
921                     FLine[0]=0;
922                     fgets(FLine, MAXLINE, libfp);
923                     chop_crlf(FLine);
924                                         IndexOffset=atol(FLine);
925                                         state=1;
926                 }
927             break;
928             case 1:
929                 if(EQ(FLine, "<MODULE>"))
930                                 {
931                                         /*The next line has the name of the module and the offset
932                                         of the corresponding embedded file in the library*/
933                     FLine[0]=0;
934                     fgets(FLine, MAXLINE, libfp);
935                     chop_crlf(FLine);
936                                         sscanf(FLine, "%s %ld", ModName, &FileOffset);
937                                         state=2;
938                                 }
939                 else if(EQ(FLine, "</INDEX>"))
940                                 {
941                                         /*Reached the end of the index.  The symbol is not in this library.*/
942                                         return 0;
943                                 }
944             break;
945             case 2:
946                 if(EQ(FLine, "</MODULE>"))
947                                 {
948                                         /*The symbol is not in this module, try the next one*/
949                     state=1;
950                                 }
951                 else
952                                 {
953                                         /*Check if this is the symbol we are looking for.*/
954                                         if (strncmp(SymName, FLine, NCPS)==0)
955                                         {
956                                                 /*The symbol is in this module.*/
957
958                                                 /*As in the original library format, it is assumed that the .rel
959                                                 files reside in the same directory as the lib files.*/
960                                                 strcat(DirLib, ModName);
961                                     sprintf(&DirLib[strlen(DirLib)], "%c%s", FSEPX, LKOBJEXT);
962
963                                                 /*If this module has been loaded already don't load it again.*/
964                                                 lbf = lbfhead;
965                                                 while (lbf)
966                                                 {
967                                                         if(EQ(DirLib, lbf->filspc)) return 1;/*Already loaded*/
968                                                         lbf=lbf->next;
969                                                 }
970                                                 
971                                                 /*Add the embedded file to the list of files to be loaded in
972                                                 the second pass.  That is performed latter by the function
973                                                 library() below.*/
974                                                 lbfh = (struct lbfile *) new (sizeof(struct lbfile));
975                                                 if (lbfhead == NULL)
976                                                 {
977                                                         lbfhead = lbfh;
978                                                 }
979                                                 else
980                                                 {
981                                                         lbf = lbfhead;
982                                                         while (lbf->next)
983                                                         lbf = lbf->next;
984                                                         lbf->next = lbfh;
985                                                 }
986
987                                                 lbfh->libspc = PathLib;
988                                                 lbfh->filspc = DirLib;
989                                                 lbfh->relfil = (char *) new (strlen(ModName) + 1);
990                                                 strcpy(lbfh->relfil, ModName);
991                                                 /*Library embedded file, so lbfh->offset must be >=0*/
992                                                 lbfh->offset = IndexOffset+FileOffset;
993                                                 
994                                                 /*Jump to where the .rel begins and load it.*/
995                                                 fseek(libfp, lbfh->offset, SEEK_SET);
996                                                 LoadRel(PathLib, libfp, ModName);
997
998                                                 return 1; /*Found the symbol, so success!*/
999                                         }
1000                                 }
1001             break;
1002                         
1003                         default:
1004                                 return 0; /*It should never reach this point, but just in case...*/
1005                         break;
1006         }
1007     }
1008
1009         return 0; /*The symbol is not in this library*/
1010 }
1011
1012 int
1013 fndsym(name)
1014 char *name;
1015 {
1016         FILE *libfp, *fp;
1017         struct lbname *lbnh;
1018         struct lbfile *lbfh, *lbf;
1019         char relfil[NINPUT+2];
1020         char buf[NINPUT+2];
1021         char symname[NINPUT];
1022         char *path,*str;
1023         char c;
1024         int result;
1025
1026         /*
1027          * Search through every library in the linked list "lbnhead".
1028          */
1029
1030 /*1*/   for (lbnh=lbnhead; lbnh; lbnh=lbnh->next) {
1031                 if ((libfp = fopen(lbnh->libspc, "r")) == NULL) {
1032                         fprintf(stderr, "Cannot open library file %s\n",
1033                                 lbnh->libspc);
1034                         lkexit(1);
1035                 }
1036                 path = lbnh->path;
1037
1038                 /*
1039                  * Read in a line from the library file.
1040                  * This is the relative file specification
1041                  * for a .REL file in this library.
1042                  */
1043
1044 /*2*/           while (fgets(relfil, NINPUT, libfp) != NULL) {
1045                     relfil[NINPUT+1] = '\0';
1046                     chop_crlf(relfil);
1047                     if (path != NULL) {
1048                         str = (char *) new (strlen(path)+strlen(relfil)+6);
1049                         strcpy(str,path);
1050 #ifdef  OTHERSYSTEM
1051 #ifdef SDK
1052 #ifdef UNIX
1053                         if (str[strlen(str)-1] != '/') {
1054                                 strcat(str,"/");
1055 #else /* UNIX */
1056                         if (str[strlen(str)-1] != '\\') {
1057                                 strcat(str,"\\");
1058 #endif /* UNIX */
1059 #else /* SDK */
1060                         if (str[strlen(str)-1] != '\\') {
1061                                 strcat(str,"\\");
1062 #endif /* SDK */
1063                         }
1064 #endif
1065                     } else {
1066                         str = (char *) new (strlen(relfil) + 5);
1067                     }
1068
1069             /*See if this is a library with embedded files*/
1070                         if(strcmp(relfil, "<SDCCLIB>")==0)
1071                         {
1072                                 result=SdccLib(lbnh->libspc, libfp, str, name);
1073                                 if(result) return(1); /*Found the symbol*/
1074                                 free(str);
1075                                 /*The symbol is not in the current library,
1076                                 check the next library in the list*/
1077                                 break; 
1078                         }
1079
1080                         /*From here down is the support for libraries in the original format*/
1081 #ifdef SDK
1082 #ifdef UNIX
1083                     if (relfil[0] == '/') {
1084 #else /* UNIX */
1085                     if (relfil[0] == '\\') {
1086 #endif /* UNIX */
1087 #else /* SDK */
1088                     if (relfil[0] == '\\') {
1089 #endif /* SDK */
1090                         strcat(str,relfil+1);
1091                     } else {
1092                         strcat(str,relfil);
1093                     }
1094                     if(strchr(relfil, FSEPX) == NULL)
1095             {
1096                 sprintf(&str[strlen(str)], "%c%s", FSEPX, LKOBJEXT);
1097                     }
1098
1099 /*3*/               if ((fp = fopen(str, "r")) != NULL) {
1100
1101                         /*
1102                          * Read in the object file.  Look for lines that
1103                          * begin with "S" and end with "D".  These are
1104                          * symbol table definitions.  If we find one, see
1105                          * if it is our symbol.  Make sure we only read in
1106                          * our object file and don't go into the next one.
1107                          */
1108                         
1109 /*4*/                   while (fgets(buf, NINPUT, fp) != NULL) {
1110
1111                         buf[NINPUT+1] = '\0';
1112                         buf[strlen(buf) - 1] = '\0';
1113
1114                         /*
1115                          * Skip everything that's not a symbol record.
1116                          */
1117                         if (buf[0] != 'S')
1118                                 continue;
1119
1120                         /*
1121                          * When a 'T line' is found terminate file scan.
1122                          * All 'S line's preceed 'T line's in .REL files.
1123                          */
1124                         if (buf[0] == 'T')
1125                                 break;
1126
1127                         sscanf(buf, "S %s %c", symname, &c);
1128
1129                         /*
1130                          * If we find a symbol definition for the
1131                          * symbol we're looking for, load in the
1132                          * file and add it to lbfhead so it gets
1133                          * loaded on pass number 2.
1134                          */
1135 /*5*/                   if (strncmp(symname, name, NCPS) == 0 && c == 'D') {
1136
1137                         lbfh = (struct lbfile *) new (sizeof(struct lbfile));
1138                         if (lbfhead == NULL) {
1139                                 lbfhead = lbfh;
1140                         } else {
1141                                 lbf = lbfhead;
1142                                 while (lbf->next)
1143                                         lbf = lbf->next;
1144                                 lbf->next = lbfh;
1145                         }
1146                         lbfh->libspc = lbnh->libspc;
1147                         lbfh->filspc = str;
1148                         lbfh->relfil = (char *) new (strlen(relfil) + 1);
1149                         lbfh->offset = -1; /*Stand alone rel file*/
1150                         strcpy(lbfh->relfil,relfil);
1151                         fclose(fp);
1152                         fclose(libfp);
1153                         loadfile(str);
1154                         return (1);
1155
1156 /*5*/                   }
1157
1158 /*4*/                   }
1159                     fclose(fp);
1160 /*3*/               }
1161
1162                     free(str);
1163 /*2*/           }
1164                 fclose(libfp);
1165 /*1*/   }
1166         return(0);
1167 }
1168 #endif /* INDEXLIB */
1169
1170 void loadfile_SdccLib(char * libspc, char * module, long offset)
1171 {
1172         FILE *fp;
1173
1174 #ifdef __CYGWIN__
1175     char posix_path[PATH_MAX];
1176     void cygwin_conv_to_full_posix_path(char * win_path, char * posix_path);
1177     cygwin_conv_to_full_posix_path(libspc, posix_path);
1178     fp = fopen(posix_path, "r");
1179 #else
1180     fp = fopen(libspc,"r");
1181 #endif
1182
1183         if (fp != NULL)
1184         {
1185                 fseek(fp, offset, SEEK_SET);
1186                 LoadRel(libspc, fp, module);
1187                 fclose(fp);
1188         }
1189     else
1190     {
1191                 fprintf(stderr, "?Aslink-Error-Opening library '%s'\n", libspc);
1192                 lkexit(1);
1193     }
1194 }
1195
1196 /*)Function     VOID    library()
1197  *
1198  *      The function library() links all the library object files
1199  *      contained in the lbfile structures.
1200  *
1201  *      local variables:
1202  *              lbfile  *lbfh           pointer to lbfile structure
1203  *
1204  *      global variables:
1205  *              lbfile  *lbfhead        pointer to first lbfile structure
1206  *
1207  *       functions called:
1208  *              VOID    loadfile        lklibr.c
1209  *
1210  *      side effects:
1211  *              Links all files contained in the lbfile structures.
1212  */
1213
1214 VOID
1215 library()
1216 {
1217         struct lbfile *lbfh;
1218
1219         for (lbfh=lbfhead; lbfh; lbfh=lbfh->next)
1220         {
1221                 if(lbfh->offset<0)
1222                 {
1223                         /*Stand alone rel file (original lib format)*/
1224                         loadfile(lbfh->filspc);
1225                 }
1226                 else
1227                 {
1228                         /*rel file embedded in lib (new lib format)*/
1229                         loadfile_SdccLib(lbfh->libspc, lbfh->relfil, lbfh->offset);
1230                 }
1231         }
1232 #ifdef INDEXLIB
1233     freelibraryindex();
1234 #endif
1235 }
1236
1237 /*)Function     VOID    loadfile(filspc)
1238  *
1239  *              char    *filspc         library object file specification
1240  *
1241  *      The function loadfile() links the library object module.
1242  *
1243  *      local variables:
1244  *              FILE    *fp             file handle
1245  *              int     i               input line length
1246  *              char    str[]           file input line
1247  *
1248  *      global variables:
1249  *              char    *ip             pointer to linker input string
1250  *
1251  *       functions called:
1252  *              int     fclose()        c_library
1253  *              int     fgets()         c_library
1254  *              FILE *  fopen()         c_library
1255  *              VOID    link()          lkmain.c
1256  *              int     strlen()        c_library
1257  *
1258  *      side effects:
1259  *              If file exists it is linked.
1260  */
1261
1262 VOID
1263 loadfile(filspc)
1264 char *filspc;
1265 {
1266         FILE *fp;
1267         char str[NINPUT+2];
1268         int i;
1269
1270 #ifdef __CYGWIN__
1271     char posix_path[PATH_MAX];
1272     void cygwin_conv_to_full_posix_path(char * win_path, char * posix_path);
1273     cygwin_conv_to_full_posix_path(filspc, posix_path);
1274     fp = fopen(posix_path, "r");
1275 #else
1276     fp = fopen(filspc,"r");
1277 #endif
1278
1279         if (fp != NULL)
1280     {
1281                 while (fgets(str, NINPUT, fp) != NULL)
1282         {
1283                         str[NINPUT+1] = '\0';
1284                         i = strlen(str) - 1;
1285                         if (str[i] == '\n')
1286                                 str[i] = '\0';
1287                         ip = str;
1288                         link();
1289                 }
1290                 fclose(fp);
1291         }
1292     else
1293     {
1294                 fprintf(stderr, "?Aslink-Error-Opening library '%s'\n", filspc);
1295                 lkexit(1);
1296     }
1297 }