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