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