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