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