4 * (C) Copyright 1989-1995
11 * With contributions for the
12 * object libraries from
14 * kenh@cmf.nrl.navy.mil
18 #define EQ(A,B) !strcmp((A),(B))
19 #define MAXLINE 254 /*when using fgets*/
21 #if defined(__APPLE__) && defined(__MACH__)
22 #include <sys/types.h>
23 #include <sys/malloc.h>
34 * The module lklibr.c contains the functions which
35 * (1) specify the path(s) to library files [.LIB]
36 * (2) specify the library file(s) [.LIB] to search
37 * (3) search the library files for specific symbols
38 * and link the module containing this symbol
40 * lklibr.c contains the following functions:
51 /*)Function VOID addpath()
53 * The function addpath() creates a linked structure containing
54 * the paths to various object module library files.
57 * lbpath *lbph pointer to new path structure
58 * lbpath *lbp temporary pointer
61 * lbpath *lbphead The pointer to the first
65 * char getnb() lklex.c
66 * VOID * new() lksym.c
67 * int strlen() c_library
68 * char * strcpy() c_library
69 * VOID unget() lklex.c
72 * An lbpath structure may be created.
78 struct lbpath *lbph, *lbp;
80 lbph = (struct lbpath *) new (sizeof(struct lbpath));
81 if (lbphead == NULL) {
90 lbph->path = (char *) new (strlen(ip)+1);
91 strcpy(lbph->path, ip);
94 /*)Function VOID addlib()
96 * The function addlib() tests for the existance of a
97 * library path structure to determine the method of
98 * adding this library file to the library search structure.
100 * This function calls the function addfile() to actually
101 * add the library file to the search list.
104 * lbpath *lbph pointer to path structure
107 * lbpath *lbphead The pointer to the first
111 * VOID addfile() lklibr.c
112 * char getnb() lklex.c
113 * VOID unget() lklex.c
116 * The function addfile() may add the file to
117 * the library search list.
127 if (lbphead == NULL) {
131 for (lbph=lbphead; lbph; lbph=lbph->next) {
132 addfile(lbph->path,ip);
136 /*)Function VOID addfile(path,libfil)
138 * char *path library path specification
139 * char *libfil library file specification
141 * The function addfile() searches for the library file
142 * by concatenating the path and libfil specifications.
143 * if the library is found, an lbname structure is created
144 * and linked to any previously defined structures. This
145 * linked list is used by the function fndsym() to attempt
146 * to find any undefined symbols.
148 * The function does not give report an error on invalid
149 * path / file specifications or if the file is not found.
152 * lbname *lbnh pointer to new name structure
153 * lbname *lbn temporary pointer
156 * lbname *lbnhead The pointer to the first
160 * char getnb() lklex.c
161 * VOID * new() lksym.c
162 * int strlen() c_library
163 * char * strcpy() c_library
164 * VOID unget() lklex.c
167 * An lbname structure may be created.
177 struct lbname *lbnh, *lbn;
179 if ((path != NULL) && (strchr(libfil,':') == NULL)){
180 str = (char *) new (strlen(path) + strlen(libfil) + 6);
183 if (str[strlen(str)-1] != '/') {
188 str = (char *) new (strlen(libfil) + 5);
191 if (libfil[0] == '/') { libfil++; }
194 if(strchr(libfil,FSEPX) == NULL) {
195 sprintf(&str[strlen(str)], "%clib", FSEPX);
197 if ((fp = fopen(str, "r")) != NULL) {
199 lbnh = (struct lbname *) new (sizeof(struct lbname));
200 if (lbnhead == NULL) {
208 if ((path != NULL) && (strchr(libfil,':') == NULL)){
211 lbnh->libfil = (char *) new (strlen(libfil) + 1);
212 strcpy(lbnh->libfil,libfil);
219 /*)Function VOID search()
221 * The function search() looks through all the symbol tables
222 * at the end of pass 1. If any undefined symbols are found
223 * then the function fndsym() is called. Function fndsym()
224 * searches any specified library files to automagically
225 * import the object modules containing the needed symbol.
227 * After a symbol is found and imported by the function
228 * fndsym() the symbol tables are again searched. The
229 * symbol tables are search until no more symbols can be
230 * resolved within the library files. This ensures that
231 * back references from one library module to another are
235 * int i temporary counter
236 * sym *sp pointer to a symbol structure
237 * int symfnd found a symbol flag
240 * sym *symhash[] array of pointers to symbol tables
243 * int fndsym() lklibr.c
246 * If a symbol is found then the library object module
247 * containing the symbol will be imported and linked.
253 register struct sym *sp;
254 register int i,symfnd;
257 * Look for undefined symbols. Keep
258 * searching until no more symbols are resolved.
264 * Look through all the symbols
266 for (i=0; i<NHASH; ++i) {
269 /* If we find an undefined symbol
270 * (one where S_DEF is not set), then
271 * try looking for it. If we find it
272 * in any of the libraries then
273 * increment symfnd. This will force
274 * another pass of symbol searching and
275 * make sure that back references work.
277 if ((sp->s_type & S_DEF) == 0) {
278 if (fndsym(sp->s_id)) {
288 /*Load a .rel file embedded in a sdcclib file*/
289 void LoadRel(FILE * libfp, char * ModName)
294 while (fgets(str, NINPUT, libfp) != NULL)
296 str[NINPUT+1] = '\0';
301 if(EQ(str, "<FILE>"))
303 fgets(str, NINPUT, libfp);
304 str[NINPUT+1] = '\0';
306 if(EQ(str, ModName)) state=1;
309 printf("Bad offset in library file str=%s, Modname=%s\n", str, ModName);
315 if(EQ(str, "<REL>")) state=2;
318 if(EQ(str, "</REL>")) return;
326 /*Load an .adb file embedded in a sdcclib file. If there is
327 something between <ADB> and </ADB> returns 1, otherwise returns 0.
328 This way the aomf51 will not have uselless empty modules. */
330 int LoadAdb(FILE * libfp)
336 while (fgets(str, MAXLINE, libfp) != NULL)
338 str[NINPUT+1] = '\0';
343 if(EQ(str, "<ADB>")) state=1;
346 if(EQ(str, "</ADB>")) return ToReturn;
347 fprintf(dfp, "%s\n", str);
355 /*Check for a symbol in a SDCC library. If found, add the embedded .rel and
356 .adb files from the library. The library must be created with the SDCC
357 librarian 'sdcclib' since the linking process depends on the correct file offsets
358 embedded in the library file.*/
360 int SdccLib(char * PathLib, FILE * libfp, char * DirLib, char * SymName)
362 struct lbfile *lbfh, *lbf;
363 char ModName[NCPS]="";
364 char FLine[MAXLINE+1];
366 long IndexOffset=0, FileOffset;
371 fgets(FLine, MAXLINE, libfp);
377 if(EQ(FLine, "<INDEX>"))
379 /*The next line has the size of the index*/
381 fgets(FLine, MAXLINE, libfp);
383 IndexOffset=atol(FLine);
388 if(EQ(FLine, "<MODULE>"))
390 /*The next line has the name of the module and the offset
391 of the corresponding embedded file in the library*/
393 fgets(FLine, MAXLINE, libfp);
395 sscanf(FLine, "%s %ld", ModName, &FileOffset);
398 else if(EQ(FLine, "</INDEX>"))
400 /*Reached the end of the index. The symbol is not in this library.*/
405 if(EQ(FLine, "</MODULE>"))
407 /*The symbol is not in this module, try the next one*/
412 /*Check if this is the symbol we are looking for.*/
413 if (strncmp(SymName, FLine, NCPS)==0)
415 /*The symbol is in this module.*/
417 /*As in the original library format, it is assumed that the .rel
418 files reside in the same directory as the lib files.*/
419 strcat(DirLib, ModName);
420 strcat(DirLib, ".rel"); /*FSEPX???*/
422 /*If this module has been loaded already don't load it again.*/
426 if(EQ(DirLib, lbf->filspc)) return 1;/*Already loaded*/
430 /*Add the embedded file to the list of files to be loaded in
431 the second pass. That is performed latter by the function
433 lbfh = (struct lbfile *) new (sizeof(struct lbfile));
446 lbfh->libspc = PathLib;
447 lbfh->filspc = DirLib;
448 lbfh->relfil = (char *) new (strlen(ModName) + 1);
449 strcpy(lbfh->relfil, ModName);
450 /*Library embedded file, so lbfh->offset must be >=0*/
451 lbfh->offset = IndexOffset+FileOffset;
453 /*Jump to where the .rel begins and load it.*/
454 fseek(libfp, lbfh->offset, SEEK_SET);
455 LoadRel(libfp, ModName);
457 /* if cdb information required & .adb file present */
461 SaveLinkedFilePath(DirLib);
463 return 1; /*Found the symbol, so success!*/
469 return 0; /*It should never reach this point, but just in case...*/
474 return 0; /*The symbol is not in this library*/
477 /*)Function VOID fndsym(name)
479 * char *name symbol name to find
481 * The function fndsym() searches through all combinations of the
482 * library path specifications (input by the -k option) and the
483 * library file specifications (input by the -l option) that
484 * lead to an existing file.
486 * The file specicifation may be formed in one of two ways:
488 * (1) If the library file contained an absolute
489 * path/file specification then this becomes filspc.
492 * (2) If the library file contains a relative path/file
493 * specification then the concatenation of the path
494 * and this file specification becomes filspc.
497 * The structure lbfile is created for the first library
498 * object file which contains the definition for the
499 * specified undefined symbol.
501 * If the library file [.LIB] contains file specifications for
502 * non existant files, no errors are returned.
505 * char buf[] [.REL] file input line
506 * char c [.REL] file input character
507 * FILE *fp file handle for object file
508 * lbfile *lbf temporary pointer
509 * lbfile *lbfh pointer to lbfile structure
510 * FILE *libfp file handle for library file
511 * lbname *lbnh pointer to lbname structure
512 * char *path file specification path
513 * char relfil[] [.REL] file specification
514 * char *str combined path and file specification
515 * char symname[] [.REL] file symbol string
518 * lbname *lbnhead The pointer to the first
520 * lbfile *lbfhead The pointer to the first
524 * int fclose() c_library
525 * int fgets() c_library
526 * FILE *fopen() c_library
527 * VOID free() c_library
528 * char getnb() lklex.c
529 * VOID lkexit() lkmain.c
530 * VOID loadfile() lklibr.c
531 * VOID * new() lksym.c
532 * char * sprintf() c_library
533 * int sscanf() c_library
534 * char * strcat() c_library
535 * char * strchr() c_library
536 * char * strcpy() c_library
537 * int strlen() c_library
538 * int strncmp() c_library
539 * VOID unget() lklex.c
542 * If the symbol is found then a new lbfile structure
543 * is created and added to the linked list of lbfile
544 * structures. The file containing the found symbol
554 struct lbfile *lbfh, *lbf;
555 char relfil[NINPUT+2];
557 char symname[NINPUT];
563 * Search through every library in the linked list "lbnhead".
566 for (lbnh=lbnhead; lbnh; lbnh=lbnh->next)
568 if ((libfp = fopen(lbnh->libspc, "r")) == NULL)
570 fprintf(stderr, "Cannot open library file %s\n",
577 * Read in a line from the library file.
578 * This is the relative file specification
579 * for a .REL file in this library.
582 while (fgets(relfil, NINPUT, libfp) != NULL)
584 relfil[NINPUT+1] = '\0';
588 str = (char *) new (strlen(path)+strlen(relfil)+6);
591 if (str[strlen(str)-1] != '/')
599 str = (char *) new (strlen(relfil) + 5);
602 if(strcmp(relfil, "<SDCCLIB>")==0)
604 result=SdccLib(lbnh->libspc, libfp, str, name);
606 if(result) return(1); /*Found the symbol*/
608 /*The symbol is not in the current library,
609 check the next library in the list*/
613 /*From here down is the support for libraries in the original format*/
614 if (relfil[0] == '\\')
616 strcat(str,relfil+1);
623 if(strchr(relfil, FSEPX) == NULL)
625 sprintf(&str[strlen(str)], "%crel", FSEPX);
628 if ((fp = fopen(str, "r")) != NULL)
632 * Read in the object file. Look for lines that
633 * begin with "S" and end with "D". These are
634 * symbol table definitions. If we find one, see
635 * if it is our symbol. Make sure we only read in
636 * our object file and don't go into the next one.
639 while (fgets(buf, NINPUT, fp) != NULL)
641 buf[NINPUT+1] = '\0';
644 * Skip everything that's not a symbol record.
646 if (buf[0] != 'S') continue;
649 * When a 'T line' is found terminate file scan.
650 * All 'S line's preceed 'T line's in .REL files.
652 if (buf[0] == 'T') break;
654 sscanf(buf, "S %s %c", symname, &c);
657 * If we find a symbol definition for the
658 * symbol we're looking for, load in the
659 * file and add it to lbfhead so it gets
660 * loaded on pass number 2.
662 if (strncmp(symname, name, NCPS) == 0 && c == 'D')
664 lbfh = (struct lbfile *) new (sizeof(struct lbfile));
677 lbfh->libspc = lbnh->libspc;
679 lbfh->relfil = (char *) new (strlen(relfil) + 1);
680 lbfh->offset = -1; /*Stand alone rel file*/
681 strcpy(lbfh->relfil,relfil);
685 /* if cdb information required & adb file present */
688 FILE *xfp = afile(str,"adb",0); //JCF: Nov 30, 2002
691 SaveLinkedFilePath(str);
709 void loadfile_SdccLib(char * libspc, char * module, long offset)
713 if ((fp = fopen(libspc,"r")) != NULL)
715 fseek(fp, offset, SEEK_SET);
721 /*)Function VOID library()
723 * The function library() links all the library object files
724 * contained in the lbfile structures.
727 * lbfile *lbfh pointer to lbfile structure
730 * lbfile *lbfhead pointer to first lbfile structure
733 * VOID loadfile lklibr.c
736 * Links all files contained in the lbfile structures.
744 for (lbfh=lbfhead; lbfh; lbfh=lbfh->next)
748 /*Stand alone rel file (original lib format)*/
749 loadfile(lbfh->filspc);
753 /*rel file embedded in lib (new lib format)*/
754 loadfile_SdccLib(lbfh->libspc, lbfh->relfil, lbfh->offset);
759 /*)Function VOID loadfile(filspc)
761 * char *filspc library object file specification
763 * The function loadfile() links the library object module.
766 * FILE *fp file handle
767 * int i input line length
768 * char str[] file input line
771 * char *ip pointer to linker input string
774 * int fclose() c_library
775 * int fgets() c_library
776 * FILE * fopen() c_library
777 * VOID link_main() lkmain.c
778 * int strlen() c_library
781 * If file exists it is linked.
791 if ((fp = fopen(filspc,"r")) != NULL) {
792 while (fgets(str, NINPUT, fp) != NULL) {
793 str[NINPUT+1] = '\0';