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*/
28 * The module lklibr.c contains the functions which
29 * (1) specify the path(s) to library files [.LIB]
30 * (2) specify the library file(s) [.LIB] to search
31 * (3) search the library files for specific symbols
32 * and link the module containing this symbol
34 * lklibr.c contains the following functions:
45 /*)Function VOID addpath()
47 * The function addpath() creates a linked structure containing
48 * the paths to various object module library files.
51 * lbpath *lbph pointer to new path structure
52 * lbpath *lbp temporary pointer
55 * lbpath *lbphead The pointer to the first
59 * char getnb() lklex.c
60 * VOID * new() lksym.c
61 * int strlen() c_library
62 * char * strcpy() c_library
63 * VOID unget() lklex.c
66 * An lbpath structure may be created.
72 struct lbpath *lbph, *lbp;
74 lbph = (struct lbpath *) new (sizeof(struct lbpath));
75 if (lbphead == NULL) {
84 lbph->path = (char *) new (strlen(ip)+1);
85 strcpy(lbph->path, ip);
88 /*)Function VOID addlib()
90 * The function addlib() tests for the existance of a
91 * library path structure to determine the method of
92 * adding this library file to the library search structure.
94 * This function calls the function addfile() to actually
95 * add the library file to the search list.
98 * lbpath *lbph pointer to path structure
101 * lbpath *lbphead The pointer to the first
103 * ip a pointer to the library name
106 * VOID addfile() lklibr.c
107 * char getnb() lklex.c
108 * VOID unget() lklex.c
111 * The function addfile() may add the file to
112 * the library search list.
125 foundcount=addfile(NULL, ip);
129 for (lbph=lbphead; lbph; lbph=lbph->next)
131 foundcount+=addfile(lbph->path, ip);
136 fprintf(stderr, "?ASlink-Warning-Couldn't find library '%s'\n", ip);
140 /*)Function int addfile(path,libfil)
142 * char *path library path specification
143 * char *libfil library file specification
145 * The function addfile() searches for the library file
146 * by concatenating the path and libfil specifications.
147 * if the library is found, an lbname structure is created
148 * and linked to any previously defined structures. This
149 * linked list is used by the function fndsym() to attempt
150 * to find any undefined symbols.
152 * The function does not give report an error on invalid
153 * path / file specifications or if the file is not found.
156 * lbname *lbnh pointer to new name structure
157 * lbname *lbn temporary pointer
160 * lbname *lbnhead The pointer to the first
164 * char getnb() lklex.c
165 * VOID * new() lksym.c
166 * int strlen() c_library
167 * char * strcpy() c_library
168 * VOID unget() lklex.c
171 * An lbname structure may be created.
174 * 1: the library was found
175 * 0: the library was not found
178 int addfile(char * path, char * libfil)
182 struct lbname *lbnh, *lbn;
189 str = (char *) new (strlen(path) + strlen(libfil) + 6);
192 if (strlen(str) && (str[strlen(str)-1] != '/') && (str[strlen(str)-1] != '\\'))
200 str = (char *) new (strlen(libfil) + 5);
204 if ((libfil[0] == '/') || (libfil[0] == '\\'))
212 if(strchr(libfil, FSEPX) == NULL)
214 sprintf(&str[strlen(str)], "%clib", FSEPX);
220 /*Ok, that didn't work. Try with the 'libfil' name only*/
222 if(libfilinc) libfil--;
224 fp=fopen(libfil, "r");
227 /*Bingo! 'libfil' is the absolute path of the library*/
229 path=NULL;/*This way 'libfil' and 'path' will be rebuilt from 'str'*/
235 /*'path' can not be null since it is needed to find the '.rel' files associated with
236 the library. So, get 'path' from 'str' and then chop it off and recreate 'libfil'.
237 That way putting 'path' and 'libfil' together will result into the original filepath
238 as contained in 'str'.*/
240 path = (char *) new (strlen(str) + 1);
242 for(j=strlen(path)-1; j>=0; j--)
244 if((path[j] == '/') || (path[j] == '\\'))
246 strcpy(libfil, &path[j+1]);
257 lbnh = (struct lbname *) new (sizeof(struct lbname));
271 lbnh->libfil = (char *) new (strlen(libfil) + 1);
272 strcpy(lbnh->libfil,libfil);
283 /*)Function VOID search()
285 * The function search() looks through all the symbol tables
286 * at the end of pass 1. If any undefined symbols are found
287 * then the function fndsym() is called. Function fndsym()
288 * searches any specified library files to automagically
289 * import the object modules containing the needed symbol.
291 * After a symbol is found and imported by the function
292 * fndsym() the symbol tables are again searched. The
293 * symbol tables are search until no more symbols can be
294 * resolved within the library files. This ensures that
295 * back references from one library module to another are
299 * int i temporary counter
300 * sym *sp pointer to a symbol structure
301 * int symfnd found a symbol flag
304 * sym *symhash[] array of pointers to symbol tables
307 * int fndsym() lklibr.c
310 * If a symbol is found then the library object module
311 * containing the symbol will be imported and linked.
317 register struct sym *sp;
318 register int i,symfnd;
321 * Look for undefined symbols. Keep
322 * searching until no more symbols are resolved.
328 * Look through all the symbols
330 for (i=0; i<NHASH; ++i) {
333 /* If we find an undefined symbol
334 * (one where S_DEF is not set), then
335 * try looking for it. If we find it
336 * in any of the libraries then
337 * increment symfnd. This will force
338 * another pass of symbol searching and
339 * make sure that back references work.
341 if ((sp->s_type & S_DEF) == 0) {
342 if (fndsym(sp->s_id)) {
352 /*Load a .rel file embedded in a sdcclib file*/
353 void LoadRel(FILE * libfp, char * ModName)
358 while (fgets(str, NINPUT, libfp) != NULL)
360 str[NINPUT+1] = '\0';
365 if(EQ(str, "<FILE>"))
367 fgets(str, NINPUT, libfp);
368 str[NINPUT+1] = '\0';
370 if(EQ(str, ModName)) state=1;
373 fprintf(stderr, "?ASlink-Error-Bad offset in library file str=%s, Modname=%s\n",
380 if(EQ(str, "<REL>")) state=2;
383 if(EQ(str, "</REL>")) return;
391 /*Load an .adb file embedded in a sdcclib file. If there is
392 something between <ADB> and </ADB> returns 1, otherwise returns 0.
393 This way the aomf51 will not have uselless empty modules. */
395 int LoadAdb(FILE * libfp)
401 while (fgets(str, MAXLINE, libfp) != NULL)
403 str[NINPUT+1] = '\0';
408 if(EQ(str, "<ADB>")) state=1;
411 if(EQ(str, "</ADB>")) return ToReturn;
412 fprintf(dfp, "%s\n", str);
420 /*Check for a symbol in a SDCC library. If found, add the embedded .rel and
421 .adb files from the library. The library must be created with the SDCC
422 librarian 'sdcclib' since the linking process depends on the correct file offsets
423 embedded in the library file.*/
425 int SdccLib(char * PathLib, FILE * libfp, char * DirLib, char * SymName)
427 struct lbfile *lbfh, *lbf;
428 char ModName[NCPS]="";
429 char FLine[MAXLINE+1];
431 long IndexOffset=0, FileOffset;
436 fgets(FLine, MAXLINE, libfp);
442 if(EQ(FLine, "<INDEX>"))
444 /*The next line has the size of the index*/
446 fgets(FLine, MAXLINE, libfp);
448 IndexOffset=atol(FLine);
453 if(EQ(FLine, "<MODULE>"))
455 /*The next line has the name of the module and the offset
456 of the corresponding embedded file in the library*/
458 fgets(FLine, MAXLINE, libfp);
460 sscanf(FLine, "%s %ld", ModName, &FileOffset);
463 else if(EQ(FLine, "</INDEX>"))
465 /*Reached the end of the index. The symbol is not in this library.*/
470 if(EQ(FLine, "</MODULE>"))
472 /*The symbol is not in this module, try the next one*/
477 /*Check if this is the symbol we are looking for.*/
478 if (strncmp(SymName, FLine, NCPS)==0)
480 /*The symbol is in this module.*/
482 /*As in the original library format, it is assumed that the .rel
483 files reside in the same directory as the lib files.*/
484 strcat(DirLib, ModName);
485 sprintf(&DirLib[strlen(DirLib)], "%crel", FSEPX);
487 /*If this module has been loaded already don't load it again.*/
491 if(EQ(DirLib, lbf->filspc)) return 1;/*Already loaded*/
495 /*Add the embedded file to the list of files to be loaded in
496 the second pass. That is performed latter by the function
498 lbfh = (struct lbfile *) new (sizeof(struct lbfile));
511 lbfh->libspc = PathLib;
512 lbfh->filspc = DirLib;
513 lbfh->relfil = (char *) new (strlen(ModName) + 1);
514 strcpy(lbfh->relfil, ModName);
515 /*Library embedded file, so lbfh->offset must be >=0*/
516 lbfh->offset = IndexOffset+FileOffset;
518 /*Jump to where the .rel begins and load it.*/
519 fseek(libfp, lbfh->offset, SEEK_SET);
520 LoadRel(libfp, ModName);
522 /* if cdb information required & .adb file present */
526 SaveLinkedFilePath(DirLib);
528 return 1; /*Found the symbol, so success!*/
534 return 0; /*It should never reach this point, but just in case...*/
539 return 0; /*The symbol is not in this library*/
542 /*)Function VOID fndsym(name)
544 * char *name symbol name to find
546 * The function fndsym() searches through all combinations of the
547 * library path specifications (input by the -k option) and the
548 * library file specifications (input by the -l option) that
549 * lead to an existing file.
551 * The file specicifation may be formed in one of two ways:
553 * (1) If the library file contained an absolute
554 * path/file specification then this becomes filspc.
557 * (2) If the library file contains a relative path/file
558 * specification then the concatenation of the path
559 * and this file specification becomes filspc.
562 * The structure lbfile is created for the first library
563 * object file which contains the definition for the
564 * specified undefined symbol.
566 * If the library file [.LIB] contains file specifications for
567 * non existant files, no errors are returned.
570 * char buf[] [.REL] file input line
571 * char c [.REL] file input character
572 * FILE *fp file handle for object file
573 * lbfile *lbf temporary pointer
574 * lbfile *lbfh pointer to lbfile structure
575 * FILE *libfp file handle for library file
576 * lbname *lbnh pointer to lbname structure
577 * char *path file specification path
578 * char relfil[] [.REL] file specification
579 * char *str combined path and file specification
580 * char symname[] [.REL] file symbol string
583 * lbname *lbnhead The pointer to the first
585 * lbfile *lbfhead The pointer to the first
589 * int fclose() c_library
590 * int fgets() c_library
591 * FILE *fopen() c_library
592 * VOID free() c_library
593 * char getnb() lklex.c
594 * VOID lkexit() lkmain.c
595 * VOID loadfile() lklibr.c
596 * VOID * new() lksym.c
597 * char * sprintf() c_library
598 * int sscanf() c_library
599 * char * strcat() c_library
600 * char * strchr() c_library
601 * char * strcpy() c_library
602 * int strlen() c_library
603 * int strncmp() c_library
604 * VOID unget() lklex.c
607 * If the symbol is found then a new lbfile structure
608 * is created and added to the linked list of lbfile
609 * structures. The file containing the found symbol
619 struct lbfile *lbfh, *lbf;
620 char relfil[NINPUT+2];
622 char symname[NINPUT];
628 * Search through every library in the linked list "lbnhead".
631 for (lbnh=lbnhead; lbnh; lbnh=lbnh->next)
633 if ((libfp = fopen(lbnh->libspc, "r")) == NULL)
635 fprintf(stderr, "ASlink-Error-Cannot open library file %s\n",
642 * Read in a line from the library file.
643 * This is the relative file specification
644 * for a .REL file in this library.
647 while (fgets(relfil, NINPUT, libfp) != NULL)
649 relfil[NINPUT+1] = '\0';
653 str = (char *) new (strlen(path)+strlen(relfil)+6);
656 if (strlen(str) && (str[strlen(str)-1] != '/') && (str[strlen(str)-1] != '\\'))
664 str = (char *) new (strlen(relfil) + 5);
667 if(strcmp(relfil, "<SDCCLIB>")==0)
669 result=SdccLib(lbnh->libspc, libfp, str, name);
671 if(result) return(1); /*Found the symbol*/
673 /*The symbol is not in the current library,
674 check the next library in the list*/
678 /*From here down is the support for libraries in the original format*/
679 if (relfil[0] == '\\')
681 strcat(str,relfil+1);
688 if(strchr(relfil, FSEPX) == NULL)
690 sprintf(&str[strlen(str)], "%crel", FSEPX);
693 if ((fp = fopen(str, "r")) != NULL)
697 * Read in the object file. Look for lines that
698 * begin with "S" and end with "D". These are
699 * symbol table definitions. If we find one, see
700 * if it is our symbol. Make sure we only read in
701 * our object file and don't go into the next one.
704 while (fgets(buf, NINPUT, fp) != NULL)
706 buf[NINPUT+1] = '\0';
709 * Skip everything that's not a symbol record.
711 if (buf[0] != 'S') continue;
714 * When a 'T line' is found terminate file scan.
715 * All 'S line's preceed 'T line's in .REL files.
717 if (buf[0] == 'T') break;
719 sscanf(buf, "S %s %c", symname, &c);
722 * If we find a symbol definition for the
723 * symbol we're looking for, load in the
724 * file and add it to lbfhead so it gets
725 * loaded on pass number 2.
727 if (strncmp(symname, name, NCPS) == 0 && c == 'D')
729 lbfh = (struct lbfile *) new (sizeof(struct lbfile));
742 lbfh->libspc = lbnh->libspc;
744 lbfh->relfil = (char *) new (strlen(relfil) + 1);
745 lbfh->offset = -1; /*Stand alone rel file*/
746 strcpy(lbfh->relfil,relfil);
750 /* if cdb information required & adb file present */
753 FILE *xfp = afile(str,"adb",0); //JCF: Nov 30, 2002
756 SaveLinkedFilePath(str);
774 void loadfile_SdccLib(char * libspc, char * module, long offset)
778 if ((fp = fopen(libspc,"r")) != NULL)
780 fseek(fp, offset, SEEK_SET);
786 /*)Function VOID library()
788 * The function library() links all the library object files
789 * contained in the lbfile structures.
792 * lbfile *lbfh pointer to lbfile structure
795 * lbfile *lbfhead pointer to first lbfile structure
798 * VOID loadfile lklibr.c
801 * Links all files contained in the lbfile structures.
809 for (lbfh=lbfhead; lbfh; lbfh=lbfh->next)
813 /*Stand alone rel file (original lib format)*/
814 loadfile(lbfh->filspc);
818 /*rel file embedded in lib (new lib format)*/
819 loadfile_SdccLib(lbfh->libspc, lbfh->relfil, lbfh->offset);
824 /*)Function VOID loadfile(filspc)
826 * char *filspc library object file specification
828 * The function loadfile() links the library object module.
831 * FILE *fp file handle
832 * int i input line length
833 * char str[] file input line
836 * char *ip pointer to linker input string
839 * int fclose() c_library
840 * int fgets() c_library
841 * FILE * fopen() c_library
842 * VOID link_main() lkmain.c
843 * int strlen() c_library
846 * If file exists it is linked.
856 if ((fp = fopen(filspc,"r")) != NULL) {
857 while (fgets(str, NINPUT, fp) != NULL) {
858 str[NINPUT+1] = '\0';