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