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