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
109 * ip a pointer to the library name
112 * VOID addfile() lklibr.c
113 * char getnb() lklex.c
114 * VOID unget() lklex.c
117 * The function addfile() may add the file to
118 * the library search list.
129 if (lbphead == NULL) {
133 for (lbph=lbphead; lbph; lbph=lbph->next) {
134 foundcount+=addfile(lbph->path,ip);
138 printf("?ASlink-Warning-Couldn't find library '%s'\n", ip);
142 /*)Function int addfile(path,libfil)
144 * char *path library path specification
145 * char *libfil library file specification
147 * The function addfile() searches for the library file
148 * by concatenating the path and libfil specifications.
149 * if the library is found, an lbname structure is created
150 * and linked to any previously defined structures. This
151 * linked list is used by the function fndsym() to attempt
152 * to find any undefined symbols.
154 * The function does not give report an error on invalid
155 * path / file specifications or if the file is not found.
158 * lbname *lbnh pointer to new name structure
159 * lbname *lbn temporary pointer
162 * lbname *lbnhead The pointer to the first
166 * char getnb() lklex.c
167 * VOID * new() lksym.c
168 * int strlen() c_library
169 * char * strcpy() c_library
170 * VOID unget() lklex.c
173 * An lbname structure may be created.
176 * 1: the library was found
177 * 0: the library was not found
180 int addfile(char * path, char * libfil)
184 struct lbname *lbnh, *lbn;
191 str = (char *) new (strlen(path) + strlen(libfil) + 6);
194 if (str[strlen(str)-1] != '/')
202 str = (char *) new (strlen(libfil) + 5);
206 if (libfil[0] == '/')
214 if(strchr(libfil, FSEPX) == NULL)
216 sprintf(&str[strlen(str)], "%clib", FSEPX);
222 /*Ok, that didn't work. Try with the 'libfil' name only*/
224 if(libfilinc) libfil--;
226 fp=fopen(libfil, "r");
229 /*Bingo! 'libfil' is the absolute path of the library*/
231 path=NULL;/*This way 'libfil' and 'path' will be rebuilt from 'str'*/
237 /*'path' can not be null since it is needed to find the '.o' files associated with
238 the library. So, get 'path' from 'str' and then chop it off and recreate 'libfil'.
239 That way putting 'path' and 'libfil' together will result into the original filepath
240 as contained in 'str'.*/
242 path = (char *) new (strlen(str));
244 for(j=strlen(path)-1; j>=0; j--)
246 if((path[j]=='\\')||(path[j]=='/'))
248 strcpy(libfil, &path[j+1]);
259 lbnh = (struct lbname *) new (sizeof(struct lbname));
273 lbnh->libfil = (char *) new (strlen(libfil) + 1);
274 strcpy(lbnh->libfil,libfil);
285 /*)Function VOID search()
287 * The function search() looks through all the symbol tables
288 * at the end of pass 1. If any undefined symbols are found
289 * then the function fndsym() is called. Function fndsym()
290 * searches any specified library files to automagically
291 * import the object modules containing the needed symbol.
293 * After a symbol is found and imported by the function
294 * fndsym() the symbol tables are again searched. The
295 * symbol tables are search until no more symbols can be
296 * resolved within the library files. This ensures that
297 * back references from one library module to another are
301 * int i temporary counter
302 * sym *sp pointer to a symbol structure
303 * int symfnd found a symbol flag
306 * sym *symhash[] array of pointers to symbol tables
309 * int fndsym() lklibr.c
312 * If a symbol is found then the library object module
313 * containing the symbol will be imported and linked.
319 register struct sym *sp;
320 register int i,symfnd;
323 * Look for undefined symbols. Keep
324 * searching until no more symbols are resolved.
330 * Look through all the symbols
332 for (i=0; i<NHASH; ++i) {
335 /* If we find an undefined symbol
336 * (one where S_DEF is not set), then
337 * try looking for it. If we find it
338 * in any of the libraries then
339 * increment symfnd. This will force
340 * another pass of symbol searching and
341 * make sure that back references work.
343 if ((sp->s_type & S_DEF) == 0) {
344 if (fndsym(sp->s_id)) {
354 /*Load a .rel file embedded in a sdcclib file*/
355 void LoadRel(FILE * libfp, char * ModName)
360 while (fgets(str, NINPUT, libfp) != NULL)
362 str[NINPUT+1] = '\0';
367 if(EQ(str, "<FILE>"))
369 fgets(str, NINPUT, libfp);
370 str[NINPUT+1] = '\0';
372 if(EQ(str, ModName)) state=1;
375 printf("Bad offset in library file str=%s, Modname=%s\n", str, ModName);
381 if(EQ(str, "<REL>")) state=2;
384 if(EQ(str, "</REL>")) return;
392 /*Load an .adb file embedded in a sdcclib file. If there is
393 something between <ADB> and </ADB> returns 1, otherwise returns 0.
394 This way the aomf51 will not have uselless empty modules. */
396 int LoadAdb(FILE * libfp)
402 while (fgets(str, MAXLINE, libfp) != NULL)
404 str[NINPUT+1] = '\0';
409 if(EQ(str, "<ADB>")) state=1;
412 if(EQ(str, "</ADB>")) return ToReturn;
413 fprintf(dfp, "%s\n", str);
421 /*Check for a symbol in a SDCC library. If found, add the embedded .rel and
422 .adb files from the library. The library must be created with the SDCC
423 librarian 'sdcclib' since the linking process depends on the correct file offsets
424 embedded in the library file.*/
426 int SdccLib(char * PathLib, FILE * libfp, char * DirLib, char * SymName)
428 struct lbfile *lbfh, *lbf;
429 char ModName[NCPS]="";
430 char FLine[MAXLINE+1];
432 long IndexOffset=0, FileOffset;
437 fgets(FLine, MAXLINE, libfp);
443 if(EQ(FLine, "<INDEX>"))
445 /*The next line has the size of the index*/
447 fgets(FLine, MAXLINE, libfp);
449 IndexOffset=atol(FLine);
454 if(EQ(FLine, "<MODULE>"))
456 /*The next line has the name of the module and the offset
457 of the corresponding embedded file in the library*/
459 fgets(FLine, MAXLINE, libfp);
461 sscanf(FLine, "%s %ld", ModName, &FileOffset);
464 else if(EQ(FLine, "</INDEX>"))
466 /*Reached the end of the index. The symbol is not in this library.*/
471 if(EQ(FLine, "</MODULE>"))
473 /*The symbol is not in this module, try the next one*/
478 /*Check if this is the symbol we are looking for.*/
479 if (strncmp(SymName, FLine, NCPS)==0)
481 /*The symbol is in this module.*/
483 /*As in the original library format, it is assumed that the .rel
484 files reside in the same directory as the lib files.*/
485 strcat(DirLib, ModName);
486 sprintf(&DirLib[strlen(DirLib)], "%crel", FSEPX);
488 /*If this module has been loaded already don't load it again.*/
492 if(EQ(DirLib, lbf->filspc)) return 1;/*Already loaded*/
496 /*Add the embedded file to the list of files to be loaded in
497 the second pass. That is performed latter by the function
499 lbfh = (struct lbfile *) new (sizeof(struct lbfile));
512 lbfh->libspc = PathLib;
513 lbfh->filspc = DirLib;
514 lbfh->relfil = (char *) new (strlen(ModName) + 1);
515 strcpy(lbfh->relfil, ModName);
516 /*Library embedded file, so lbfh->offset must be >=0*/
517 lbfh->offset = IndexOffset+FileOffset;
519 /*Jump to where the .rel begins and load it.*/
520 fseek(libfp, lbfh->offset, SEEK_SET);
521 LoadRel(libfp, ModName);
523 /* if cdb information required & .adb file present */
527 SaveLinkedFilePath(DirLib);
529 return 1; /*Found the symbol, so success!*/
535 return 0; /*It should never reach this point, but just in case...*/
540 return 0; /*The symbol is not in this library*/
543 /*)Function VOID fndsym(name)
545 * char *name symbol name to find
547 * The function fndsym() searches through all combinations of the
548 * library path specifications (input by the -k option) and the
549 * library file specifications (input by the -l option) that
550 * lead to an existing file.
552 * The file specicifation may be formed in one of two ways:
554 * (1) If the library file contained an absolute
555 * path/file specification then this becomes filspc.
558 * (2) If the library file contains a relative path/file
559 * specification then the concatenation of the path
560 * and this file specification becomes filspc.
563 * The structure lbfile is created for the first library
564 * object file which contains the definition for the
565 * specified undefined symbol.
567 * If the library file [.LIB] contains file specifications for
568 * non existant files, no errors are returned.
571 * char buf[] [.REL] file input line
572 * char c [.REL] file input character
573 * FILE *fp file handle for object file
574 * lbfile *lbf temporary pointer
575 * lbfile *lbfh pointer to lbfile structure
576 * FILE *libfp file handle for library file
577 * lbname *lbnh pointer to lbname structure
578 * char *path file specification path
579 * char relfil[] [.REL] file specification
580 * char *str combined path and file specification
581 * char symname[] [.REL] file symbol string
584 * lbname *lbnhead The pointer to the first
586 * lbfile *lbfhead The pointer to the first
590 * int fclose() c_library
591 * int fgets() c_library
592 * FILE *fopen() c_library
593 * VOID free() c_library
594 * char getnb() lklex.c
595 * VOID lkexit() lkmain.c
596 * VOID loadfile() lklibr.c
597 * VOID * new() lksym.c
598 * char * sprintf() c_library
599 * int sscanf() c_library
600 * char * strcat() c_library
601 * char * strchr() c_library
602 * char * strcpy() c_library
603 * int strlen() c_library
604 * int strncmp() c_library
605 * VOID unget() lklex.c
608 * If the symbol is found then a new lbfile structure
609 * is created and added to the linked list of lbfile
610 * structures. The file containing the found symbol
620 struct lbfile *lbfh, *lbf;
621 char relfil[NINPUT+2];
623 char symname[NINPUT];
629 * Search through every library in the linked list "lbnhead".
632 for (lbnh=lbnhead; lbnh; lbnh=lbnh->next)
634 if ((libfp = fopen(lbnh->libspc, "r")) == NULL)
636 fprintf(stderr, "Cannot open library file %s\n",
643 * Read in a line from the library file.
644 * This is the relative file specification
645 * for a .REL file in this library.
648 while (fgets(relfil, NINPUT, libfp) != NULL)
650 relfil[NINPUT+1] = '\0';
654 str = (char *) new (strlen(path)+strlen(relfil)+6);
657 if (str[strlen(str)-1] != '/')
665 str = (char *) new (strlen(relfil) + 5);
668 if(strcmp(relfil, "<SDCCLIB>")==0)
670 result=SdccLib(lbnh->libspc, libfp, str, name);
672 if(result) return(1); /*Found the symbol*/
674 /*The symbol is not in the current library,
675 check the next library in the list*/
679 /*From here down is the support for libraries in the original format*/
680 if (relfil[0] == '\\')
682 strcat(str,relfil+1);
689 if(strchr(relfil, FSEPX) == NULL)
691 sprintf(&str[strlen(str)], "%crel", FSEPX);
694 if ((fp = fopen(str, "r")) != NULL)
698 * Read in the object file. Look for lines that
699 * begin with "S" and end with "D". These are
700 * symbol table definitions. If we find one, see
701 * if it is our symbol. Make sure we only read in
702 * our object file and don't go into the next one.
705 while (fgets(buf, NINPUT, fp) != NULL)
707 buf[NINPUT+1] = '\0';
710 * Skip everything that's not a symbol record.
712 if (buf[0] != 'S') continue;
715 * When a 'T line' is found terminate file scan.
716 * All 'S line's preceed 'T line's in .REL files.
718 if (buf[0] == 'T') break;
720 sscanf(buf, "S %s %c", symname, &c);
723 * If we find a symbol definition for the
724 * symbol we're looking for, load in the
725 * file and add it to lbfhead so it gets
726 * loaded on pass number 2.
728 if (strncmp(symname, name, NCPS) == 0 && c == 'D')
730 lbfh = (struct lbfile *) new (sizeof(struct lbfile));
743 lbfh->libspc = lbnh->libspc;
745 lbfh->relfil = (char *) new (strlen(relfil) + 1);
746 lbfh->offset = -1; /*Stand alone rel file*/
747 strcpy(lbfh->relfil,relfil);
751 /* if cdb information required & adb file present */
754 FILE *xfp = afile(str,"adb",0); //JCF: Nov 30, 2002
757 SaveLinkedFilePath(str);
775 void loadfile_SdccLib(char * libspc, char * module, long offset)
779 if ((fp = fopen(libspc,"r")) != NULL)
781 fseek(fp, offset, SEEK_SET);
787 /*)Function VOID library()
789 * The function library() links all the library object files
790 * contained in the lbfile structures.
793 * lbfile *lbfh pointer to lbfile structure
796 * lbfile *lbfhead pointer to first lbfile structure
799 * VOID loadfile lklibr.c
802 * Links all files contained in the lbfile structures.
810 for (lbfh=lbfhead; lbfh; lbfh=lbfh->next)
814 /*Stand alone rel file (original lib format)*/
815 loadfile(lbfh->filspc);
819 /*rel file embedded in lib (new lib format)*/
820 loadfile_SdccLib(lbfh->libspc, lbfh->relfil, lbfh->offset);
825 /*)Function VOID loadfile(filspc)
827 * char *filspc library object file specification
829 * The function loadfile() links the library object module.
832 * FILE *fp file handle
833 * int i input line length
834 * char str[] file input line
837 * char *ip pointer to linker input string
840 * int fclose() c_library
841 * int fgets() c_library
842 * FILE * fopen() c_library
843 * VOID link_main() lkmain.c
844 * int strlen() c_library
847 * If file exists it is linked.
857 if ((fp = fopen(filspc,"r")) != NULL) {
858 while (fgets(str, NINPUT, fp) != NULL) {
859 str[NINPUT+1] = '\0';