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) {
86 lbph->path = (char *) new (strlen(ip)+1);
87 strcpy(lbph->path, ip);
90 /*)Function VOID addlib()
92 * The function addlib() tests for the existance of a
93 * library path structure to determine the method of
94 * adding this library file to the library search structure.
96 * This function calls the function addfile() to actually
97 * add the library file to the search list.
100 * lbpath *lbph pointer to path structure
103 * lbpath *lbphead The pointer to the first
105 * ip a pointer to the library name
108 * VOID addfile() lklibr.c
109 * char getnb() lklex.c
110 * VOID unget() lklex.c
113 * The function addfile() may add the file to
114 * the library search list.
127 foundcount=addfile(NULL, ip);
131 for (lbph=lbphead; lbph; lbph=lbph->next)
133 foundcount+=addfile(lbph->path, ip);
138 fprintf(stderr, "?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 (strlen(str) && (str[strlen(str)-1] != '/') && (str[strlen(str)-1] != LKDIRSEP))
196 strcat(str, LKDIRSEPSTR);
202 str = (char *) new (strlen(libfil) + 5);
206 if ((libfil[0] == '/') || (libfil[0] == LKDIRSEP))
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 object 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) + 1);
244 for(j=strlen(path)-1; j>=0; j--)
246 if((path[j] == '/') || (path[j] == LKDIRSEP))
248 strcpy(libfil, &path[j+1]);
259 lbnh = (struct lbname *) new (sizeof(struct lbname));
275 lbnh->libfil = (char *) new (strlen(libfil) + 1);
276 strcpy(lbnh->libfil, libfil);
287 /*)Function VOID search()
289 * The function search() looks through all the symbol tables
290 * at the end of pass 1. If any undefined symbols are found
291 * then the function fndsym() is called. Function fndsym()
292 * searches any specified library files to automagically
293 * import the object modules containing the needed symbol.
295 * After a symbol is found and imported by the function
296 * fndsym() the symbol tables are again searched. The
297 * symbol tables are search until no more symbols can be
298 * resolved within the library files. This ensures that
299 * back references from one library module to another are
303 * int i temporary counter
304 * sym *sp pointer to a symbol structure
305 * int symfnd found a symbol flag
308 * sym *symhash[] array of pointers to symbol tables
311 * int fndsym() lklibr.c
314 * If a symbol is found then the library object module
315 * containing the symbol will be imported and linked.
321 register struct sym *sp;
322 register int i, symfnd;
325 * Look for undefined symbols. Keep
326 * searching until no more symbols are resolved.
332 * Look through all the symbols
334 for (i=0; i<NHASH; ++i) {
337 /* If we find an undefined symbol
338 * (one where S_DEF is not set), then
339 * try looking for it. If we find it
340 * in any of the libraries then
341 * increment symfnd. This will force
342 * another pass of symbol searching and
343 * make sure that back references work.
345 if ((sp->s_type & S_DEF) == 0) {
346 if (fndsym(sp->s_id)) {
356 /*Load a .rel file embedded in a sdcclib file*/
357 void LoadRel(char * libfname, FILE * libfp, char * ModName)
362 while (fgets(str, NINPUT, libfp) != NULL)
364 str[NINPUT+1] = '\0';
369 if(EQ(str, "<FILE>"))
371 fgets(str, NINPUT, libfp);
372 str[NINPUT+1] = '\0';
374 if(EQ(str, ModName)) state=1;
377 fprintf(stderr, "?ASlink-Error-Bad offset in library file %s(%s)\n",
384 if(EQ(str, "<REL>")) state=2;
387 if(EQ(str, "</REL>")) return;
395 /*Load an .adb file embedded in a sdcclib file. If there is
396 something between <ADB> and </ADB> returns 1, otherwise returns 0.
397 This way the aomf51 will not have useless empty modules. */
399 int LoadAdb(FILE * libfp)
405 while (fgets(str, MAXLINE, libfp) != NULL)
407 str[NINPUT+1] = '\0';
412 if(EQ(str, "<ADB>")) state=1;
415 if(EQ(str, "</ADB>")) return ToReturn;
416 fprintf(dfp, "%s\n", str);
424 /*Check for a symbol in a SDCC library. If found, add the embedded .rel and
425 .adb files from the library. The library must be created with the SDCC
426 librarian 'sdcclib' since the linking process depends on the correct file offsets
427 embedded in the library file.*/
429 int SdccLib(char * PathLib, FILE * libfp, char * DirLib, char * SymName)
431 struct lbfile *lbfh, *lbf;
432 char ModName[NCPS]="";
433 char FLine[MAXLINE+1];
435 long IndexOffset=0, FileOffset;
440 fgets(FLine, MAXLINE, libfp);
446 if(EQ(FLine, "<INDEX>"))
448 /*The next line has the size of the index*/
450 fgets(FLine, MAXLINE, libfp);
452 IndexOffset=atol(FLine);
457 if(EQ(FLine, "<MODULE>"))
459 /*The next line has the name of the module and the offset
460 of the corresponding embedded file in the library*/
462 fgets(FLine, MAXLINE, libfp);
464 sscanf(FLine, "%s %ld", ModName, &FileOffset);
467 else if(EQ(FLine, "</INDEX>"))
469 /*Reached the end of the index. The symbol is not in this library.*/
474 if(EQ(FLine, "</MODULE>"))
476 /*The symbol is not in this module, try the next one*/
481 /*Check if this is the symbol we are looking for.*/
482 if (strncmp(SymName, FLine, NCPS)==0)
484 /*The symbol is in this module.*/
486 /*As in the original library format, it is assumed that the .rel
487 files reside in the same directory as the lib files.*/
488 strcat(DirLib, ModName);
489 sprintf(&DirLib[strlen(DirLib)], "%c%s", FSEPX, LKOBJEXT);
491 /*If this module has been loaded already don't load it again.*/
495 if(EQ(DirLib, lbf->filspc)) return 1;/*Already loaded*/
499 /*Add the embedded file to the list of files to be loaded in
500 the second pass. That is performed latter by the function
502 lbfh = (struct lbfile *) new (sizeof(struct lbfile));
517 lbfh->libspc = PathLib;
518 lbfh->filspc = DirLib;
519 lbfh->relfil = (char *) new (strlen(ModName) + 1);
520 strcpy(lbfh->relfil, ModName);
521 /*Library embedded file, so lbfh->offset must be >=0*/
522 lbfh->offset = IndexOffset+FileOffset;
524 /*Jump to where the .rel begins and load it.*/
525 fseek(libfp, lbfh->offset, SEEK_SET);
526 LoadRel(PathLib, libfp, ModName);
528 /* if cdb information required & .adb file present */
532 SaveLinkedFilePath(DirLib);
534 return 1; /*Found the symbol, so success!*/
540 return 0; /*It should never reach this point, but just in case...*/
545 return 0; /*The symbol is not in this library*/
548 /*)Function VOID fndsym(name)
550 * char *name symbol name to find
552 * The function fndsym() searches through all combinations of the
553 * library path specifications (input by the -k option) and the
554 * library file specifications (input by the -l option) that
555 * lead to an existing file.
557 * The file specicifation may be formed in one of two ways:
559 * (1) If the library file contained an absolute
560 * path/file specification then this becomes filspc.
563 * (2) If the library file contains a relative path/file
564 * specification then the concatenation of the path
565 * and this file specification becomes filspc.
568 * The structure lbfile is created for the first library
569 * object file which contains the definition for the
570 * specified undefined symbol.
572 * If the library file [.LIB] contains file specifications for
573 * non existant files, no errors are returned.
576 * char buf[] [.REL] file input line
577 * char c [.REL] file input character
578 * FILE *fp file handle for object file
579 * lbfile *lbf temporary pointer
580 * lbfile *lbfh pointer to lbfile structure
581 * FILE *libfp file handle for library file
582 * lbname *lbnh pointer to lbname structure
583 * char *path file specification path
584 * char relfil[] [.REL] file specification
585 * char *str combined path and file specification
586 * char symname[] [.REL] file symbol string
589 * lbname *lbnhead The pointer to the first
591 * lbfile *lbfhead The pointer to the first
595 * int fclose() c_library
596 * int fgets() c_library
597 * FILE *fopen() c_library
598 * VOID free() c_library
599 * char getnb() lklex.c
600 * VOID lkexit() lkmain.c
601 * VOID loadfile() lklibr.c
602 * VOID * new() lksym.c
603 * char * sprintf() c_library
604 * int sscanf() c_library
605 * char * strcat() c_library
606 * char * strchr() c_library
607 * char * strcpy() c_library
608 * int strlen() c_library
609 * int strncmp() c_library
610 * VOID unget() lklex.c
613 * If the symbol is found then a new lbfile structure
614 * is created and added to the linked list of lbfile
615 * 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, "?ASlink-Error-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 (strlen(str) && (str[strlen(str)-1] != '/') && (str[strlen(str)-1] != LKDIRSEP))
663 strcat(str, LKDIRSEPSTR);
669 str = (char *) new (strlen(relfil) + 5);
672 /*See if this is a library with embedded files*/
673 if(strcmp(relfil, "<SDCCLIB>")==0)
675 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] == '/') || (relfil[0] == LKDIRSEP))
686 strcat(str, relfil+1);
693 if(strchr(relfil, FSEPX) == NULL)
695 sprintf(&str[strlen(str)], "%c%s", FSEPX, LKOBJEXT);
698 if ((fp = fopen(str, "r")) != NULL)
701 * Read in the object file. Look for lines that
702 * begin with "S" and end with "D". These are
703 * symbol table definitions. If we find one, see
704 * if it is our symbol. Make sure we only read in
705 * our object file and don't go into the next one.
708 while (fgets(buf, NINPUT, fp) != NULL)
710 buf[NINPUT+1] = '\0';
713 * Skip everything that's not a symbol record.
719 * When a 'T line' is found terminate file scan.
720 * All 'S line's preceed 'T line's in .REL files.
725 sscanf(buf, "S %s %c", symname, &c);
728 * If we find a symbol definition for the
729 * symbol we're looking for, load in the
730 * file and add it to lbfhead so it gets
731 * loaded on pass number 2.
733 if (strncmp(symname, name, NCPS) == 0 && c == 'D')
735 lbfh = (struct lbfile *) new (sizeof(struct lbfile));
750 lbfh->libspc = lbnh->libspc;
752 lbfh->relfil = (char *) new (strlen(relfil) + 1);
753 lbfh->offset = -1; /*Stand alone rel file*/
754 strcpy(lbfh->relfil,relfil);
758 /* if cdb information required & adb file present */
761 FILE *xfp = afile(str,"adb",0); //JCF: Nov 30, 2002
764 SaveLinkedFilePath(str);
772 } /* Closes while - read object file */
774 } /* Closes if object file opened OK */
777 fprintf(stderr, "?ASlink-Warning-Cannot open library module %s\n", str);
780 } /* Ends while - processing all in libr */
782 } /* Ends good open of libr file */
786 void loadfile_SdccLib(char * libspc, char * module, long offset)
791 char posix_path[PATH_MAX];
792 void cygwin_conv_to_full_posix_path(char * win_path, char * posix_path);
793 cygwin_conv_to_full_posix_path(libspc, posix_path);
794 fp = fopen(posix_path, "r");
796 fp = fopen(libspc,"r");
801 fseek(fp, offset, SEEK_SET);
802 LoadRel(libspc, fp, module);
807 fprintf(stderr, "?ASlink-Error-Opening library '%s'\n", libspc);
812 /*)Function VOID library()
814 * The function library() links all the library object files
815 * contained in the lbfile structures.
818 * lbfile *lbfh pointer to lbfile structure
821 * lbfile *lbfhead pointer to first lbfile structure
824 * VOID loadfile lklibr.c
827 * Links all files contained in the lbfile structures.
835 for (lbfh=lbfhead; lbfh; lbfh=lbfh->next)
839 /*Stand alone rel file (original lib format)*/
840 loadfile(lbfh->filspc);
844 /*rel file embedded in lib (new lib format)*/
845 loadfile_SdccLib(lbfh->libspc, lbfh->relfil, lbfh->offset);
850 /*)Function VOID loadfile(filspc)
852 * char *filspc library object file specification
854 * The function loadfile() links the library object module.
857 * FILE *fp file handle
858 * int i input line length
859 * char str[] file input line
862 * char *ip pointer to linker input string
865 * int fclose() c_library
866 * int fgets() c_library
867 * FILE * fopen() c_library
868 * VOID link_main() lkmain.c
869 * int strlen() c_library
872 * If file exists it is linked.
876 loadfile(char *filspc)
882 char posix_path[PATH_MAX];
883 void cygwin_conv_to_full_posix_path(char * win_path, char * posix_path);
884 cygwin_conv_to_full_posix_path(filspc, posix_path);
885 fp = fopen(posix_path, "r");
887 fp = fopen(filspc,"r");
892 while (fgets(str, NINPUT, fp) != NULL)
894 str[NINPUT+1] = '\0';
903 fprintf(stderr, "?ASlink-Error-Opening library '%s'\n", filspc);