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>
36 * The module lklibr.c contains the functions which
37 * (1) specify the path(s) to library files [.LIB]
38 * (2) specify the library file(s) [.LIB] to search
39 * (3) search the library files for specific symbols
40 * and link the module containing this symbol
42 * lklibr.c contains the following functions:
53 /*)Function VOID addpath()
55 * The function addpath() creates a linked structure containing
56 * the paths to various object module library files.
59 * lbpath *lbph pointer to new path structure
60 * lbpath *lbp temporary pointer
63 * lbpath *lbphead The pointer to the first
67 * char getnb() lklex.c
68 * VOID * new() lksym.c
69 * int strlen() c_library
70 * char * strcpy() c_library
71 * VOID unget() lklex.c
74 * An lbpath structure may be created.
80 struct lbpath *lbph, *lbp;
82 lbph = (struct lbpath *) new (sizeof(struct lbpath));
83 if (lbphead == NULL) {
92 lbph->path = (char *) new (strlen(ip)+1);
93 strcpy(lbph->path, ip);
96 /*)Function VOID addlib()
98 * The function addlib() tests for the existance of a
99 * library path structure to determine the method of
100 * adding this library file to the library search structure.
102 * This function calls the function addfile() to actually
103 * add the library file to the search list.
106 * lbpath *lbph pointer to path structure
109 * lbpath *lbphead The pointer to the first
111 * ip a pointer to the library name
114 * VOID addfile() lklibr.c
115 * char getnb() lklex.c
116 * VOID unget() lklex.c
119 * The function addfile() may add the file to
120 * the library search list.
133 foundcount=addfile(NULL, ip);
137 for (lbph=lbphead; lbph; lbph=lbph->next)
139 foundcount+=addfile(lbph->path, ip);
144 printf("?ASlink-Warning-Couldn't find library '%s'\n", ip);
148 /*)Function int addfile(path,libfil)
150 * char *path library path specification
151 * char *libfil library file specification
153 * The function addfile() searches for the library file
154 * by concatenating the path and libfil specifications.
155 * if the library is found, an lbname structure is created
156 * and linked to any previously defined structures. This
157 * linked list is used by the function fndsym() to attempt
158 * to find any undefined symbols.
160 * The function does not give report an error on invalid
161 * path / file specifications or if the file is not found.
164 * lbname *lbnh pointer to new name structure
165 * lbname *lbn temporary pointer
168 * lbname *lbnhead The pointer to the first
172 * char getnb() lklex.c
173 * VOID * new() lksym.c
174 * int strlen() c_library
175 * char * strcpy() c_library
176 * VOID unget() lklex.c
179 * An lbname structure may be created.
182 * 1: the library was found
183 * 0: the library was not found
186 int addfile(char * path, char * libfil)
190 struct lbname *lbnh, *lbn;
197 str = (char *) new (strlen(path) + strlen(libfil) + 6);
200 if (str[strlen(str)-1] != '/')
208 str = (char *) new (strlen(libfil) + 5);
212 if (libfil[0] == '/')
220 if(strchr(libfil, FSEPX) == NULL)
222 sprintf(&str[strlen(str)], "%clib", FSEPX);
228 /*Ok, that didn't work. Try with the 'libfil' name only*/
230 if(libfilinc) libfil--;
232 fp=fopen(libfil, "r");
235 /*Bingo! 'libfil' is the absolute path of the library*/
237 path=NULL;/*This way 'libfil' and 'path' will be rebuilt from 'str'*/
243 /*'path' can not be null since it is needed to find the '.rel' files associated with
244 the library. So, get 'path' from 'str' and then chop it off and recreate 'libfil'.
245 That way putting 'path' and 'libfil' together will result into the original filepath
246 as contained in 'str'.*/
248 path = (char *) new (strlen(str));
250 for(j=strlen(path)-1; j>=0; j--)
252 if((path[j]=='\\')||(path[j]=='/'))
254 strcpy(libfil, &path[j+1]);
265 lbnh = (struct lbname *) new (sizeof(struct lbname));
279 lbnh->libfil = (char *) new (strlen(libfil) + 1);
280 strcpy(lbnh->libfil,libfil);
291 /*)Function VOID search()
293 * The function search() looks through all the symbol tables
294 * at the end of pass 1. If any undefined symbols are found
295 * then the function fndsym() is called. Function fndsym()
296 * searches any specified library files to automagically
297 * import the object modules containing the needed symbol.
299 * After a symbol is found and imported by the function
300 * fndsym() the symbol tables are again searched. The
301 * symbol tables are search until no more symbols can be
302 * resolved within the library files. This ensures that
303 * back references from one library module to another are
307 * int i temporary counter
308 * sym *sp pointer to a symbol structure
309 * int symfnd found a symbol flag
312 * sym *symhash[] array of pointers to symbol tables
315 * int fndsym() lklibr.c
318 * If a symbol is found then the library object module
319 * containing the symbol will be imported and linked.
325 register struct sym *sp;
326 register int i,symfnd;
329 * Look for undefined symbols. Keep
330 * searching until no more symbols are resolved.
336 * Look through all the symbols
338 for (i=0; i<NHASH; ++i) {
341 /* If we find an undefined symbol
342 * (one where S_DEF is not set), then
343 * try looking for it. If we find it
344 * in any of the libraries then
345 * increment symfnd. This will force
346 * another pass of symbol searching and
347 * make sure that back references work.
349 if ((sp->s_type & S_DEF) == 0) {
350 if (fndsym(sp->s_id)) {
360 /*Load a .rel file embedded in a sdcclib file*/
361 void LoadRel(FILE * libfp, char * ModName)
366 while (fgets(str, NINPUT, libfp) != NULL)
368 str[NINPUT+1] = '\0';
373 if(EQ(str, "<FILE>"))
375 fgets(str, NINPUT, libfp);
376 str[NINPUT+1] = '\0';
378 if(EQ(str, ModName)) state=1;
381 printf("Bad offset in library file str=%s, Modname=%s\n", str, ModName);
387 if(EQ(str, "<REL>")) state=2;
390 if(EQ(str, "</REL>")) return;
398 /*Load an .adb file embedded in a sdcclib file. If there is
399 something between <ADB> and </ADB> returns 1, otherwise returns 0.
400 This way the aomf51 will not have uselless empty modules. */
402 int LoadAdb(FILE * libfp)
408 while (fgets(str, MAXLINE, libfp) != NULL)
410 str[NINPUT+1] = '\0';
415 if(EQ(str, "<ADB>")) state=1;
418 if(EQ(str, "</ADB>")) return ToReturn;
419 fprintf(dfp, "%s\n", str);
427 /*Check for a symbol in a SDCC library. If found, add the embedded .rel and
428 .adb files from the library. The library must be created with the SDCC
429 librarian 'sdcclib' since the linking process depends on the correct file offsets
430 embedded in the library file.*/
432 int SdccLib(char * PathLib, FILE * libfp, char * DirLib, char * SymName)
434 struct lbfile *lbfh, *lbf;
435 char ModName[NCPS]="";
436 char FLine[MAXLINE+1];
438 long IndexOffset=0, FileOffset;
443 fgets(FLine, MAXLINE, libfp);
449 if(EQ(FLine, "<INDEX>"))
451 /*The next line has the size of the index*/
453 fgets(FLine, MAXLINE, libfp);
455 IndexOffset=atol(FLine);
460 if(EQ(FLine, "<MODULE>"))
462 /*The next line has the name of the module and the offset
463 of the corresponding embedded file in the library*/
465 fgets(FLine, MAXLINE, libfp);
467 sscanf(FLine, "%s %ld", ModName, &FileOffset);
470 else if(EQ(FLine, "</INDEX>"))
472 /*Reached the end of the index. The symbol is not in this library.*/
477 if(EQ(FLine, "</MODULE>"))
479 /*The symbol is not in this module, try the next one*/
484 /*Check if this is the symbol we are looking for.*/
485 if (strncmp(SymName, FLine, NCPS)==0)
487 /*The symbol is in this module.*/
489 /*As in the original library format, it is assumed that the .rel
490 files reside in the same directory as the lib files.*/
491 strcat(DirLib, ModName);
492 sprintf(&DirLib[strlen(DirLib)], "%crel", FSEPX);
494 /*If this module has been loaded already don't load it again.*/
498 if(EQ(DirLib, lbf->filspc)) return 1;/*Already loaded*/
502 /*Add the embedded file to the list of files to be loaded in
503 the second pass. That is performed latter by the function
505 lbfh = (struct lbfile *) new (sizeof(struct lbfile));
518 lbfh->libspc = PathLib;
519 lbfh->filspc = DirLib;
520 lbfh->relfil = (char *) new (strlen(ModName) + 1);
521 strcpy(lbfh->relfil, ModName);
522 /*Library embedded file, so lbfh->offset must be >=0*/
523 lbfh->offset = IndexOffset+FileOffset;
525 /*Jump to where the .rel begins and load it.*/
526 fseek(libfp, lbfh->offset, SEEK_SET);
527 LoadRel(libfp, ModName);
529 /* if cdb information required & .adb file present */
533 SaveLinkedFilePath(DirLib);
535 return 1; /*Found the symbol, so success!*/
541 return 0; /*It should never reach this point, but just in case...*/
546 return 0; /*The symbol is not in this library*/
549 /*)Function VOID fndsym(name)
551 * char *name symbol name to find
553 * The function fndsym() searches through all combinations of the
554 * library path specifications (input by the -k option) and the
555 * library file specifications (input by the -l option) that
556 * lead to an existing file.
558 * The file specicifation may be formed in one of two ways:
560 * (1) If the library file contained an absolute
561 * path/file specification then this becomes filspc.
564 * (2) If the library file contains a relative path/file
565 * specification then the concatenation of the path
566 * and this file specification becomes filspc.
569 * The structure lbfile is created for the first library
570 * object file which contains the definition for the
571 * specified undefined symbol.
573 * If the library file [.LIB] contains file specifications for
574 * non existant files, no errors are returned.
577 * char buf[] [.REL] file input line
578 * char c [.REL] file input character
579 * FILE *fp file handle for object file
580 * lbfile *lbf temporary pointer
581 * lbfile *lbfh pointer to lbfile structure
582 * FILE *libfp file handle for library file
583 * lbname *lbnh pointer to lbname structure
584 * char *path file specification path
585 * char relfil[] [.REL] file specification
586 * char *str combined path and file specification
587 * char symname[] [.REL] file symbol string
590 * lbname *lbnhead The pointer to the first
592 * lbfile *lbfhead The pointer to the first
596 * int fclose() c_library
597 * int fgets() c_library
598 * FILE *fopen() c_library
599 * VOID free() c_library
600 * char getnb() lklex.c
601 * VOID lkexit() lkmain.c
602 * VOID loadfile() lklibr.c
603 * VOID * new() lksym.c
604 * char * sprintf() c_library
605 * int sscanf() c_library
606 * char * strcat() c_library
607 * char * strchr() c_library
608 * char * strcpy() c_library
609 * int strlen() c_library
610 * int strncmp() c_library
611 * VOID unget() lklex.c
614 * If the symbol is found then a new lbfile structure
615 * is created and added to the linked list of lbfile
616 * structures. The file containing the found symbol
626 struct lbfile *lbfh, *lbf;
627 char relfil[NINPUT+2];
629 char symname[NINPUT];
635 * Search through every library in the linked list "lbnhead".
638 for (lbnh=lbnhead; lbnh; lbnh=lbnh->next)
640 if ((libfp = fopen(lbnh->libspc, "r")) == NULL)
642 fprintf(stderr, "Cannot open library file %s\n",
649 * Read in a line from the library file.
650 * This is the relative file specification
651 * for a .REL file in this library.
654 while (fgets(relfil, NINPUT, libfp) != NULL)
656 relfil[NINPUT+1] = '\0';
660 str = (char *) new (strlen(path)+strlen(relfil)+6);
663 if (str[strlen(str)-1] != '/')
671 str = (char *) new (strlen(relfil) + 5);
674 if(strcmp(relfil, "<SDCCLIB>")==0)
676 result=SdccLib(lbnh->libspc, libfp, str, name);
678 if(result) return(1); /*Found the symbol*/
680 /*The symbol is not in the current library,
681 check the next library in the list*/
685 /*From here down is the support for libraries in the original format*/
686 if (relfil[0] == '\\')
688 strcat(str,relfil+1);
695 if(strchr(relfil, FSEPX) == NULL)
697 sprintf(&str[strlen(str)], "%crel", FSEPX);
700 if ((fp = fopen(str, "r")) != NULL)
704 * Read in the object file. Look for lines that
705 * begin with "S" and end with "D". These are
706 * symbol table definitions. If we find one, see
707 * if it is our symbol. Make sure we only read in
708 * our object file and don't go into the next one.
711 while (fgets(buf, NINPUT, fp) != NULL)
713 buf[NINPUT+1] = '\0';
716 * Skip everything that's not a symbol record.
718 if (buf[0] != 'S') continue;
721 * When a 'T line' is found terminate file scan.
722 * All 'S line's preceed 'T line's in .REL files.
724 if (buf[0] == 'T') break;
726 sscanf(buf, "S %s %c", symname, &c);
729 * If we find a symbol definition for the
730 * symbol we're looking for, load in the
731 * file and add it to lbfhead so it gets
732 * loaded on pass number 2.
734 if (strncmp(symname, name, NCPS) == 0 && c == 'D')
736 lbfh = (struct lbfile *) new (sizeof(struct lbfile));
749 lbfh->libspc = lbnh->libspc;
751 lbfh->relfil = (char *) new (strlen(relfil) + 1);
752 lbfh->offset = -1; /*Stand alone rel file*/
753 strcpy(lbfh->relfil,relfil);
757 /* if cdb information required & adb file present */
760 FILE *xfp = afile(str,"adb",0); //JCF: Nov 30, 2002
763 SaveLinkedFilePath(str);
781 void loadfile_SdccLib(char * libspc, char * module, long offset)
785 if ((fp = fopen(libspc,"r")) != NULL)
787 fseek(fp, offset, SEEK_SET);
793 /*)Function VOID library()
795 * The function library() links all the library object files
796 * contained in the lbfile structures.
799 * lbfile *lbfh pointer to lbfile structure
802 * lbfile *lbfhead pointer to first lbfile structure
805 * VOID loadfile lklibr.c
808 * Links all files contained in the lbfile structures.
816 for (lbfh=lbfhead; lbfh; lbfh=lbfh->next)
820 /*Stand alone rel file (original lib format)*/
821 loadfile(lbfh->filspc);
825 /*rel file embedded in lib (new lib format)*/
826 loadfile_SdccLib(lbfh->libspc, lbfh->relfil, lbfh->offset);
831 /*)Function VOID loadfile(filspc)
833 * char *filspc library object file specification
835 * The function loadfile() links the library object module.
838 * FILE *fp file handle
839 * int i input line length
840 * char str[] file input line
843 * char *ip pointer to linker input string
846 * int fclose() c_library
847 * int fgets() c_library
848 * FILE * fopen() c_library
849 * VOID link_main() lkmain.c
850 * int strlen() c_library
853 * If file exists it is linked.
863 if ((fp = fopen(filspc,"r")) != NULL) {
864 while (fgets(str, NINPUT, fp) != NULL) {
865 str[NINPUT+1] = '\0';