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*/
21 #if defined(__APPLE__) && defined(__MACH__)
22 #include <sys/types.h>
23 #include <sys/malloc.h>
35 * The module lklibr.c contains the functions which
36 * (1) specify the path(s) to library files [.LIB]
37 * (2) specify the library file(s) [.LIB] to search
38 * (3) search the library files for specific symbols
39 * and link the module containing this symbol
41 * lklibr.c contains the following functions:
53 typedef struct slibrarysymbol mlibrarysymbol;
54 typedef struct slibrarysymbol *pmlibrarysymbol;
56 struct slibrarysymbol {
61 typedef struct slibraryfile mlibraryfile;
62 typedef struct slibraryfile *pmlibraryfile;
68 char relfil[PATH_MAX];
69 char filename[PATH_MAX];
70 long offset; //if > 0, the embedded file offset in the library file libspc
71 pmlibrarysymbol symbols;
75 int buildlibraryindex();
78 /*)Function VOID addpath()
80 * The function addpath() creates a linked structure containing
81 * the paths to various object module library files.
84 * lbpath *lbph pointer to new path structure
85 * lbpath *lbp temporary pointer
88 * lbpath *lbphead The pointer to the first
92 * char getnb() lklex.c
93 * VOID * new() lksym.c
94 * int strlen() c_library
95 * char * strcpy() c_library
96 * VOID unget() lklex.c
99 * An lbpath structure may be created.
105 struct lbpath *lbph, *lbp;
107 lbph = (struct lbpath *) new (sizeof(struct lbpath));
108 if (lbphead == NULL) {
117 lbph->path = (char *) new (strlen(ip)+1);
118 strcpy(lbph->path, ip);
121 /*)Function VOID addlib()
123 * The function addlib() tests for the existance of a
124 * library path structure to determine the method of
125 * adding this library file to the library search structure.
127 * This function calls the function addfile() to actually
128 * add the library file to the search list.
131 * lbpath *lbph pointer to path structure
134 * lbpath *lbphead The pointer to the first
136 * ip a pointer to the library name
139 * VOID addfile() lklibr.c
140 * char getnb() lklex.c
141 * VOID unget() lklex.c
144 * The function addfile() may add the file to
145 * the library search list.
158 foundcount=addfile(NULL, ip);
162 for (lbph=lbphead; lbph; lbph=lbph->next)
164 foundcount+=addfile(lbph->path, ip);
169 printf("?ASlink-Warning-Couldn't find library '%s'\n", ip);
173 /*)Function int addfile(path,libfil)
175 * char *path library path specification
176 * char *libfil library file specification
178 * The function addfile() searches for the library file
179 * by concatenating the path and libfil specifications.
180 * if the library is found, an lbname structure is created
181 * and linked to any previously defined structures. This
182 * linked list is used by the function fndsym() to attempt
183 * to find any undefined symbols.
185 * The function does not give report an error on invalid
186 * path / file specifications or if the file is not found.
189 * lbname *lbnh pointer to new name structure
190 * lbname *lbn temporary pointer
193 * lbname *lbnhead The pointer to the first
197 * char getnb() lklex.c
198 * VOID * new() lksym.c
199 * int strlen() c_library
200 * char * strcpy() c_library
201 * VOID unget() lklex.c
204 * An lbname structure may be created.
207 * 1: the library was found
208 * 0: the library was not found
211 int addfile(char * path, char * libfil)
215 struct lbname *lbnh, *lbn;
222 str = (char *) new (strlen(path) + strlen(libfil) + 6);
225 if (str[strlen(str)-1] != '/')
233 str = (char *) new (strlen(libfil) + 5);
237 if (libfil[0] == '/')
245 if(strchr(libfil, FSEPX) == NULL)
247 sprintf(&str[strlen(str)], "%clib", FSEPX);
253 /*Ok, that didn't work. Try with the 'libfil' name only*/
255 if(libfilinc) libfil--;
257 fp=fopen(libfil, "r");
260 /*Bingo! 'libfil' is the absolute path of the library*/
262 path=NULL;/*This way 'libfil' and 'path' will be rebuilt from 'str'*/
268 /*'path' can not be null since it is needed to find the '.rel' files associated with
269 the library. So, get 'path' from 'str' and then chop it off and recreate 'libfil'.
270 That way putting 'path' and 'libfil' together will result into the original filepath
271 as contained in 'str'.*/
273 path = (char *) new (strlen(str));
275 for(j=strlen(path)-1; j>=0; j--)
277 if((path[j]=='\\')||(path[j]=='/'))
279 strcpy(libfil, &path[j+1]);
290 lbnh = (struct lbname *) new (sizeof(struct lbname));
304 lbnh->libfil = (char *) new (strlen(libfil) + 1);
305 strcpy(lbnh->libfil,libfil);
316 /*)Function VOID search()
318 * The function search() looks through all the symbol tables
319 * at the end of pass 1. If any undefined symbols are found
320 * then the function fndsym() is called. Function fndsym()
321 * searches any specified library files to automagically
322 * import the object modules containing the needed symbol.
324 * After a symbol is found and imported by the function
325 * fndsym() the symbol tables are again searched. The
326 * symbol tables are search until no more symbols can be
327 * resolved within the library files. This ensures that
328 * back references from one library module to another are
332 * int i temporary counter
333 * sym *sp pointer to a symbol structure
334 * int symfnd found a symbol flag
337 * sym *symhash[] array of pointers to symbol tables
340 * int fndsym() lklibr.c
343 * If a symbol is found then the library object module
344 * containing the symbol will be imported and linked.
350 register struct sym *sp;
351 register int i,symfnd;
354 * Look for undefined symbols. Keep
355 * searching until no more symbols are resolved.
361 * Look through all the symbols
363 for (i=0; i<NHASH; ++i) {
366 /* If we find an undefined symbol
367 * (one where S_DEF is not set), then
368 * try looking for it. If we find it
369 * in any of the libraries then
370 * increment symfnd. This will force
371 * another pass of symbol searching and
372 * make sure that back references work.
374 if ((sp->s_type & S_DEF) == 0) {
375 if (fndsym(sp->s_id)) {
385 /*Load a .rel file embedded in a sdcclib file*/
386 void LoadRel(FILE * libfp, char * ModName)
391 while (fgets(str, NINPUT, libfp) != NULL)
393 str[NINPUT+1] = '\0';
398 if(EQ(str, "<FILE>"))
400 fgets(str, NINPUT, libfp);
401 str[NINPUT+1] = '\0';
403 if(EQ(str, ModName)) state=1;
406 printf("Bad offset in library file str=%s, Modname=%s\n", str, ModName);
412 if(EQ(str, "<REL>")) state=2;
415 if(EQ(str, "</REL>")) return;
423 /*Load an .adb file embedded in a sdcclib file. If there is
424 something between <ADB> and </ADB> returns 1, otherwise returns 0.
425 This way the aomf51 will not have uselless empty modules. */
427 int LoadAdb(FILE * libfp)
433 while (fgets(str, MAXLINE, libfp) != NULL)
435 str[NINPUT+1] = '\0';
440 if(EQ(str, "<ADB>")) state=1;
443 if(EQ(str, "</ADB>")) return ToReturn;
444 fprintf(dfp, "%s\n", str);
452 /*Check for a symbol in a SDCC library. If found, add the embedded .rel and
453 .adb files from the library. The library must be created with the SDCC
454 librarian 'sdcclib' since the linking process depends on the correct file offsets
455 embedded in the library file.*/
457 int SdccLib(char * PathLib, FILE * libfp, char * DirLib, char * SymName)
459 struct lbfile *lbfh, *lbf;
460 char ModName[NCPS]="";
461 char FLine[MAXLINE+1];
463 long IndexOffset=0, FileOffset;
468 fgets(FLine, MAXLINE, libfp);
474 if(EQ(FLine, "<INDEX>"))
476 /*The next line has the size of the index*/
478 fgets(FLine, MAXLINE, libfp);
480 IndexOffset=atol(FLine);
485 if(EQ(FLine, "<MODULE>"))
487 /*The next line has the name of the module and the offset
488 of the corresponding embedded file in the library*/
490 fgets(FLine, MAXLINE, libfp);
492 sscanf(FLine, "%s %ld", ModName, &FileOffset);
495 else if(EQ(FLine, "</INDEX>"))
497 /*Reached the end of the index. The symbol is not in this library.*/
502 if(EQ(FLine, "</MODULE>"))
504 /*The symbol is not in this module, try the next one*/
509 /*Check if this is the symbol we are looking for.*/
510 if (strncmp(SymName, FLine, NCPS)==0)
512 /*The symbol is in this module.*/
514 /*As in the original library format, it is assumed that the .rel
515 files reside in the same directory as the lib files.*/
516 strcat(DirLib, ModName);
517 sprintf(&DirLib[strlen(DirLib)], "%crel", FSEPX);
519 /*If this module has been loaded already don't load it again.*/
523 if(EQ(DirLib, lbf->filspc)) return 1;/*Already loaded*/
527 /*Add the embedded file to the list of files to be loaded in
528 the second pass. That is performed latter by the function
530 lbfh = (struct lbfile *) new (sizeof(struct lbfile));
543 lbfh->libspc = PathLib;
544 lbfh->filspc = DirLib;
545 lbfh->relfil = (char *) new (strlen(ModName) + 1);
546 strcpy(lbfh->relfil, ModName);
547 /*Library embedded file, so lbfh->offset must be >=0*/
548 lbfh->offset = IndexOffset+FileOffset;
550 /*Jump to where the .rel begins and load it.*/
551 fseek(libfp, lbfh->offset, SEEK_SET);
552 LoadRel(libfp, ModName);
554 /* if cdb information required & .adb file present */
558 SaveLinkedFilePath(DirLib);
560 return 1; /*Found the symbol, so success!*/
566 return 0; /*It should never reach this point, but just in case...*/
571 return 0; /*The symbol is not in this library*/
574 /*)Function VOID fndsym(name)
576 * char *name symbol name to find
578 * The function fndsym() searches through all combinations of the
579 * library path specifications (input by the -k option) and the
580 * library file specifications (input by the -l option) that
581 * lead to an existing file.
583 * The file specicifation may be formed in one of two ways:
585 * (1) If the library file contained an absolute
586 * path/file specification then this becomes filspc.
589 * (2) If the library file contains a relative path/file
590 * specification then the concatenation of the path
591 * and this file specification becomes filspc.
594 * The structure lbfile is created for the first library
595 * object file which contains the definition for the
596 * specified undefined symbol.
598 * If the library file [.LIB] contains file specifications for
599 * non existant files, no errors are returned.
602 * char buf[] [.REL] file input line
603 * char c [.REL] file input character
604 * FILE *fp file handle for object file
605 * lbfile *lbf temporary pointer
606 * lbfile *lbfh pointer to lbfile structure
607 * FILE *libfp file handle for library file
608 * lbname *lbnh pointer to lbname structure
609 * char *path file specification path
610 * char relfil[] [.REL] file specification
611 * char *str combined path and file specification
612 * char symname[] [.REL] file symbol string
615 * lbname *lbnhead The pointer to the first
617 * lbfile *lbfhead The pointer to the first
621 * int fclose() c_library
622 * int fgets() c_library
623 * FILE *fopen() c_library
624 * VOID free() c_library
625 * char getnb() lklex.c
626 * VOID lkexit() lkmain.c
627 * VOID loadfile() lklibr.c
628 * VOID * new() lksym.c
629 * char * sprintf() c_library
630 * int sscanf() c_library
631 * char * strcat() c_library
632 * char * strchr() c_library
633 * char * strcpy() c_library
634 * int strlen() c_library
635 * int strncmp() c_library
636 * VOID unget() lklex.c
639 * If the symbol is found then a new lbfile structure
640 * is created and added to the linked list of lbfile
641 * structures. The file containing the found symbol
647 /* First entry in the library object symbol cache */
650 int fndsym( char *name )
652 struct lbfile *lbfh, *lbf;
653 pmlibraryfile ThisLibr;
654 pmlibrarysymbol ThisSym = NULL;
656 pmlibraryfile FirstFound;
659 /* Build the index if this is the first call to fndsym */
663 /* Iterate through all library object files */
664 ThisLibr = libr.next;
665 FirstFound = libr.next; /*So gcc stops whining*/
668 /* Iterate through all symbols in an object file */
669 ThisSym = ThisLibr->symbols->next;
673 if (!strcmp(ThisSym->name, name))
675 if ((!ThisLibr->loaded) && (numfound==0))
677 /* Object file is not loaded - add it to the list */
678 lbfh = (struct lbfile *) new (sizeof(struct lbfile));
690 lbfh->libspc = ThisLibr->libspc;
691 lbfh->filspc = ThisLibr->str;
692 lbfh->relfil = (char *) new (strlen(ThisLibr->relfil) + 1);
693 strcpy(lbfh->relfil,ThisLibr->relfil);
694 lbfh->offset = ThisLibr->offset;
696 { /*For an embedded object file in a library*/
697 void loadfile_SdccLib(char * libspc, char * module, long offset);
698 loadfile_SdccLib(lbfh->libspc, lbfh->relfil, lbfh->offset);
701 { /*For a stand alone object file*/
702 /* if cdb information required & adb file present */
705 FILE *xfp = afile(lbfh->filspc, "adb",0);
708 SaveLinkedFilePath(lbfh->filspc);
713 loadfile(lbfh->filspc);
725 char absPath1[PATH_MAX];
726 char absPath2[PATH_MAX];
727 #if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
730 _fullpath(absPath1, FirstFound->libspc, PATH_MAX);
731 _fullpath(absPath2, ThisLibr->libspc, PATH_MAX);
732 for(j=0; absPath1[j]!=0; j++) absPath1[j]=tolower(absPath1[j]);
733 for(j=0; absPath2[j]!=0; j++) absPath2[j]=tolower(absPath2[j]);
735 realpath(FirstFound->libspc, absPath1);
736 realpath(ThisLibr->libspc, absPath2);
738 if( !( EQ(absPath1, absPath2) && EQ(FirstFound->relfil, ThisLibr->relfil) ) )
742 printf("?Aslink-Warning-Definition of public symbol '%s'"
743 " found more than once:\n", name);
744 printf(" Library: '%s', Module: '%s'\n",
745 FirstFound->libspc, FirstFound->relfil);
747 printf(" Library: '%s', Module: '%s'\n",
748 ThisLibr->libspc, ThisLibr->relfil);
753 ThisSym=ThisSym->next; /* Next sym in library */
755 ThisLibr=ThisLibr->next; /* Next library in list */
760 pmlibraryfile buildlibraryindex_SdccLib(char * PathLib, FILE * libfp, char * DirLib, pmlibraryfile This)
762 char ModName[NCPS]="";
763 char FLine[MAXLINE+1];
765 long IndexOffset=0, FileOffset;
766 pmlibrarysymbol ThisSym = NULL;
771 fgets(FLine, MAXLINE, libfp);
777 if(EQ(FLine, "<INDEX>"))
779 /*The next line has the size of the index*/
781 fgets(FLine, MAXLINE, libfp);
783 IndexOffset=atol(FLine);
788 if(EQ(FLine, "<MODULE>"))
790 /*The next line has the name of the module and the offset
791 of the corresponding embedded file in the library*/
793 fgets(FLine, MAXLINE, libfp);
795 sscanf(FLine, "%s %ld", ModName, &FileOffset);
798 /*create a new libraryfile object for this module*/
799 This->next = (pmlibraryfile)new( sizeof( mlibraryfile ));
800 if (This->next == NULL)
802 printf("panic: can't allocate memory.\n");
808 This->loaded=-1; /*Kind of useless, but...*/
809 This->offset=FileOffset+IndexOffset;
810 This->libspc=PathLib;
811 strcpy(This->relfil, ModName);
813 sprintf(This->filename, "%s%s%crel", DirLib, ModName, FSEPX);
815 This->str=This->filename;
817 ThisSym = This->symbols = (pmlibrarysymbol)malloc( sizeof(mlibrarysymbol));
818 ThisSym->next = NULL;
820 else if(EQ(FLine, "</INDEX>"))
822 return This; /*Finish, get out of here*/
826 if(EQ(FLine, "</MODULE>"))
829 /*Create the index for the next module*/
835 ThisSym->next = (pmlibrarysymbol)malloc(sizeof(mlibrarysymbol));
836 ThisSym=ThisSym->next;
839 printf("panic: can't allocate memory.\n");
843 strcpy(ThisSym->name, FLine);
848 return This; /*State machine should never reach this point, but just in case...*/
853 return This; /*State machine should never reach this point, but just in case...*/
857 /* buildlibraryindex - build an in-memory cache of the symbols contained in
860 int buildlibraryindex(void)
864 char relfil[NINPUT+2], *str, *path;
865 char buf[NINPUT+2], c;
866 char symname[NINPUT+2];
868 pmlibrarysymbol ThisSym;
873 * Search through every library in the linked list "lbnhead".
876 for (lbnh=lbnhead; lbnh; lbnh=lbnh->next)
878 if ((libfp = fopen(lbnh->libspc, "r")) == NULL)
880 fprintf(stderr, "Cannot open library file %s\n",
887 * Read in a line from the library file.
888 * This is the relative file specification
889 * for a .REL file in this library.
892 while (fgets(relfil, NINPUT, libfp) != NULL)
894 relfil[NINPUT+1] = '\0';
898 str = (char *)new(strlen(path)+strlen(relfil)+6);
901 if (str[strlen(str)-1] != '/')
909 str = (char *)new(strlen(relfil) + 5);
912 if(strcmp(relfil, "<SDCCLIB>")==0)
914 /*Get the built in index of a library*/
915 This=buildlibraryindex_SdccLib(lbnh->libspc, libfp, str, This);
918 break; /*get the index for next library*/
921 /*From here down, build the index for the original library format*/
923 if (relfil[0] == '\\')
925 strcat(str,relfil+1);
932 if(strchr(relfil, FSEPX) == NULL)
934 sprintf(&str[strlen(str)], "%crel", FSEPX);
937 if ((fp = fopen(str, "r")) != NULL)
939 /* Opened OK - create a new libraryfile object for it */
940 This->next = (pmlibraryfile)new( sizeof( mlibraryfile ));
941 if (This->next == NULL)
943 printf("panic: can't allocate memory.\n");
950 This->offset=-1; /*There should be a rel file*/
952 strcpy( This->filename, str );
954 ThisSym = This->symbols = (pmlibrarysymbol)malloc( sizeof(mlibrarysymbol));
955 ThisSym->next = NULL;
958 * Read in the object file. Look for lines that
959 * begin with "S" and end with "D". These are
960 * symbol table definitions. If we find one, see
961 * if it is our symbol. Make sure we only read in
962 * our object file and don't go into the next one.
965 while (fgets(buf, NINPUT, fp) != NULL)
967 buf[NINPUT+1] = '\0';
968 buf[strlen(buf) - 1] = '\0';
971 * Skip everything that's not a symbol record.
973 if (buf[0] != 'S') continue;
976 * When a 'T line' is found terminate file scan.
977 * All 'S line's preceed 'T line's in .REL files.
979 if (buf[0] == 'T') break;
981 sscanf(buf, "S %s %c", symname, &c);
983 /* If it's an actual symbol, record it */
986 ThisSym->next = (pmlibrarysymbol)malloc(sizeof(mlibrarysymbol));
987 ThisSym=ThisSym->next;
990 printf("panic: can't allocate memory.\n");
996 strcpy(This->relfil,relfil);
997 strcpy(ThisSym->name, symname);
998 This->libspc = lbnh->libspc;
1000 } /* Closes while - read object file */
1002 } /* Closes if object file opened OK */
1003 } /* Ends while - processing all in libr */
1005 } /* Ends good open of libr file */
1008 #else /* INDEXLIB */
1015 struct lbname *lbnh;
1016 struct lbfile *lbfh, *lbf;
1017 char relfil[NINPUT+2];
1019 char symname[NINPUT];
1025 * Search through every library in the linked list "lbnhead".
1028 for (lbnh=lbnhead; lbnh; lbnh=lbnh->next)
1030 if ((libfp = fopen(lbnh->libspc, "r")) == NULL)
1032 fprintf(stderr, "Cannot open library file %s\n",
1039 * Read in a line from the library file.
1040 * This is the relative file specification
1041 * for a .REL file in this library.
1044 while (fgets(relfil, NINPUT, libfp) != NULL)
1046 relfil[NINPUT+1] = '\0';
1050 str = (char *) new (strlen(path)+strlen(relfil)+6);
1053 if (str[strlen(str)-1] != '/')
1061 str = (char *) new (strlen(relfil) + 5);
1064 if(strcmp(relfil, "<SDCCLIB>")==0)
1066 result=SdccLib(lbnh->libspc, libfp, str, name);
1068 if(result) return(1); /*Found the symbol*/
1070 /*The symbol is not in the current library,
1071 check the next library in the list*/
1075 /*From here down is the support for libraries in the original format*/
1076 if (relfil[0] == '\\')
1078 strcat(str,relfil+1);
1085 if(strchr(relfil, FSEPX) == NULL)
1087 sprintf(&str[strlen(str)], "%crel", FSEPX);
1090 if ((fp = fopen(str, "r")) != NULL)
1094 * Read in the object file. Look for lines that
1095 * begin with "S" and end with "D". These are
1096 * symbol table definitions. If we find one, see
1097 * if it is our symbol. Make sure we only read in
1098 * our object file and don't go into the next one.
1101 while (fgets(buf, NINPUT, fp) != NULL)
1103 buf[NINPUT+1] = '\0';
1106 * Skip everything that's not a symbol record.
1108 if (buf[0] != 'S') continue;
1111 * When a 'T line' is found terminate file scan.
1112 * All 'S line's preceed 'T line's in .REL files.
1114 if (buf[0] == 'T') break;
1116 sscanf(buf, "S %s %c", symname, &c);
1119 * If we find a symbol definition for the
1120 * symbol we're looking for, load in the
1121 * file and add it to lbfhead so it gets
1122 * loaded on pass number 2.
1124 if (strncmp(symname, name, NCPS) == 0 && c == 'D')
1126 lbfh = (struct lbfile *) new (sizeof(struct lbfile));
1127 if (lbfhead == NULL)
1139 lbfh->libspc = lbnh->libspc;
1141 lbfh->relfil = (char *) new (strlen(relfil) + 1);
1142 lbfh->offset = -1; /*Stand alone rel file*/
1143 strcpy(lbfh->relfil,relfil);
1147 /* if cdb information required & adb file present */
1150 FILE *xfp = afile(str,"adb",0); //JCF: Nov 30, 2002
1153 SaveLinkedFilePath(str);
1173 void loadfile_SdccLib(char * libspc, char * module, long offset)
1177 if ((fp = fopen(libspc,"r")) != NULL)
1179 fseek(fp, offset, SEEK_SET);
1180 LoadRel(fp, module);
1185 /*)Function VOID library()
1187 * The function library() links all the library object files
1188 * contained in the lbfile structures.
1191 * lbfile *lbfh pointer to lbfile structure
1194 * lbfile *lbfhead pointer to first lbfile structure
1197 * VOID loadfile lklibr.c
1200 * Links all files contained in the lbfile structures.
1206 struct lbfile *lbfh;
1208 for (lbfh=lbfhead; lbfh; lbfh=lbfh->next)
1212 /*Stand alone rel file (original lib format)*/
1213 loadfile(lbfh->filspc);
1217 /*rel file embedded in lib (new lib format)*/
1218 loadfile_SdccLib(lbfh->libspc, lbfh->relfil, lbfh->offset);
1223 /*)Function VOID loadfile(filspc)
1225 * char *filspc library object file specification
1227 * The function loadfile() links the library object module.
1230 * FILE *fp file handle
1231 * int i input line length
1232 * char str[] file input line
1235 * char *ip pointer to linker input string
1238 * int fclose() c_library
1239 * int fgets() c_library
1240 * FILE * fopen() c_library
1241 * VOID link_main() lkmain.c
1242 * int strlen() c_library
1245 * If file exists it is linked.
1255 if ((fp = fopen(filspc,"r")) != NULL) {
1256 while (fgets(str, NINPUT, fp) != NULL) {
1257 str[NINPUT+1] = '\0';