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.
131 foundcount=addfile(NULL, ip);
135 for (lbph=lbphead; lbph; lbph=lbph->next)
137 foundcount+=addfile(lbph->path, ip);
142 printf("?ASlink-Warning-Couldn't find library '%s'\n", ip);
146 /*)Function int addfile(path,libfil)
148 * char *path library path specification
149 * char *libfil library file specification
151 * The function addfile() searches for the library file
152 * by concatenating the path and libfil specifications.
153 * if the library is found, an lbname structure is created
154 * and linked to any previously defined structures. This
155 * linked list is used by the function fndsym() to attempt
156 * to find any undefined symbols.
158 * The function does not give report an error on invalid
159 * path / file specifications or if the file is not found.
162 * lbname *lbnh pointer to new name structure
163 * lbname *lbn temporary pointer
166 * lbname *lbnhead The pointer to the first
170 * char getnb() lklex.c
171 * VOID * new() lksym.c
172 * int strlen() c_library
173 * char * strcpy() c_library
174 * VOID unget() lklex.c
177 * An lbname structure may be created.
180 * 1: the library was found
181 * 0: the library was not found
184 int addfile(char * path, char * libfil)
188 struct lbname *lbnh, *lbn;
195 str = (char *) new (strlen(path) + strlen(libfil) + 6);
198 if (str[strlen(str)-1] != '/')
206 str = (char *) new (strlen(libfil) + 5);
210 if (libfil[0] == '/')
218 if(strchr(libfil, FSEPX) == NULL)
220 sprintf(&str[strlen(str)], "%clib", FSEPX);
226 /*Ok, that didn't work. Try with the 'libfil' name only*/
228 if(libfilinc) libfil--;
230 fp=fopen(libfil, "r");
233 /*Bingo! 'libfil' is the absolute path of the library*/
235 path=NULL;/*This way 'libfil' and 'path' will be rebuilt from 'str'*/
241 /*'path' can not be null since it is needed to find the '.rel' files associated with
242 the library. So, get 'path' from 'str' and then chop it off and recreate 'libfil'.
243 That way putting 'path' and 'libfil' together will result into the original filepath
244 as contained in 'str'.*/
246 path = (char *) new (strlen(str));
248 for(j=strlen(path)-1; j>=0; j--)
250 if((path[j]=='\\')||(path[j]=='/'))
252 strcpy(libfil, &path[j+1]);
263 lbnh = (struct lbname *) new (sizeof(struct lbname));
277 lbnh->libfil = (char *) new (strlen(libfil) + 1);
278 strcpy(lbnh->libfil,libfil);
289 /*)Function VOID search()
291 * The function search() looks through all the symbol tables
292 * at the end of pass 1. If any undefined symbols are found
293 * then the function fndsym() is called. Function fndsym()
294 * searches any specified library files to automagically
295 * import the object modules containing the needed symbol.
297 * After a symbol is found and imported by the function
298 * fndsym() the symbol tables are again searched. The
299 * symbol tables are search until no more symbols can be
300 * resolved within the library files. This ensures that
301 * back references from one library module to another are
305 * int i temporary counter
306 * sym *sp pointer to a symbol structure
307 * int symfnd found a symbol flag
310 * sym *symhash[] array of pointers to symbol tables
313 * int fndsym() lklibr.c
316 * If a symbol is found then the library object module
317 * containing the symbol will be imported and linked.
323 register struct sym *sp;
324 register int i,symfnd;
327 * Look for undefined symbols. Keep
328 * searching until no more symbols are resolved.
334 * Look through all the symbols
336 for (i=0; i<NHASH; ++i) {
339 /* If we find an undefined symbol
340 * (one where S_DEF is not set), then
341 * try looking for it. If we find it
342 * in any of the libraries then
343 * increment symfnd. This will force
344 * another pass of symbol searching and
345 * make sure that back references work.
347 if ((sp->s_type & S_DEF) == 0) {
348 if (fndsym(sp->s_id)) {
358 /*Load a .rel file embedded in a sdcclib file*/
359 void LoadRel(FILE * libfp, char * ModName)
364 while (fgets(str, NINPUT, libfp) != NULL)
366 str[NINPUT+1] = '\0';
371 if(EQ(str, "<FILE>"))
373 fgets(str, NINPUT, libfp);
374 str[NINPUT+1] = '\0';
376 if(EQ(str, ModName)) state=1;
379 printf("Bad offset in library file str=%s, Modname=%s\n", str, ModName);
385 if(EQ(str, "<REL>")) state=2;
388 if(EQ(str, "</REL>")) return;
396 /*Load an .adb file embedded in a sdcclib file. If there is
397 something between <ADB> and </ADB> returns 1, otherwise returns 0.
398 This way the aomf51 will not have uselless empty modules. */
400 int LoadAdb(FILE * libfp)
406 while (fgets(str, MAXLINE, libfp) != NULL)
408 str[NINPUT+1] = '\0';
413 if(EQ(str, "<ADB>")) state=1;
416 if(EQ(str, "</ADB>")) return ToReturn;
417 fprintf(dfp, "%s\n", str);
425 /*Check for a symbol in a SDCC library. If found, add the embedded .rel and
426 .adb files from the library. The library must be created with the SDCC
427 librarian 'sdcclib' since the linking process depends on the correct file offsets
428 embedded in the library file.*/
430 int SdccLib(char * PathLib, FILE * libfp, char * DirLib, char * SymName)
432 struct lbfile *lbfh, *lbf;
433 char ModName[NCPS]="";
434 char FLine[MAXLINE+1];
436 long IndexOffset=0, FileOffset;
441 fgets(FLine, MAXLINE, libfp);
447 if(EQ(FLine, "<INDEX>"))
449 /*The next line has the size of the index*/
451 fgets(FLine, MAXLINE, libfp);
453 IndexOffset=atol(FLine);
458 if(EQ(FLine, "<MODULE>"))
460 /*The next line has the name of the module and the offset
461 of the corresponding embedded file in the library*/
463 fgets(FLine, MAXLINE, libfp);
465 sscanf(FLine, "%s %ld", ModName, &FileOffset);
468 else if(EQ(FLine, "</INDEX>"))
470 /*Reached the end of the index. The symbol is not in this library.*/
475 if(EQ(FLine, "</MODULE>"))
477 /*The symbol is not in this module, try the next one*/
482 /*Check if this is the symbol we are looking for.*/
483 if (strncmp(SymName, FLine, NCPS)==0)
485 /*The symbol is in this module.*/
487 /*As in the original library format, it is assumed that the .rel
488 files reside in the same directory as the lib files.*/
489 strcat(DirLib, ModName);
490 sprintf(&DirLib[strlen(DirLib)], "%crel", FSEPX);
492 /*If this module has been loaded already don't load it again.*/
496 if(EQ(DirLib, lbf->filspc)) return 1;/*Already loaded*/
500 /*Add the embedded file to the list of files to be loaded in
501 the second pass. That is performed latter by the function
503 lbfh = (struct lbfile *) new (sizeof(struct lbfile));
516 lbfh->libspc = PathLib;
517 lbfh->filspc = DirLib;
518 lbfh->relfil = (char *) new (strlen(ModName) + 1);
519 strcpy(lbfh->relfil, ModName);
520 /*Library embedded file, so lbfh->offset must be >=0*/
521 lbfh->offset = IndexOffset+FileOffset;
523 /*Jump to where the .rel begins and load it.*/
524 fseek(libfp, lbfh->offset, SEEK_SET);
525 LoadRel(libfp, ModName);
527 /* if cdb information required & .adb file present */
531 SaveLinkedFilePath(DirLib);
533 return 1; /*Found the symbol, so success!*/
539 return 0; /*It should never reach this point, but just in case...*/
544 return 0; /*The symbol is not in this library*/
547 /*)Function VOID fndsym(name)
549 * char *name symbol name to find
551 * The function fndsym() searches through all combinations of the
552 * library path specifications (input by the -k option) and the
553 * library file specifications (input by the -l option) that
554 * lead to an existing file.
556 * The file specicifation may be formed in one of two ways:
558 * (1) If the library file contained an absolute
559 * path/file specification then this becomes filspc.
562 * (2) If the library file contains a relative path/file
563 * specification then the concatenation of the path
564 * and this file specification becomes filspc.
567 * The structure lbfile is created for the first library
568 * object file which contains the definition for the
569 * specified undefined symbol.
571 * If the library file [.LIB] contains file specifications for
572 * non existant files, no errors are returned.
575 * char buf[] [.REL] file input line
576 * char c [.REL] file input character
577 * FILE *fp file handle for object file
578 * lbfile *lbf temporary pointer
579 * lbfile *lbfh pointer to lbfile structure
580 * FILE *libfp file handle for library file
581 * lbname *lbnh pointer to lbname structure
582 * char *path file specification path
583 * char relfil[] [.REL] file specification
584 * char *str combined path and file specification
585 * char symname[] [.REL] file symbol string
588 * lbname *lbnhead The pointer to the first
590 * lbfile *lbfhead The pointer to the first
594 * int fclose() c_library
595 * int fgets() c_library
596 * FILE *fopen() c_library
597 * VOID free() c_library
598 * char getnb() lklex.c
599 * VOID lkexit() lkmain.c
600 * VOID loadfile() lklibr.c
601 * VOID * new() lksym.c
602 * char * sprintf() c_library
603 * int sscanf() c_library
604 * char * strcat() c_library
605 * char * strchr() c_library
606 * char * strcpy() c_library
607 * int strlen() c_library
608 * int strncmp() c_library
609 * VOID unget() lklex.c
612 * If the symbol is found then a new lbfile structure
613 * is created and added to the linked list of lbfile
614 * structures. The file containing the found symbol
624 struct lbfile *lbfh, *lbf;
625 char relfil[NINPUT+2];
627 char symname[NINPUT];
633 * Search through every library in the linked list "lbnhead".
636 for (lbnh=lbnhead; lbnh; lbnh=lbnh->next)
638 if ((libfp = fopen(lbnh->libspc, "r")) == NULL)
640 fprintf(stderr, "Cannot open library file %s\n",
647 * Read in a line from the library file.
648 * This is the relative file specification
649 * for a .REL file in this library.
652 while (fgets(relfil, NINPUT, libfp) != NULL)
654 relfil[NINPUT+1] = '\0';
658 str = (char *) new (strlen(path)+strlen(relfil)+6);
661 if (str[strlen(str)-1] != '/')
669 str = (char *) new (strlen(relfil) + 5);
672 if(strcmp(relfil, "<SDCCLIB>")==0)
674 result=SdccLib(lbnh->libspc, libfp, str, name);
676 if(result) return(1); /*Found the symbol*/
678 /*The symbol is not in the current library,
679 check the next library in the list*/
683 /*From here down is the support for libraries in the original format*/
684 if (relfil[0] == '\\')
686 strcat(str,relfil+1);
693 if(strchr(relfil, FSEPX) == NULL)
695 sprintf(&str[strlen(str)], "%crel", FSEPX);
698 if ((fp = fopen(str, "r")) != NULL)
702 * Read in the object file. Look for lines that
703 * begin with "S" and end with "D". These are
704 * symbol table definitions. If we find one, see
705 * if it is our symbol. Make sure we only read in
706 * our object file and don't go into the next one.
709 while (fgets(buf, NINPUT, fp) != NULL)
711 buf[NINPUT+1] = '\0';
714 * Skip everything that's not a symbol record.
716 if (buf[0] != 'S') continue;
719 * When a 'T line' is found terminate file scan.
720 * All 'S line's preceed 'T line's in .REL files.
722 if (buf[0] == 'T') break;
724 sscanf(buf, "S %s %c", symname, &c);
727 * If we find a symbol definition for the
728 * symbol we're looking for, load in the
729 * file and add it to lbfhead so it gets
730 * loaded on pass number 2.
732 if (strncmp(symname, name, NCPS) == 0 && c == 'D')
734 lbfh = (struct lbfile *) new (sizeof(struct lbfile));
747 lbfh->libspc = lbnh->libspc;
749 lbfh->relfil = (char *) new (strlen(relfil) + 1);
750 lbfh->offset = -1; /*Stand alone rel file*/
751 strcpy(lbfh->relfil,relfil);
755 /* if cdb information required & adb file present */
758 FILE *xfp = afile(str,"adb",0); //JCF: Nov 30, 2002
761 SaveLinkedFilePath(str);
779 void loadfile_SdccLib(char * libspc, char * module, long offset)
783 if ((fp = fopen(libspc,"r")) != NULL)
785 fseek(fp, offset, SEEK_SET);
791 /*)Function VOID library()
793 * The function library() links all the library object files
794 * contained in the lbfile structures.
797 * lbfile *lbfh pointer to lbfile structure
800 * lbfile *lbfhead pointer to first lbfile structure
803 * VOID loadfile lklibr.c
806 * Links all files contained in the lbfile structures.
814 for (lbfh=lbfhead; lbfh; lbfh=lbfh->next)
818 /*Stand alone rel file (original lib format)*/
819 loadfile(lbfh->filspc);
823 /*rel file embedded in lib (new lib format)*/
824 loadfile_SdccLib(lbfh->libspc, lbfh->relfil, lbfh->offset);
829 /*)Function VOID loadfile(filspc)
831 * char *filspc library object file specification
833 * The function loadfile() links the library object module.
836 * FILE *fp file handle
837 * int i input line length
838 * char str[] file input line
841 * char *ip pointer to linker input string
844 * int fclose() c_library
845 * int fgets() c_library
846 * FILE * fopen() c_library
847 * VOID link_main() lkmain.c
848 * int strlen() c_library
851 * If file exists it is linked.
861 if ((fp = fopen(filspc,"r")) != NULL) {
862 while (fgets(str, NINPUT, fp) != NULL) {
863 str[NINPUT+1] = '\0';