4 * (C) Copyright 1989-1995
11 * With contributions for the
12 * object libraries from
14 * kenh@cmf.nrl.navy.mil
19 * Extensions: P. Felber
22 #define EQ(A,B) !strcmp((A),(B))
23 #define MAXLINE 254 /*when using fgets*/
34 #define LKDIRSEPSTR "/"
37 #define LKDIRSEPSTR "\\"
41 #define LKDIRSEPSTR "\\"
46 void ToCygWin(char * filspc)
48 char posix_path[PATH_MAX];
49 void cygwin_conv_to_full_posix_path(char * win_path, char * posix_path);
50 cygwin_conv_to_full_posix_path(filspc, posix_path);
51 strcpy(filspc, posix_path);
57 * The module lklibr.c contains the functions which
58 * (1) specify the path(s) to library files [.LIB]
59 * (2) specify the library file(s) [.LIB] to search
60 * (3) search the library files for specific symbols
61 * and link the module containing this symbol
63 * lklibr.c contains the following functions:
75 typedef struct slibrarysymbol mlibrarysymbol;
76 typedef struct slibrarysymbol *pmlibrarysymbol;
78 struct slibrarysymbol {
83 typedef struct slibraryfile mlibraryfile;
84 typedef struct slibraryfile *pmlibraryfile;
91 char filename[FILSPC];
92 long offset; //if > 0, the embedded file offset in the library file libspc
93 pmlibrarysymbol symbols;
97 int buildlibraryindex();
100 /*)Function VOID addpath()
102 * The function addpath() creates a linked structure containing
103 * the paths to various object module library files.
106 * lbpath *lbph pointer to new path structure
107 * lbpath *lbp temporary pointer
110 * lbpath *lbphead The pointer to the first
114 * char getnb() lklex.c
115 * VOID * new() lksym.c
116 * int strlen() c_library
117 * char * strcpy() c_library
118 * VOID unget() lklex.c
121 * An lbpath structure may be created.
127 struct lbpath *lbph, *lbp;
129 lbph = (struct lbpath *) new (sizeof(struct lbpath));
130 if (lbphead == NULL) {
139 lbph->path = (char *) new (strlen(ip)+1);
140 strcpy(lbph->path, ip);
143 /*)Function VOID addlib()
145 * The function addlib() tests for the existance of a
146 * library path structure to determine the method of
147 * adding this library file to the library search structure.
149 * This function calls the function addfile() to actually
150 * add the library file to the search list.
153 * lbpath *lbph pointer to path structure
156 * lbpath *lbphead The pointer to the first
158 * ip a pointer to the library name
161 * VOID addfile() lklibr.c
162 * char getnb() lklex.c
163 * VOID unget() lklex.c
166 * The function addfile() may add the file to
167 * the library search list.
178 if (lbphead == NULL) {
182 for (lbph=lbphead; lbph; lbph=lbph->next) {
183 foundcount+=addfile(lbph->path,ip);
187 printf("?ASlink-Warning-Couldn't find library '%s'\n", ip);
191 /*)Function int addfile(path,libfil)
193 * char *path library path specification
194 * char *libfil library file specification
196 * The function addfile() searches for the library file
197 * by concatenating the path and libfil specifications.
198 * if the library is found, an lbname structure is created
199 * and linked to any previously defined structures. This
200 * linked list is used by the function fndsym() to attempt
201 * to find any undefined symbols.
203 * The function does not give report an error on invalid
204 * path / file specifications or if the file is not found.
207 * lbname *lbnh pointer to new name structure
208 * lbname *lbn temporary pointer
211 * lbname *lbnhead The pointer to the first
215 * char getnb() lklex.c
216 * VOID * new() lksym.c
217 * int strlen() c_library
218 * char * strcpy() c_library
219 * VOID unget() lklex.c
222 * An lbname structure may be created.
225 * 1: the library was found
226 * 0: the library was not found
229 int addfile(char * path, char * libfil)
233 struct lbname *lbnh, *lbn;
238 str = (char *) new (strlen(path) + strlen(libfil) + 6);
241 if (str[strlen(str)-1] != LKDIRSEP)
243 strcat(str, LKDIRSEPSTR);
248 str = (char *) new (strlen(libfil) + 5);
251 if (libfil[0] == LKDIRSEP)
259 if(strchr(libfil, FSEPX) == NULL)
261 sprintf(&str[strlen(str)], "%clib", FSEPX);
267 /*Ok, that didn't work. Try with the 'libfil' name only*/
268 if(libfilinc) libfil--;
269 fp=fopen(libfil, "r");
272 /*Bingo! 'libfil' is the absolute path of the library*/
274 path=NULL;/*This way 'libfil' and 'path' will be rebuilt from 'str'*/
280 /*'path' can not be null since it is needed to find the '.o' files associated with
281 the library. So, get 'path' from 'str' and then chop it off and recreate 'libfil'.
282 That way putting 'path' and 'libfil' together will result into the original filepath
283 as contained in 'str'.*/
285 path = (char *) new (strlen(str));
287 for(j=strlen(path)-1; j>=0; j--)
289 if((path[j]=='\\')||(path[j]=='/'))
291 strcpy(libfil, &path[j+1]);
302 lbnh = (struct lbname *) new (sizeof(struct lbname));
316 lbnh->libfil = (char *) new (strlen(libfil) + 1);
317 strcpy(lbnh->libfil, libfil);
328 /*)Function VOID search()
330 * The function search() looks through all the symbol tables
331 * at the end of pass 1. If any undefined symbols are found
332 * then the function fndsym() is called. Function fndsym()
333 * searches any specified library files to automagically
334 * import the object modules containing the needed symbol.
336 * After a symbol is found and imported by the function
337 * fndsym() the symbol tables are again searched. The
338 * symbol tables are search until no more symbols can be
339 * resolved within the library files. This ensures that
340 * back references from one library module to another are
344 * int i temporary counter
345 * sym *sp pointer to a symbol structure
346 * int symfnd found a symbol flag
349 * sym *symhash[] array of pointers to symbol tables
352 * int fndsym() lklibr.c
355 * If a symbol is found then the library object module
356 * containing the symbol will be imported and linked.
362 register struct sym *sp;
363 register int i, symfnd;
366 * Look for undefined symbols. Keep
367 * searching until no more symbols are resolved.
373 * Look through all the symbols
375 for (i=0; i<NHASH; ++i) {
378 /* If we find an undefined symbol
379 * (one where S_DEF is not set), then
380 * try looking for it. If we find it
381 * in any of the libraries then
382 * increment symfnd. This will force
383 * another pass of symbol searching and
384 * make sure that back references work.
386 if ((sp->s_type & S_DEF) == 0) {
387 if (fndsym(sp->s_id)) {
397 /*Load a .rel file embedded in a sdcclib file*/
398 void LoadRel(FILE * libfp, char * ModName)
403 while (fgets(str, NINPUT, libfp) != NULL)
405 str[NINPUT+1] = '\0';
410 if(EQ(str, "<FILE>"))
412 fgets(str, NINPUT, libfp);
413 str[NINPUT+1] = '\0';
415 if(EQ(str, ModName)) state=1;
418 printf("Bad offset in library file str=%s, Modname=%s\n", str, ModName);
424 if(EQ(str, "<REL>")) state=2;
427 if(EQ(str, "</REL>")) return;
435 /*)Function VOID fndsym(name)
437 * char *name symbol name to find
439 * The function fndsym() searches through all combinations of the
440 * library path specifications (input by the -k option) and the
441 * library file specifications (input by the -l option) that
442 * lead to an existing file.
444 * The file specicifation may be formed in one of two ways:
446 * (1) If the library file contained an absolute
447 * path/file specification then this becomes filspc.
450 * (2) If the library file contains a relative path/file
451 * specification then the concatenation of the path
452 * and this file specification becomes filspc.
455 * The structure lbfile is created for the first library
456 * object file which contains the definition for the
457 * specified undefined symbol.
459 * If the library file [.LIB] contains file specifications for
460 * non existant files, no errors are returned.
463 * char buf[] [.REL] file input line
464 * char c [.REL] file input character
465 * FILE *fp file handle for object file
466 * lbfile *lbf temporary pointer
467 * lbfile *lbfh pointer to lbfile structure
468 * FILE *libfp file handle for library file
469 * lbname *lbnh pointer to lbname structure
470 * char *path file specification path
471 * char relfil[] [.REL] file specification
472 * char *str combined path and file specification
473 * char symname[] [.REL] file symbol string
476 * lbname *lbnhead The pointer to the first
478 * lbfile *lbfhead The pointer to the first
482 * int fclose() c_library
483 * int fgets() c_library
484 * FILE *fopen() c_library
485 * VOID free() c_library
486 * char getnb() lklex.c
487 * VOID lkexit() lkmain.c
488 * VOID loadfile() lklibr.c
489 * VOID * new() lksym.c
490 * char * sprintf() c_library
491 * int sscanf() c_library
492 * char * strcat() c_library
493 * char * strchr() c_library
494 * char * strcpy() c_library
495 * int strlen() c_library
496 * int strncmp() c_library
497 * VOID unget() lklex.c
500 * If the symbol is found then a new lbfile structure
501 * is created and added to the linked list of lbfile
502 * structures. The file containing the found symbol
508 /* First entry in the library object symbol cache */
511 int fndsym( char *name )
513 struct lbfile *lbfh, *lbf;
514 pmlibraryfile ThisLibr;
515 pmlibrarysymbol ThisSym = NULL;
517 /* Build the index if this is the first call to fndsym */
521 /* Iterate through all library object files */
522 ThisLibr = libr.next;
525 /* Iterate through all symbols in an object file */
526 ThisSym = ThisLibr->symbols->next;
529 //printf("ThisSym->name=%s\n", ThisSym->name);
530 if (!strcmp(ThisSym->name, name)) {
531 if (!ThisLibr->loaded) {
532 /* Object file is not loaded - add it to the list */
533 lbfh = (struct lbfile *) new (sizeof(struct lbfile));
534 if (lbfhead == NULL) {
542 lbfh->libspc = ThisLibr->libspc;
543 lbfh->filspc = ThisLibr->str;
544 lbfh->relfil = (char *) new (strlen(ThisLibr->relfil) + 1);
545 strcpy(lbfh->relfil,ThisLibr->relfil);
546 lbfh->offset = ThisLibr->offset;
548 { /*For an embedded object file in a library*/
549 void loadfile_SdccLib(char * libspc, char * module, long offset);
550 loadfile_SdccLib(lbfh->libspc, lbfh->relfil, lbfh->offset);
553 { /*For a stand alone object file*/
554 loadfile(lbfh->filspc);
558 return (1); /* Found the symbol, return */
560 ThisSym=ThisSym->next; /* Next sym in library */
562 ThisLibr=ThisLibr->next; /* Next library in list */
564 return 0; /* Failure - symbol not found in any library */
567 pmlibraryfile buildlibraryindex_SdccLib(char * PathLib, FILE * libfp, char * DirLib, pmlibraryfile This)
569 char ModName[NCPS]="";
570 char FLine[MAXLINE+1];
572 long IndexOffset=0, FileOffset;
573 pmlibrarysymbol ThisSym = NULL;
578 fgets(FLine, MAXLINE, libfp);
584 if(EQ(FLine, "<INDEX>"))
586 /*The next line has the size of the index*/
588 fgets(FLine, MAXLINE, libfp);
590 IndexOffset=atol(FLine);
595 if(EQ(FLine, "<MODULE>"))
597 /*The next line has the name of the module and the offset
598 of the corresponding embedded file in the library*/
600 fgets(FLine, MAXLINE, libfp);
602 sscanf(FLine, "%s %ld", ModName, &FileOffset);
605 /*create a new libraryfile object for this module*/
606 This->next = (pmlibraryfile)new( sizeof( mlibraryfile ));
607 if (This->next == NULL)
609 printf("panic: can't allocate memory.\n");
615 This->loaded=-1; /*Kind of useless, but...*/
616 This->offset=FileOffset+IndexOffset;
617 This->libspc=PathLib;
618 strcpy(This->relfil, ModName);
621 sprintf(This->filename, "%s%s%co", DirLib, ModName, FSEPX);
623 sprintf(This->filename, "%s%s%crel", DirLib, ModName, FSEPX);
626 This->str=This->filename;
628 ThisSym = This->symbols = (pmlibrarysymbol)malloc( sizeof(mlibrarysymbol));
629 ThisSym->next = NULL;
631 else if(EQ(FLine, "</INDEX>"))
633 return This; /*Finish, get out of here*/
637 if(EQ(FLine, "</MODULE>"))
640 /*Create the index for the next module*/
646 ThisSym->next = (pmlibrarysymbol)malloc(sizeof(mlibrarysymbol));
647 ThisSym=ThisSym->next;
650 printf("panic: can't allocate memory.\n");
654 strcpy(ThisSym->name, FLine);
659 return This; /*State machine should never reach this point, but just in case...*/
664 return This; /*State machine should never reach this point, but just in case...*/
668 /* buildlibraryindex - build an in-memory cache of the symbols contained in
671 int buildlibraryindex(void)
675 char relfil[NINPUT+2], *str, *path;
676 char buf[NINPUT+2], c;
677 char symname[NINPUT+2];
679 pmlibrarysymbol ThisSym;
683 /* Iterate through all library files */
684 /*1*/ for (lbnh=lbnhead; lbnh; lbnh=lbnh->next) {
685 libfp = fopen( lbnh->libspc, "r" );
690 * Read in a line from the library file.
691 * This is the relative file specification
692 * for a .REL file in this library.
695 /*2*/ while (fgets(relfil, NINPUT, libfp) != NULL) {
696 relfil[NINPUT+1] = '\0';
699 str = (char *)new(strlen(path)+strlen(relfil)+6);
704 if (str[strlen(str)-1] != '/') {
707 if (str[strlen(str)-1] != '\\') {
711 if (str[strlen(str)-1] != '\\') {
717 str = (char *)new(strlen(relfil) + 5);
720 if(strcmp(relfil, "<SDCCLIB>")==0)
722 /*Get the built in index of a library*/
723 This=buildlibraryindex_SdccLib(lbnh->libspc, libfp, str, This);
726 break; /*get the index for next library*/
729 /*From here down, build the index for the original library
733 if (relfil[0] == '/') {
735 if (relfil[0] == '\\') {
738 if (relfil[0] == '\\') {
740 strcat(str,relfil+1);
744 if(strchr(str,FSEPX) == NULL) {
746 sprintf(&str[strlen(str)], "%co", FSEPX);
748 sprintf(&str[strlen(str)], "%crel", FSEPX);
751 /*3*/ if ((fp = fopen(str, "r")) != NULL) {
753 /* Opened OK - create a new libraryfile object for it */
754 This->next = (pmlibraryfile)new( sizeof( mlibraryfile ));
755 if (This->next == NULL) {
756 printf("panic: can't allocate memory.\n");
763 This->offset=-1; /*There should be a rel file*/
765 strcpy( This->filename, str );
767 ThisSym = This->symbols = (pmlibrarysymbol)malloc( sizeof(mlibrarysymbol));
768 ThisSym->next = NULL;
771 * Read in the object file. Look for lines that
772 * begin with "S" and end with "D". These are
773 * symbol table definitions. If we find one, see
774 * if it is our symbol. Make sure we only read in
775 * our object file and don't go into the next one.
778 /*4*/ while (fgets(buf, NINPUT, fp) != NULL) {
780 buf[NINPUT+1] = '\0';
781 buf[strlen(buf) - 1] = '\0';
784 * Skip everything that's not a symbol record.
790 * When a 'T line' is found terminate file scan.
791 * All 'S line's preceed 'T line's in .REL files.
796 sscanf(buf, "S %s %c", symname, &c);
798 /* If it's an actual symbol, record it */
799 /*5*/ if (c == 'D') {
800 ThisSym->next = (pmlibrarysymbol)malloc(sizeof(mlibrarysymbol));
801 ThisSym=ThisSym->next;
802 if (ThisSym == NULL) {
803 printf("panic: can't allocate memory.\n");
809 strcpy(This->relfil,relfil);
810 strcpy(ThisSym->name, symname);
811 This->libspc = lbnh->libspc;
813 } /* Closes while - read object file */
815 } /* Closes if object file opened OK */
816 } /* Ends while - processing all in libr */
818 } /* Ends good open of libr file */
825 /*Check for a symbol in a SDCC library. If found, add the embedded .rel.
826 The library must be created with the SDCC librarian 'sdcclib' since the
827 linking process depends on the correct file offsets embedded in the library
830 int SdccLib(char * PathLib, FILE * libfp, char * DirLib, char * SymName)
832 struct lbfile *lbfh, *lbf;
833 char ModName[NCPS]="";
834 char FLine[MAXLINE+1];
836 long IndexOffset=0, FileOffset;
841 fgets(FLine, MAXLINE, libfp);
847 if(EQ(FLine, "<INDEX>"))
849 /*The next line has the size of the index*/
851 fgets(FLine, MAXLINE, libfp);
853 IndexOffset=atol(FLine);
858 if(EQ(FLine, "<MODULE>"))
860 /*The next line has the name of the module and the offset
861 of the corresponding embedded file in the library*/
863 fgets(FLine, MAXLINE, libfp);
865 sscanf(FLine, "%s %ld", ModName, &FileOffset);
868 else if(EQ(FLine, "</INDEX>"))
870 /*Reached the end of the index. The symbol is not in this library.*/
875 if(EQ(FLine, "</MODULE>"))
877 /*The symbol is not in this module, try the next one*/
882 /*Check if this is the symbol we are looking for.*/
883 if (strncmp(SymName, FLine, NCPS)==0)
885 /*The symbol is in this module.*/
887 /*As in the original library format, it is assumed that the .rel
888 files reside in the same directory as the lib files.*/
889 strcat(DirLib, ModName);
891 sprintf(&DirLib[strlen(DirLib)], "%co", FSEPX);
893 sprintf(&DirLib[strlen(DirLib)], "%crel", FSEPX);
896 /*If this module has been loaded already don't load it again.*/
900 if(EQ(DirLib, lbf->filspc)) return 1;/*Already loaded*/
904 /*Add the embedded file to the list of files to be loaded in
905 the second pass. That is performed latter by the function
907 lbfh = (struct lbfile *) new (sizeof(struct lbfile));
920 lbfh->libspc = PathLib;
921 lbfh->filspc = DirLib;
922 lbfh->relfil = (char *) new (strlen(ModName) + 1);
923 strcpy(lbfh->relfil, ModName);
924 /*Library embedded file, so lbfh->offset must be >=0*/
925 lbfh->offset = IndexOffset+FileOffset;
927 /*Jump to where the .rel begins and load it.*/
928 fseek(libfp, lbfh->offset, SEEK_SET);
929 LoadRel(libfp, ModName);
931 return 1; /*Found the symbol, so success!*/
937 return 0; /*It should never reach this point, but just in case...*/
942 return 0; /*The symbol is not in this library*/
951 struct lbfile *lbfh, *lbf;
952 char relfil[NINPUT+2];
954 char symname[NINPUT];
960 * Search through every library in the linked list "lbnhead".
963 /*1*/ for (lbnh=lbnhead; lbnh; lbnh=lbnh->next) {
964 if ((libfp = fopen(lbnh->libspc, "r")) == NULL) {
965 fprintf(stderr, "Cannot open library file %s\n",
972 * Read in a line from the library file.
973 * This is the relative file specification
974 * for a .REL file in this library.
977 /*2*/ while (fgets(relfil, NINPUT, libfp) != NULL) {
978 relfil[NINPUT+1] = '\0';
981 str = (char *) new (strlen(path)+strlen(relfil)+6);
986 if (str[strlen(str)-1] != '/') {
989 if (str[strlen(str)-1] != '\\') {
993 if (str[strlen(str)-1] != '\\') {
999 str = (char *) new (strlen(relfil) + 5);
1002 /*See if this is a library with embedded files*/
1003 if(strcmp(relfil, "<SDCCLIB>")==0)
1005 result=SdccLib(lbnh->libspc, libfp, str, name);
1007 if(result) return(1); /*Found the symbol*/
1009 /*The symbol is not in the current library,
1010 check the next library in the list*/
1014 /*From here down is the support for libraries in the original format*/
1017 if (relfil[0] == '/') {
1019 if (relfil[0] == '\\') {
1022 if (relfil[0] == '\\') {
1024 strcat(str,relfil+1);
1028 if(strchr(relfil,FSEPX) == NULL) {
1030 sprintf(&str[strlen(str)], "%co", FSEPX);
1032 sprintf(&str[strlen(str)], "%crel", FSEPX);
1035 /*3*/ if ((fp = fopen(str, "r")) != NULL) {
1038 * Read in the object file. Look for lines that
1039 * begin with "S" and end with "D". These are
1040 * symbol table definitions. If we find one, see
1041 * if it is our symbol. Make sure we only read in
1042 * our object file and don't go into the next one.
1045 /*4*/ while (fgets(buf, NINPUT, fp) != NULL) {
1047 buf[NINPUT+1] = '\0';
1048 buf[strlen(buf) - 1] = '\0';
1051 * Skip everything that's not a symbol record.
1057 * When a 'T line' is found terminate file scan.
1058 * All 'S line's preceed 'T line's in .REL files.
1063 sscanf(buf, "S %s %c", symname, &c);
1066 * If we find a symbol definition for the
1067 * symbol we're looking for, load in the
1068 * file and add it to lbfhead so it gets
1069 * loaded on pass number 2.
1071 /*5*/ if (strncmp(symname, name, NCPS) == 0 && c == 'D') {
1073 lbfh = (struct lbfile *) new (sizeof(struct lbfile));
1074 if (lbfhead == NULL) {
1082 lbfh->libspc = lbnh->libspc;
1084 lbfh->relfil = (char *) new (strlen(relfil) + 1);
1085 lbfh->offset = -1; /*Stand alone rel file*/
1086 strcpy(lbfh->relfil,relfil);
1104 #endif /* INDEXLIB */
1106 void loadfile_SdccLib(char * libspc, char * module, long offset)
1114 if ((fp = fopen(libspc,"r")) != NULL)
1116 fseek(fp, offset, SEEK_SET);
1117 LoadRel(fp, module);
1122 /*)Function VOID library()
1124 * The function library() links all the library object files
1125 * contained in the lbfile structures.
1128 * lbfile *lbfh pointer to lbfile structure
1131 * lbfile *lbfhead pointer to first lbfile structure
1134 * VOID loadfile lklibr.c
1137 * Links all files contained in the lbfile structures.
1143 struct lbfile *lbfh;
1145 for (lbfh=lbfhead; lbfh; lbfh=lbfh->next)
1149 /*Stand alone rel file (original lib format)*/
1150 loadfile(lbfh->filspc);
1154 /*rel file embedded in lib (new lib format)*/
1155 loadfile_SdccLib(lbfh->libspc, lbfh->relfil, lbfh->offset);
1160 /*)Function VOID loadfile(filspc)
1162 * char *filspc library object file specification
1164 * The function loadfile() links the library object module.
1167 * FILE *fp file handle
1168 * int i input line length
1169 * char str[] file input line
1172 * char *ip pointer to linker input string
1175 * int fclose() c_library
1176 * int fgets() c_library
1177 * FILE * fopen() c_library
1178 * VOID link() lkmain.c
1179 * int strlen() c_library
1182 * If file exists it is linked.
1197 if ((fp = fopen(filspc,"r")) != NULL) {
1198 while (fgets(str, NINPUT, fp) != NULL) {
1199 str[NINPUT+1] = '\0';
1200 i = strlen(str) - 1;
1210 printf("Couldn't find file %s\n", filspc);