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*/
35 #define LKDIRSEPSTR "/"
38 #define LKDIRSEPSTR "\\"
42 #define LKDIRSEPSTR "\\"
47 void ToCygWin(char * filspc)
49 char posix_path[PATH_MAX];
50 void cygwin_conv_to_full_posix_path(char * win_path, char * posix_path);
51 cygwin_conv_to_full_posix_path(filspc, posix_path);
52 strcpy(filspc, posix_path);
58 * The module lklibr.c contains the functions which
59 * (1) specify the path(s) to library files [.LIB]
60 * (2) specify the library file(s) [.LIB] to search
61 * (3) search the library files for specific symbols
62 * and link the module containing this symbol
64 * lklibr.c contains the following functions:
76 typedef struct slibrarysymbol mlibrarysymbol;
77 typedef struct slibrarysymbol *pmlibrarysymbol;
79 struct slibrarysymbol {
84 typedef struct slibraryfile mlibraryfile;
85 typedef struct slibraryfile *pmlibraryfile;
92 char filename[FILSPC];
93 long offset; //if > 0, the embedded file offset in the library file libspc
94 pmlibrarysymbol symbols;
98 int buildlibraryindex();
101 /*)Function VOID addpath()
103 * The function addpath() creates a linked structure containing
104 * the paths to various object module library files.
107 * lbpath *lbph pointer to new path structure
108 * lbpath *lbp temporary pointer
111 * lbpath *lbphead The pointer to the first
115 * char getnb() lklex.c
116 * VOID * new() lksym.c
117 * int strlen() c_library
118 * char * strcpy() c_library
119 * VOID unget() lklex.c
122 * An lbpath structure may be created.
128 struct lbpath *lbph, *lbp;
130 lbph = (struct lbpath *) new (sizeof(struct lbpath));
131 if (lbphead == NULL) {
140 lbph->path = (char *) new (strlen(ip)+1);
141 strcpy(lbph->path, ip);
144 /*)Function VOID addlib()
146 * The function addlib() tests for the existance of a
147 * library path structure to determine the method of
148 * adding this library file to the library search structure.
150 * This function calls the function addfile() to actually
151 * add the library file to the search list.
154 * lbpath *lbph pointer to path structure
157 * lbpath *lbphead The pointer to the first
159 * ip a pointer to the library name
162 * VOID addfile() lklibr.c
163 * char getnb() lklex.c
164 * VOID unget() lklex.c
167 * The function addfile() may add the file to
168 * the library search list.
181 foundcount=addfile(NULL, ip);
185 for (lbph=lbphead; lbph; lbph=lbph->next)
187 foundcount+=addfile(lbph->path, ip);
192 printf("\n?ASlink-Warning-Couldn't find library '%s'", ip);
196 /*)Function int addfile(path,libfil)
198 * char *path library path specification
199 * char *libfil library file specification
201 * The function addfile() searches for the library file
202 * by concatenating the path and libfil specifications.
203 * if the library is found, an lbname structure is created
204 * and linked to any previously defined structures. This
205 * linked list is used by the function fndsym() to attempt
206 * to find any undefined symbols.
208 * The function does not give report an error on invalid
209 * path / file specifications or if the file is not found.
212 * lbname *lbnh pointer to new name structure
213 * lbname *lbn temporary pointer
216 * lbname *lbnhead The pointer to the first
220 * char getnb() lklex.c
221 * VOID * new() lksym.c
222 * int strlen() c_library
223 * char * strcpy() c_library
224 * VOID unget() lklex.c
227 * An lbname structure may be created.
230 * 1: the library was found
231 * 0: the library was not found
234 int addfile(char * path, char * libfil)
238 struct lbname *lbnh, *lbn;
243 str = (char *) new (strlen(path) + strlen(libfil) + 6);
246 if (str[strlen(str)-1] != LKDIRSEP)
248 strcat(str, LKDIRSEPSTR);
253 str = (char *) new (strlen(libfil) + 5);
256 if (libfil[0] == LKDIRSEP)
264 if(strchr(libfil, FSEPX) == NULL)
266 sprintf(&str[strlen(str)], "%clib", FSEPX);
272 /*Ok, that didn't work. Try with the 'libfil' name only*/
273 if(libfilinc) libfil--;
274 fp=fopen(libfil, "r");
277 /*Bingo! 'libfil' is the absolute path of the library*/
279 path=NULL;/*This way 'libfil' and 'path' will be rebuilt from 'str'*/
285 /*'path' can not be null since it is needed to find the '.o' files associated with
286 the library. So, get 'path' from 'str' and then chop it off and recreate 'libfil'.
287 That way putting 'path' and 'libfil' together will result into the original filepath
288 as contained in 'str'.*/
290 path = (char *) new (strlen(str));
292 for(j=strlen(path)-1; j>=0; j--)
294 if((path[j]=='\\')||(path[j]=='/'))
296 strcpy(libfil, &path[j+1]);
307 lbnh = (struct lbname *) new (sizeof(struct lbname));
321 lbnh->libfil = (char *) new (strlen(libfil) + 1);
322 strcpy(lbnh->libfil, libfil);
333 /*)Function VOID search()
335 * The function search() looks through all the symbol tables
336 * at the end of pass 1. If any undefined symbols are found
337 * then the function fndsym() is called. Function fndsym()
338 * searches any specified library files to automagically
339 * import the object modules containing the needed symbol.
341 * After a symbol is found and imported by the function
342 * fndsym() the symbol tables are again searched. The
343 * symbol tables are search until no more symbols can be
344 * resolved within the library files. This ensures that
345 * back references from one library module to another are
349 * int i temporary counter
350 * sym *sp pointer to a symbol structure
351 * int symfnd found a symbol flag
354 * sym *symhash[] array of pointers to symbol tables
357 * int fndsym() lklibr.c
360 * If a symbol is found then the library object module
361 * containing the symbol will be imported and linked.
367 register struct sym *sp;
368 register int i, symfnd;
371 * Look for undefined symbols. Keep
372 * searching until no more symbols are resolved.
378 * Look through all the symbols
380 for (i=0; i<NHASH; ++i) {
383 /* If we find an undefined symbol
384 * (one where S_DEF is not set), then
385 * try looking for it. If we find it
386 * in any of the libraries then
387 * increment symfnd. This will force
388 * another pass of symbol searching and
389 * make sure that back references work.
391 if ((sp->s_type & S_DEF) == 0) {
392 if (fndsym(sp->s_id)) {
402 /*Load a .rel file embedded in a sdcclib file*/
403 void LoadRel(FILE * libfp, char * ModName)
408 while (fgets(str, NINPUT, libfp) != NULL)
410 str[NINPUT+1] = '\0';
415 if(EQ(str, "<FILE>"))
417 fgets(str, NINPUT, libfp);
418 str[NINPUT+1] = '\0';
420 if(EQ(str, ModName)) state=1;
423 printf("Bad offset in library file str=%s, Modname=%s\n", str, ModName);
429 if(EQ(str, "<REL>")) state=2;
432 if(EQ(str, "</REL>")) return;
440 /*)Function VOID fndsym(name)
442 * char *name symbol name to find
444 * The function fndsym() searches through all combinations of the
445 * library path specifications (input by the -k option) and the
446 * library file specifications (input by the -l option) that
447 * lead to an existing file.
449 * The file specicifation may be formed in one of two ways:
451 * (1) If the library file contained an absolute
452 * path/file specification then this becomes filspc.
455 * (2) If the library file contains a relative path/file
456 * specification then the concatenation of the path
457 * and this file specification becomes filspc.
460 * The structure lbfile is created for the first library
461 * object file which contains the definition for the
462 * specified undefined symbol.
464 * If the library file [.LIB] contains file specifications for
465 * non existant files, no errors are returned.
468 * char buf[] [.REL] file input line
469 * char c [.REL] file input character
470 * FILE *fp file handle for object file
471 * lbfile *lbf temporary pointer
472 * lbfile *lbfh pointer to lbfile structure
473 * FILE *libfp file handle for library file
474 * lbname *lbnh pointer to lbname structure
475 * char *path file specification path
476 * char relfil[] [.REL] file specification
477 * char *str combined path and file specification
478 * char symname[] [.REL] file symbol string
481 * lbname *lbnhead The pointer to the first
483 * lbfile *lbfhead The pointer to the first
487 * int fclose() c_library
488 * int fgets() c_library
489 * FILE *fopen() c_library
490 * VOID free() c_library
491 * char getnb() lklex.c
492 * VOID lkexit() lkmain.c
493 * VOID loadfile() lklibr.c
494 * VOID * new() lksym.c
495 * char * sprintf() c_library
496 * int sscanf() c_library
497 * char * strcat() c_library
498 * char * strchr() c_library
499 * char * strcpy() c_library
500 * int strlen() c_library
501 * int strncmp() c_library
502 * VOID unget() lklex.c
505 * If the symbol is found then a new lbfile structure
506 * is created and added to the linked list of lbfile
507 * structures. The file containing the found symbol
513 /* First entry in the library object symbol cache */
516 int fndsym( char *name )
518 struct lbfile *lbfh, *lbf;
519 pmlibraryfile ThisLibr;
520 pmlibrarysymbol ThisSym = NULL;
522 pmlibraryfile FirstFound;
525 /* Build the index if this is the first call to fndsym */
529 /* Iterate through all library object files */
530 ThisLibr = libr.next;
531 FirstFound = libr.next; /*So gcc stops whining*/
534 /* Iterate through all symbols in an object file */
535 ThisSym = ThisLibr->symbols->next;
539 //printf("ThisSym->name=%s\n", ThisSym->name);
540 if (!strcmp(ThisSym->name, name))
542 if ((!ThisLibr->loaded) && (numfound==0))
544 /* Object file is not loaded - add it to the list */
545 lbfh = (struct lbfile *) new (sizeof(struct lbfile));
557 lbfh->libspc = ThisLibr->libspc;
558 lbfh->filspc = ThisLibr->str;
559 lbfh->relfil = (char *) new (strlen(ThisLibr->relfil) + 1);
560 strcpy(lbfh->relfil,ThisLibr->relfil);
561 lbfh->offset = ThisLibr->offset;
563 { /*For an embedded object file in a library*/
564 void loadfile_SdccLib(char * libspc, char * module, long offset);
565 loadfile_SdccLib(lbfh->libspc, lbfh->relfil, lbfh->offset);
568 { /*For a stand alone object file*/
569 loadfile(lbfh->filspc);
581 char absPath1[PATH_MAX];
582 char absPath2[PATH_MAX];
583 #if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
586 _fullpath(absPath1, FirstFound->libspc, PATH_MAX);
587 _fullpath(absPath2, ThisLibr->libspc, PATH_MAX);
588 for(j=0; absPath1[j]!=0; j++) absPath1[j]=tolower(absPath1[j]);
589 for(j=0; absPath2[j]!=0; j++) absPath2[j]=tolower(absPath2[j]);
591 realpath(FirstFound->libspc, absPath1);
592 realpath(ThisLibr->libspc, absPath2);
594 if( !( EQ(absPath1, absPath2) && EQ(FirstFound->relfil, ThisLibr->relfil) ) )
598 printf("?Aslink-Warning-Definition of public symbol '%s'"
599 " found more than once:\n", name);
600 printf(" Library: '%s', Module: '%s'\n",
601 FirstFound->libspc, FirstFound->relfil);
603 printf(" Library: '%s', Module: '%s'\n",
604 ThisLibr->libspc, ThisLibr->relfil);
609 ThisSym=ThisSym->next; /* Next sym in library */
611 ThisLibr=ThisLibr->next; /* Next library in list */
616 pmlibraryfile buildlibraryindex_SdccLib(char * PathLib, FILE * libfp, char * DirLib, pmlibraryfile This)
618 char ModName[NCPS]="";
619 char FLine[MAXLINE+1];
621 long IndexOffset=0, FileOffset;
622 pmlibrarysymbol ThisSym = NULL;
627 fgets(FLine, MAXLINE, libfp);
633 if(EQ(FLine, "<INDEX>"))
635 /*The next line has the size of the index*/
637 fgets(FLine, MAXLINE, libfp);
639 IndexOffset=atol(FLine);
644 if(EQ(FLine, "<MODULE>"))
646 /*The next line has the name of the module and the offset
647 of the corresponding embedded file in the library*/
649 fgets(FLine, MAXLINE, libfp);
651 sscanf(FLine, "%s %ld", ModName, &FileOffset);
654 /*create a new libraryfile object for this module*/
655 This->next = (pmlibraryfile)new( sizeof( mlibraryfile ));
656 if (This->next == NULL)
658 printf("panic: can't allocate memory.\n");
664 This->loaded=-1; /*Kind of useless, but...*/
665 This->offset=FileOffset+IndexOffset;
666 This->libspc=PathLib;
667 strcpy(This->relfil, ModName);
670 sprintf(This->filename, "%s%s%co", DirLib, ModName, FSEPX);
672 sprintf(This->filename, "%s%s%crel", DirLib, ModName, FSEPX);
675 This->str=This->filename;
677 ThisSym = This->symbols = (pmlibrarysymbol)malloc( sizeof(mlibrarysymbol));
678 ThisSym->next = NULL;
680 else if(EQ(FLine, "</INDEX>"))
682 return This; /*Finish, get out of here*/
686 if(EQ(FLine, "</MODULE>"))
689 /*Create the index for the next module*/
695 ThisSym->next = (pmlibrarysymbol)malloc(sizeof(mlibrarysymbol));
696 ThisSym=ThisSym->next;
699 printf("panic: can't allocate memory.\n");
703 strcpy(ThisSym->name, FLine);
708 return This; /*State machine should never reach this point, but just in case...*/
713 return This; /*State machine should never reach this point, but just in case...*/
717 /* buildlibraryindex - build an in-memory cache of the symbols contained in
720 int buildlibraryindex(void)
724 char relfil[NINPUT+2], *str, *path;
725 char buf[NINPUT+2], c;
726 char symname[NINPUT+2];
728 pmlibrarysymbol ThisSym;
732 /* Iterate through all library files */
733 /*1*/ for (lbnh=lbnhead; lbnh; lbnh=lbnh->next) {
734 libfp = fopen( lbnh->libspc, "r" );
739 * Read in a line from the library file.
740 * This is the relative file specification
741 * for a .REL file in this library.
744 /*2*/ while (fgets(relfil, NINPUT, libfp) != NULL) {
745 relfil[NINPUT+1] = '\0';
748 str = (char *)new(strlen(path)+strlen(relfil)+6);
753 if (str[strlen(str)-1] != '/') {
756 if (str[strlen(str)-1] != '\\') {
760 if (str[strlen(str)-1] != '\\') {
766 str = (char *)new(strlen(relfil) + 5);
769 if(strcmp(relfil, "<SDCCLIB>")==0)
771 /*Get the built in index of a library*/
772 This=buildlibraryindex_SdccLib(lbnh->libspc, libfp, str, This);
775 break; /*get the index for next library*/
778 /*From here down, build the index for the original library
782 if (relfil[0] == '/') {
784 if (relfil[0] == '\\') {
787 if (relfil[0] == '\\') {
789 strcat(str,relfil+1);
793 if(strchr(relfil, FSEPX) == NULL) {
795 sprintf(&str[strlen(str)], "%co", FSEPX);
797 sprintf(&str[strlen(str)], "%crel", FSEPX);
800 /*3*/ if ((fp = fopen(str, "r")) != NULL) {
802 /* Opened OK - create a new libraryfile object for it */
803 This->next = (pmlibraryfile)new( sizeof( mlibraryfile ));
804 if (This->next == NULL) {
805 printf("panic: can't allocate memory.\n");
812 This->offset=-1; /*There should be a rel file*/
814 strcpy( This->filename, str );
816 ThisSym = This->symbols = (pmlibrarysymbol)malloc( sizeof(mlibrarysymbol));
817 ThisSym->next = NULL;
820 * Read in the object file. Look for lines that
821 * begin with "S" and end with "D". These are
822 * symbol table definitions. If we find one, see
823 * if it is our symbol. Make sure we only read in
824 * our object file and don't go into the next one.
827 /*4*/ while (fgets(buf, NINPUT, fp) != NULL) {
829 buf[NINPUT+1] = '\0';
830 buf[strlen(buf) - 1] = '\0';
833 * Skip everything that's not a symbol record.
839 * When a 'T line' is found terminate file scan.
840 * All 'S line's preceed 'T line's in .REL files.
845 sscanf(buf, "S %s %c", symname, &c);
847 /* If it's an actual symbol, record it */
848 /*5*/ if (c == 'D') {
849 ThisSym->next = (pmlibrarysymbol)malloc(sizeof(mlibrarysymbol));
850 ThisSym=ThisSym->next;
851 if (ThisSym == NULL) {
852 printf("panic: can't allocate memory.\n");
858 strcpy(This->relfil,relfil);
859 strcpy(ThisSym->name, symname);
860 This->libspc = lbnh->libspc;
862 } /* Closes while - read object file */
864 } /* Closes if object file opened OK */
865 } /* Ends while - processing all in libr */
867 } /* Ends good open of libr file */
874 /*Check for a symbol in a SDCC library. If found, add the embedded .rel.
875 The library must be created with the SDCC librarian 'sdcclib' since the
876 linking process depends on the correct file offsets embedded in the library
879 int SdccLib(char * PathLib, FILE * libfp, char * DirLib, char * SymName)
881 struct lbfile *lbfh, *lbf;
882 char ModName[NCPS]="";
883 char FLine[MAXLINE+1];
885 long IndexOffset=0, FileOffset;
890 fgets(FLine, MAXLINE, libfp);
896 if(EQ(FLine, "<INDEX>"))
898 /*The next line has the size of the index*/
900 fgets(FLine, MAXLINE, libfp);
902 IndexOffset=atol(FLine);
907 if(EQ(FLine, "<MODULE>"))
909 /*The next line has the name of the module and the offset
910 of the corresponding embedded file in the library*/
912 fgets(FLine, MAXLINE, libfp);
914 sscanf(FLine, "%s %ld", ModName, &FileOffset);
917 else if(EQ(FLine, "</INDEX>"))
919 /*Reached the end of the index. The symbol is not in this library.*/
924 if(EQ(FLine, "</MODULE>"))
926 /*The symbol is not in this module, try the next one*/
931 /*Check if this is the symbol we are looking for.*/
932 if (strncmp(SymName, FLine, NCPS)==0)
934 /*The symbol is in this module.*/
936 /*As in the original library format, it is assumed that the .rel
937 files reside in the same directory as the lib files.*/
938 strcat(DirLib, ModName);
940 sprintf(&DirLib[strlen(DirLib)], "%co", FSEPX);
942 sprintf(&DirLib[strlen(DirLib)], "%crel", FSEPX);
945 /*If this module has been loaded already don't load it again.*/
949 if(EQ(DirLib, lbf->filspc)) return 1;/*Already loaded*/
953 /*Add the embedded file to the list of files to be loaded in
954 the second pass. That is performed latter by the function
956 lbfh = (struct lbfile *) new (sizeof(struct lbfile));
969 lbfh->libspc = PathLib;
970 lbfh->filspc = DirLib;
971 lbfh->relfil = (char *) new (strlen(ModName) + 1);
972 strcpy(lbfh->relfil, ModName);
973 /*Library embedded file, so lbfh->offset must be >=0*/
974 lbfh->offset = IndexOffset+FileOffset;
976 /*Jump to where the .rel begins and load it.*/
977 fseek(libfp, lbfh->offset, SEEK_SET);
978 LoadRel(libfp, ModName);
980 return 1; /*Found the symbol, so success!*/
986 return 0; /*It should never reach this point, but just in case...*/
991 return 0; /*The symbol is not in this library*/
1000 struct lbfile *lbfh, *lbf;
1001 char relfil[NINPUT+2];
1003 char symname[NINPUT];
1009 * Search through every library in the linked list "lbnhead".
1012 /*1*/ for (lbnh=lbnhead; lbnh; lbnh=lbnh->next) {
1013 if ((libfp = fopen(lbnh->libspc, "r")) == NULL) {
1014 fprintf(stderr, "Cannot open library file %s\n",
1021 * Read in a line from the library file.
1022 * This is the relative file specification
1023 * for a .REL file in this library.
1026 /*2*/ while (fgets(relfil, NINPUT, libfp) != NULL) {
1027 relfil[NINPUT+1] = '\0';
1030 str = (char *) new (strlen(path)+strlen(relfil)+6);
1035 if (str[strlen(str)-1] != '/') {
1038 if (str[strlen(str)-1] != '\\') {
1042 if (str[strlen(str)-1] != '\\') {
1048 str = (char *) new (strlen(relfil) + 5);
1051 /*See if this is a library with embedded files*/
1052 if(strcmp(relfil, "<SDCCLIB>")==0)
1054 result=SdccLib(lbnh->libspc, libfp, str, name);
1056 if(result) return(1); /*Found the symbol*/
1058 /*The symbol is not in the current library,
1059 check the next library in the list*/
1063 /*From here down is the support for libraries in the original format*/
1066 if (relfil[0] == '/') {
1068 if (relfil[0] == '\\') {
1071 if (relfil[0] == '\\') {
1073 strcat(str,relfil+1);
1077 if(strchr(relfil, FSEPX) == NULL) {
1079 sprintf(&str[strlen(str)], "%co", FSEPX);
1081 sprintf(&str[strlen(str)], "%crel", FSEPX);
1084 /*3*/ if ((fp = fopen(str, "r")) != NULL) {
1087 * Read in the object file. Look for lines that
1088 * begin with "S" and end with "D". These are
1089 * symbol table definitions. If we find one, see
1090 * if it is our symbol. Make sure we only read in
1091 * our object file and don't go into the next one.
1094 /*4*/ while (fgets(buf, NINPUT, fp) != NULL) {
1096 buf[NINPUT+1] = '\0';
1097 buf[strlen(buf) - 1] = '\0';
1100 * Skip everything that's not a symbol record.
1106 * When a 'T line' is found terminate file scan.
1107 * All 'S line's preceed 'T line's in .REL files.
1112 sscanf(buf, "S %s %c", symname, &c);
1115 * If we find a symbol definition for the
1116 * symbol we're looking for, load in the
1117 * file and add it to lbfhead so it gets
1118 * loaded on pass number 2.
1120 /*5*/ if (strncmp(symname, name, NCPS) == 0 && c == 'D') {
1122 lbfh = (struct lbfile *) new (sizeof(struct lbfile));
1123 if (lbfhead == NULL) {
1131 lbfh->libspc = lbnh->libspc;
1133 lbfh->relfil = (char *) new (strlen(relfil) + 1);
1134 lbfh->offset = -1; /*Stand alone rel file*/
1135 strcpy(lbfh->relfil,relfil);
1153 #endif /* INDEXLIB */
1155 void loadfile_SdccLib(char * libspc, char * module, long offset)
1163 if ((fp = fopen(libspc,"r")) != NULL)
1165 fseek(fp, offset, SEEK_SET);
1166 LoadRel(fp, module);
1171 /*)Function VOID library()
1173 * The function library() links all the library object files
1174 * contained in the lbfile structures.
1177 * lbfile *lbfh pointer to lbfile structure
1180 * lbfile *lbfhead pointer to first lbfile structure
1183 * VOID loadfile lklibr.c
1186 * Links all files contained in the lbfile structures.
1192 struct lbfile *lbfh;
1194 for (lbfh=lbfhead; lbfh; lbfh=lbfh->next)
1198 /*Stand alone rel file (original lib format)*/
1199 loadfile(lbfh->filspc);
1203 /*rel file embedded in lib (new lib format)*/
1204 loadfile_SdccLib(lbfh->libspc, lbfh->relfil, lbfh->offset);
1209 /*)Function VOID loadfile(filspc)
1211 * char *filspc library object file specification
1213 * The function loadfile() links the library object module.
1216 * FILE *fp file handle
1217 * int i input line length
1218 * char str[] file input line
1221 * char *ip pointer to linker input string
1224 * int fclose() c_library
1225 * int fgets() c_library
1226 * FILE * fopen() c_library
1227 * VOID link() lkmain.c
1228 * int strlen() c_library
1231 * If file exists it is linked.
1246 if ((fp = fopen(filspc,"r")) != NULL) {
1247 while (fgets(str, NINPUT, fp) != NULL) {
1248 str[NINPUT+1] = '\0';
1249 i = strlen(str) - 1;
1259 printf("Couldn't find file %s\n", filspc);