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.
180 foundcount=addfile(NULL, ip);
184 for (lbph=lbphead; lbph; lbph=lbph->next)
186 foundcount+=addfile(lbph->path, ip);
191 printf("\n?ASlink-Warning-Couldn't find library '%s'", ip);
195 /*)Function int addfile(path,libfil)
197 * char *path library path specification
198 * char *libfil library file specification
200 * The function addfile() searches for the library file
201 * by concatenating the path and libfil specifications.
202 * if the library is found, an lbname structure is created
203 * and linked to any previously defined structures. This
204 * linked list is used by the function fndsym() to attempt
205 * to find any undefined symbols.
207 * The function does not give report an error on invalid
208 * path / file specifications or if the file is not found.
211 * lbname *lbnh pointer to new name structure
212 * lbname *lbn temporary pointer
215 * lbname *lbnhead The pointer to the first
219 * char getnb() lklex.c
220 * VOID * new() lksym.c
221 * int strlen() c_library
222 * char * strcpy() c_library
223 * VOID unget() lklex.c
226 * An lbname structure may be created.
229 * 1: the library was found
230 * 0: the library was not found
233 int addfile(char * path, char * libfil)
237 struct lbname *lbnh, *lbn;
242 str = (char *) new (strlen(path) + strlen(libfil) + 6);
245 if (str[strlen(str)-1] != LKDIRSEP)
247 strcat(str, LKDIRSEPSTR);
252 str = (char *) new (strlen(libfil) + 5);
255 if (libfil[0] == LKDIRSEP)
263 if(strchr(libfil, FSEPX) == NULL)
265 sprintf(&str[strlen(str)], "%clib", FSEPX);
271 /*Ok, that didn't work. Try with the 'libfil' name only*/
272 if(libfilinc) libfil--;
273 fp=fopen(libfil, "r");
276 /*Bingo! 'libfil' is the absolute path of the library*/
278 path=NULL;/*This way 'libfil' and 'path' will be rebuilt from 'str'*/
284 /*'path' can not be null since it is needed to find the '.o' files associated with
285 the library. So, get 'path' from 'str' and then chop it off and recreate 'libfil'.
286 That way putting 'path' and 'libfil' together will result into the original filepath
287 as contained in 'str'.*/
289 path = (char *) new (strlen(str));
291 for(j=strlen(path)-1; j>=0; j--)
293 if((path[j]=='\\')||(path[j]=='/'))
295 strcpy(libfil, &path[j+1]);
306 lbnh = (struct lbname *) new (sizeof(struct lbname));
320 lbnh->libfil = (char *) new (strlen(libfil) + 1);
321 strcpy(lbnh->libfil, libfil);
332 /*)Function VOID search()
334 * The function search() looks through all the symbol tables
335 * at the end of pass 1. If any undefined symbols are found
336 * then the function fndsym() is called. Function fndsym()
337 * searches any specified library files to automagically
338 * import the object modules containing the needed symbol.
340 * After a symbol is found and imported by the function
341 * fndsym() the symbol tables are again searched. The
342 * symbol tables are search until no more symbols can be
343 * resolved within the library files. This ensures that
344 * back references from one library module to another are
348 * int i temporary counter
349 * sym *sp pointer to a symbol structure
350 * int symfnd found a symbol flag
353 * sym *symhash[] array of pointers to symbol tables
356 * int fndsym() lklibr.c
359 * If a symbol is found then the library object module
360 * containing the symbol will be imported and linked.
366 register struct sym *sp;
367 register int i, symfnd;
370 * Look for undefined symbols. Keep
371 * searching until no more symbols are resolved.
377 * Look through all the symbols
379 for (i=0; i<NHASH; ++i) {
382 /* If we find an undefined symbol
383 * (one where S_DEF is not set), then
384 * try looking for it. If we find it
385 * in any of the libraries then
386 * increment symfnd. This will force
387 * another pass of symbol searching and
388 * make sure that back references work.
390 if ((sp->s_type & S_DEF) == 0) {
391 if (fndsym(sp->s_id)) {
401 /*Load a .rel file embedded in a sdcclib file*/
402 void LoadRel(FILE * libfp, char * ModName)
407 while (fgets(str, NINPUT, libfp) != NULL)
409 str[NINPUT+1] = '\0';
414 if(EQ(str, "<FILE>"))
416 fgets(str, NINPUT, libfp);
417 str[NINPUT+1] = '\0';
419 if(EQ(str, ModName)) state=1;
422 printf("Bad offset in library file str=%s, Modname=%s\n", str, ModName);
428 if(EQ(str, "<REL>")) state=2;
431 if(EQ(str, "</REL>")) return;
439 /*)Function VOID fndsym(name)
441 * char *name symbol name to find
443 * The function fndsym() searches through all combinations of the
444 * library path specifications (input by the -k option) and the
445 * library file specifications (input by the -l option) that
446 * lead to an existing file.
448 * The file specicifation may be formed in one of two ways:
450 * (1) If the library file contained an absolute
451 * path/file specification then this becomes filspc.
454 * (2) If the library file contains a relative path/file
455 * specification then the concatenation of the path
456 * and this file specification becomes filspc.
459 * The structure lbfile is created for the first library
460 * object file which contains the definition for the
461 * specified undefined symbol.
463 * If the library file [.LIB] contains file specifications for
464 * non existant files, no errors are returned.
467 * char buf[] [.REL] file input line
468 * char c [.REL] file input character
469 * FILE *fp file handle for object file
470 * lbfile *lbf temporary pointer
471 * lbfile *lbfh pointer to lbfile structure
472 * FILE *libfp file handle for library file
473 * lbname *lbnh pointer to lbname structure
474 * char *path file specification path
475 * char relfil[] [.REL] file specification
476 * char *str combined path and file specification
477 * char symname[] [.REL] file symbol string
480 * lbname *lbnhead The pointer to the first
482 * lbfile *lbfhead The pointer to the first
486 * int fclose() c_library
487 * int fgets() c_library
488 * FILE *fopen() c_library
489 * VOID free() c_library
490 * char getnb() lklex.c
491 * VOID lkexit() lkmain.c
492 * VOID loadfile() lklibr.c
493 * VOID * new() lksym.c
494 * char * sprintf() c_library
495 * int sscanf() c_library
496 * char * strcat() c_library
497 * char * strchr() c_library
498 * char * strcpy() c_library
499 * int strlen() c_library
500 * int strncmp() c_library
501 * VOID unget() lklex.c
504 * If the symbol is found then a new lbfile structure
505 * is created and added to the linked list of lbfile
506 * structures. The file containing the found symbol
512 /* First entry in the library object symbol cache */
515 int fndsym( char *name )
517 struct lbfile *lbfh, *lbf;
518 pmlibraryfile ThisLibr;
519 pmlibrarysymbol ThisSym = NULL;
521 pmlibraryfile FirstFound;
524 /* Build the index if this is the first call to fndsym */
528 /* Iterate through all library object files */
529 ThisLibr = libr.next;
530 FirstFound = libr.next; /*So gcc stops whining*/
533 /* Iterate through all symbols in an object file */
534 ThisSym = ThisLibr->symbols->next;
538 //printf("ThisSym->name=%s\n", ThisSym->name);
539 if (!strcmp(ThisSym->name, name))
541 if ((!ThisLibr->loaded) && (numfound==0))
543 /* Object file is not loaded - add it to the list */
544 lbfh = (struct lbfile *) new (sizeof(struct lbfile));
556 lbfh->libspc = ThisLibr->libspc;
557 lbfh->filspc = ThisLibr->str;
558 lbfh->relfil = (char *) new (strlen(ThisLibr->relfil) + 1);
559 strcpy(lbfh->relfil,ThisLibr->relfil);
560 lbfh->offset = ThisLibr->offset;
562 { /*For an embedded object file in a library*/
563 void loadfile_SdccLib(char * libspc, char * module, long offset);
564 loadfile_SdccLib(lbfh->libspc, lbfh->relfil, lbfh->offset);
567 { /*For a stand alone object file*/
568 loadfile(lbfh->filspc);
580 if( !( EQ(FirstFound->libspc, ThisLibr->libspc) &&
581 EQ(FirstFound->relfil, ThisLibr->relfil) ) )
585 printf("?Aslink-Warning-Definition of public symbol '%s'"
586 " found more than once:\n", name);
587 printf(" Library: '%s', Module: '%s'\n",
588 FirstFound->libspc, FirstFound->relfil);
590 printf(" Library: '%s', Module: '%s'\n",
591 ThisLibr->libspc, ThisLibr->relfil);
596 ThisSym=ThisSym->next; /* Next sym in library */
598 ThisLibr=ThisLibr->next; /* Next library in list */
603 pmlibraryfile buildlibraryindex_SdccLib(char * PathLib, FILE * libfp, char * DirLib, pmlibraryfile This)
605 char ModName[NCPS]="";
606 char FLine[MAXLINE+1];
608 long IndexOffset=0, FileOffset;
609 pmlibrarysymbol ThisSym = NULL;
614 fgets(FLine, MAXLINE, libfp);
620 if(EQ(FLine, "<INDEX>"))
622 /*The next line has the size of the index*/
624 fgets(FLine, MAXLINE, libfp);
626 IndexOffset=atol(FLine);
631 if(EQ(FLine, "<MODULE>"))
633 /*The next line has the name of the module and the offset
634 of the corresponding embedded file in the library*/
636 fgets(FLine, MAXLINE, libfp);
638 sscanf(FLine, "%s %ld", ModName, &FileOffset);
641 /*create a new libraryfile object for this module*/
642 This->next = (pmlibraryfile)new( sizeof( mlibraryfile ));
643 if (This->next == NULL)
645 printf("panic: can't allocate memory.\n");
651 This->loaded=-1; /*Kind of useless, but...*/
652 This->offset=FileOffset+IndexOffset;
653 This->libspc=PathLib;
654 strcpy(This->relfil, ModName);
657 sprintf(This->filename, "%s%s%co", DirLib, ModName, FSEPX);
659 sprintf(This->filename, "%s%s%crel", DirLib, ModName, FSEPX);
662 This->str=This->filename;
664 ThisSym = This->symbols = (pmlibrarysymbol)malloc( sizeof(mlibrarysymbol));
665 ThisSym->next = NULL;
667 else if(EQ(FLine, "</INDEX>"))
669 return This; /*Finish, get out of here*/
673 if(EQ(FLine, "</MODULE>"))
676 /*Create the index for the next module*/
682 ThisSym->next = (pmlibrarysymbol)malloc(sizeof(mlibrarysymbol));
683 ThisSym=ThisSym->next;
686 printf("panic: can't allocate memory.\n");
690 strcpy(ThisSym->name, FLine);
695 return This; /*State machine should never reach this point, but just in case...*/
700 return This; /*State machine should never reach this point, but just in case...*/
704 /* buildlibraryindex - build an in-memory cache of the symbols contained in
707 int buildlibraryindex(void)
711 char relfil[NINPUT+2], *str, *path;
712 char buf[NINPUT+2], c;
713 char symname[NINPUT+2];
715 pmlibrarysymbol ThisSym;
719 /* Iterate through all library files */
720 /*1*/ for (lbnh=lbnhead; lbnh; lbnh=lbnh->next) {
721 libfp = fopen( lbnh->libspc, "r" );
726 * Read in a line from the library file.
727 * This is the relative file specification
728 * for a .REL file in this library.
731 /*2*/ while (fgets(relfil, NINPUT, libfp) != NULL) {
732 relfil[NINPUT+1] = '\0';
735 str = (char *)new(strlen(path)+strlen(relfil)+6);
740 if (str[strlen(str)-1] != '/') {
743 if (str[strlen(str)-1] != '\\') {
747 if (str[strlen(str)-1] != '\\') {
753 str = (char *)new(strlen(relfil) + 5);
756 if(strcmp(relfil, "<SDCCLIB>")==0)
758 /*Get the built in index of a library*/
759 This=buildlibraryindex_SdccLib(lbnh->libspc, libfp, str, This);
762 break; /*get the index for next library*/
765 /*From here down, build the index for the original library
769 if (relfil[0] == '/') {
771 if (relfil[0] == '\\') {
774 if (relfil[0] == '\\') {
776 strcat(str,relfil+1);
780 if(strchr(relfil, FSEPX) == NULL) {
782 sprintf(&str[strlen(str)], "%co", FSEPX);
784 sprintf(&str[strlen(str)], "%crel", FSEPX);
787 /*3*/ if ((fp = fopen(str, "r")) != NULL) {
789 /* Opened OK - create a new libraryfile object for it */
790 This->next = (pmlibraryfile)new( sizeof( mlibraryfile ));
791 if (This->next == NULL) {
792 printf("panic: can't allocate memory.\n");
799 This->offset=-1; /*There should be a rel file*/
801 strcpy( This->filename, str );
803 ThisSym = This->symbols = (pmlibrarysymbol)malloc( sizeof(mlibrarysymbol));
804 ThisSym->next = NULL;
807 * Read in the object file. Look for lines that
808 * begin with "S" and end with "D". These are
809 * symbol table definitions. If we find one, see
810 * if it is our symbol. Make sure we only read in
811 * our object file and don't go into the next one.
814 /*4*/ while (fgets(buf, NINPUT, fp) != NULL) {
816 buf[NINPUT+1] = '\0';
817 buf[strlen(buf) - 1] = '\0';
820 * Skip everything that's not a symbol record.
826 * When a 'T line' is found terminate file scan.
827 * All 'S line's preceed 'T line's in .REL files.
832 sscanf(buf, "S %s %c", symname, &c);
834 /* If it's an actual symbol, record it */
835 /*5*/ if (c == 'D') {
836 ThisSym->next = (pmlibrarysymbol)malloc(sizeof(mlibrarysymbol));
837 ThisSym=ThisSym->next;
838 if (ThisSym == NULL) {
839 printf("panic: can't allocate memory.\n");
845 strcpy(This->relfil,relfil);
846 strcpy(ThisSym->name, symname);
847 This->libspc = lbnh->libspc;
849 } /* Closes while - read object file */
851 } /* Closes if object file opened OK */
852 } /* Ends while - processing all in libr */
854 } /* Ends good open of libr file */
861 /*Check for a symbol in a SDCC library. If found, add the embedded .rel.
862 The library must be created with the SDCC librarian 'sdcclib' since the
863 linking process depends on the correct file offsets embedded in the library
866 int SdccLib(char * PathLib, FILE * libfp, char * DirLib, char * SymName)
868 struct lbfile *lbfh, *lbf;
869 char ModName[NCPS]="";
870 char FLine[MAXLINE+1];
872 long IndexOffset=0, FileOffset;
877 fgets(FLine, MAXLINE, libfp);
883 if(EQ(FLine, "<INDEX>"))
885 /*The next line has the size of the index*/
887 fgets(FLine, MAXLINE, libfp);
889 IndexOffset=atol(FLine);
894 if(EQ(FLine, "<MODULE>"))
896 /*The next line has the name of the module and the offset
897 of the corresponding embedded file in the library*/
899 fgets(FLine, MAXLINE, libfp);
901 sscanf(FLine, "%s %ld", ModName, &FileOffset);
904 else if(EQ(FLine, "</INDEX>"))
906 /*Reached the end of the index. The symbol is not in this library.*/
911 if(EQ(FLine, "</MODULE>"))
913 /*The symbol is not in this module, try the next one*/
918 /*Check if this is the symbol we are looking for.*/
919 if (strncmp(SymName, FLine, NCPS)==0)
921 /*The symbol is in this module.*/
923 /*As in the original library format, it is assumed that the .rel
924 files reside in the same directory as the lib files.*/
925 strcat(DirLib, ModName);
927 sprintf(&DirLib[strlen(DirLib)], "%co", FSEPX);
929 sprintf(&DirLib[strlen(DirLib)], "%crel", FSEPX);
932 /*If this module has been loaded already don't load it again.*/
936 if(EQ(DirLib, lbf->filspc)) return 1;/*Already loaded*/
940 /*Add the embedded file to the list of files to be loaded in
941 the second pass. That is performed latter by the function
943 lbfh = (struct lbfile *) new (sizeof(struct lbfile));
956 lbfh->libspc = PathLib;
957 lbfh->filspc = DirLib;
958 lbfh->relfil = (char *) new (strlen(ModName) + 1);
959 strcpy(lbfh->relfil, ModName);
960 /*Library embedded file, so lbfh->offset must be >=0*/
961 lbfh->offset = IndexOffset+FileOffset;
963 /*Jump to where the .rel begins and load it.*/
964 fseek(libfp, lbfh->offset, SEEK_SET);
965 LoadRel(libfp, ModName);
967 return 1; /*Found the symbol, so success!*/
973 return 0; /*It should never reach this point, but just in case...*/
978 return 0; /*The symbol is not in this library*/
987 struct lbfile *lbfh, *lbf;
988 char relfil[NINPUT+2];
990 char symname[NINPUT];
996 * Search through every library in the linked list "lbnhead".
999 /*1*/ for (lbnh=lbnhead; lbnh; lbnh=lbnh->next) {
1000 if ((libfp = fopen(lbnh->libspc, "r")) == NULL) {
1001 fprintf(stderr, "Cannot open library file %s\n",
1008 * Read in a line from the library file.
1009 * This is the relative file specification
1010 * for a .REL file in this library.
1013 /*2*/ while (fgets(relfil, NINPUT, libfp) != NULL) {
1014 relfil[NINPUT+1] = '\0';
1017 str = (char *) new (strlen(path)+strlen(relfil)+6);
1022 if (str[strlen(str)-1] != '/') {
1025 if (str[strlen(str)-1] != '\\') {
1029 if (str[strlen(str)-1] != '\\') {
1035 str = (char *) new (strlen(relfil) + 5);
1038 /*See if this is a library with embedded files*/
1039 if(strcmp(relfil, "<SDCCLIB>")==0)
1041 result=SdccLib(lbnh->libspc, libfp, str, name);
1043 if(result) return(1); /*Found the symbol*/
1045 /*The symbol is not in the current library,
1046 check the next library in the list*/
1050 /*From here down is the support for libraries in the original format*/
1053 if (relfil[0] == '/') {
1055 if (relfil[0] == '\\') {
1058 if (relfil[0] == '\\') {
1060 strcat(str,relfil+1);
1064 if(strchr(relfil, FSEPX) == NULL) {
1066 sprintf(&str[strlen(str)], "%co", FSEPX);
1068 sprintf(&str[strlen(str)], "%crel", FSEPX);
1071 /*3*/ if ((fp = fopen(str, "r")) != NULL) {
1074 * Read in the object file. Look for lines that
1075 * begin with "S" and end with "D". These are
1076 * symbol table definitions. If we find one, see
1077 * if it is our symbol. Make sure we only read in
1078 * our object file and don't go into the next one.
1081 /*4*/ while (fgets(buf, NINPUT, fp) != NULL) {
1083 buf[NINPUT+1] = '\0';
1084 buf[strlen(buf) - 1] = '\0';
1087 * Skip everything that's not a symbol record.
1093 * When a 'T line' is found terminate file scan.
1094 * All 'S line's preceed 'T line's in .REL files.
1099 sscanf(buf, "S %s %c", symname, &c);
1102 * If we find a symbol definition for the
1103 * symbol we're looking for, load in the
1104 * file and add it to lbfhead so it gets
1105 * loaded on pass number 2.
1107 /*5*/ if (strncmp(symname, name, NCPS) == 0 && c == 'D') {
1109 lbfh = (struct lbfile *) new (sizeof(struct lbfile));
1110 if (lbfhead == NULL) {
1118 lbfh->libspc = lbnh->libspc;
1120 lbfh->relfil = (char *) new (strlen(relfil) + 1);
1121 lbfh->offset = -1; /*Stand alone rel file*/
1122 strcpy(lbfh->relfil,relfil);
1140 #endif /* INDEXLIB */
1142 void loadfile_SdccLib(char * libspc, char * module, long offset)
1150 if ((fp = fopen(libspc,"r")) != NULL)
1152 fseek(fp, offset, SEEK_SET);
1153 LoadRel(fp, module);
1158 /*)Function VOID library()
1160 * The function library() links all the library object files
1161 * contained in the lbfile structures.
1164 * lbfile *lbfh pointer to lbfile structure
1167 * lbfile *lbfhead pointer to first lbfile structure
1170 * VOID loadfile lklibr.c
1173 * Links all files contained in the lbfile structures.
1179 struct lbfile *lbfh;
1181 for (lbfh=lbfhead; lbfh; lbfh=lbfh->next)
1185 /*Stand alone rel file (original lib format)*/
1186 loadfile(lbfh->filspc);
1190 /*rel file embedded in lib (new lib format)*/
1191 loadfile_SdccLib(lbfh->libspc, lbfh->relfil, lbfh->offset);
1196 /*)Function VOID loadfile(filspc)
1198 * char *filspc library object file specification
1200 * The function loadfile() links the library object module.
1203 * FILE *fp file handle
1204 * int i input line length
1205 * char str[] file input line
1208 * char *ip pointer to linker input string
1211 * int fclose() c_library
1212 * int fgets() c_library
1213 * FILE * fopen() c_library
1214 * VOID link() lkmain.c
1215 * int strlen() c_library
1218 * If file exists it is linked.
1233 if ((fp = fopen(filspc,"r")) != NULL) {
1234 while (fgets(str, NINPUT, fp) != NULL) {
1235 str[NINPUT+1] = '\0';
1236 i = strlen(str) - 1;
1246 printf("Couldn't find file %s\n", filspc);