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>
34 * The module lklibr.c contains the functions which
35 * (1) specify the path(s) to library files [.LIB]
36 * (2) specify the library file(s) [.LIB] to search
37 * (3) search the library files for specific symbols
38 * and link the module containing this symbol
40 * lklibr.c contains the following functions:
52 typedef struct slibrarysymbol mlibrarysymbol;
53 typedef struct slibrarysymbol *pmlibrarysymbol;
55 struct slibrarysymbol {
60 typedef struct slibraryfile mlibraryfile;
61 typedef struct slibraryfile *pmlibraryfile;
67 char relfil[PATH_MAX];
68 char filename[PATH_MAX];
69 long offset; //if > 0, the embedded file offset in the library file libspc
70 pmlibrarysymbol symbols;
74 int buildlibraryindex();
77 /*)Function VOID addpath()
79 * The function addpath() creates a linked structure containing
80 * the paths to various object module library files.
83 * lbpath *lbph pointer to new path structure
84 * lbpath *lbp temporary pointer
87 * lbpath *lbphead The pointer to the first
91 * char getnb() lklex.c
92 * VOID * new() lksym.c
93 * int strlen() c_library
94 * char * strcpy() c_library
95 * VOID unget() lklex.c
98 * An lbpath structure may be created.
104 struct lbpath *lbph, *lbp;
106 lbph = (struct lbpath *) new (sizeof(struct lbpath));
107 if (lbphead == NULL) {
116 lbph->path = (char *) new (strlen(ip)+1);
117 strcpy(lbph->path, ip);
120 /*)Function VOID addlib()
122 * The function addlib() tests for the existance of a
123 * library path structure to determine the method of
124 * adding this library file to the library search structure.
126 * This function calls the function addfile() to actually
127 * add the library file to the search list.
130 * lbpath *lbph pointer to path structure
133 * lbpath *lbphead The pointer to the first
135 * ip a pointer to the library name
138 * VOID addfile() lklibr.c
139 * char getnb() lklex.c
140 * VOID unget() lklex.c
143 * The function addfile() may add the file to
144 * the library search list.
157 foundcount=addfile(NULL, ip);
161 for (lbph=lbphead; lbph; lbph=lbph->next)
163 foundcount+=addfile(lbph->path, ip);
168 printf("?ASlink-Warning-Couldn't find library '%s'\n", ip);
172 /*)Function int addfile(path,libfil)
174 * char *path library path specification
175 * char *libfil library file specification
177 * The function addfile() searches for the library file
178 * by concatenating the path and libfil specifications.
179 * if the library is found, an lbname structure is created
180 * and linked to any previously defined structures. This
181 * linked list is used by the function fndsym() to attempt
182 * to find any undefined symbols.
184 * The function does not give report an error on invalid
185 * path / file specifications or if the file is not found.
188 * lbname *lbnh pointer to new name structure
189 * lbname *lbn temporary pointer
192 * lbname *lbnhead The pointer to the first
196 * char getnb() lklex.c
197 * VOID * new() lksym.c
198 * int strlen() c_library
199 * char * strcpy() c_library
200 * VOID unget() lklex.c
203 * An lbname structure may be created.
206 * 1: the library was found
207 * 0: the library was not found
210 int addfile(char * path, char * libfil)
214 struct lbname *lbnh, *lbn;
221 str = (char *) new (strlen(path) + strlen(libfil) + 6);
224 if (str[strlen(str)-1] != '/')
232 str = (char *) new (strlen(libfil) + 5);
236 if (libfil[0] == '/')
244 if(strchr(libfil, FSEPX) == NULL)
246 sprintf(&str[strlen(str)], "%clib", FSEPX);
252 /*Ok, that didn't work. Try with the 'libfil' name only*/
254 if(libfilinc) libfil--;
256 fp=fopen(libfil, "r");
259 /*Bingo! 'libfil' is the absolute path of the library*/
261 path=NULL;/*This way 'libfil' and 'path' will be rebuilt from 'str'*/
267 /*'path' can not be null since it is needed to find the '.rel' files associated with
268 the library. So, get 'path' from 'str' and then chop it off and recreate 'libfil'.
269 That way putting 'path' and 'libfil' together will result into the original filepath
270 as contained in 'str'.*/
272 path = (char *) new (strlen(str));
274 for(j=strlen(path)-1; j>=0; j--)
276 if((path[j]=='\\')||(path[j]=='/'))
278 strcpy(libfil, &path[j+1]);
289 lbnh = (struct lbname *) new (sizeof(struct lbname));
303 lbnh->libfil = (char *) new (strlen(libfil) + 1);
304 strcpy(lbnh->libfil,libfil);
315 /*)Function VOID search()
317 * The function search() looks through all the symbol tables
318 * at the end of pass 1. If any undefined symbols are found
319 * then the function fndsym() is called. Function fndsym()
320 * searches any specified library files to automagically
321 * import the object modules containing the needed symbol.
323 * After a symbol is found and imported by the function
324 * fndsym() the symbol tables are again searched. The
325 * symbol tables are search until no more symbols can be
326 * resolved within the library files. This ensures that
327 * back references from one library module to another are
331 * int i temporary counter
332 * sym *sp pointer to a symbol structure
333 * int symfnd found a symbol flag
336 * sym *symhash[] array of pointers to symbol tables
339 * int fndsym() lklibr.c
342 * If a symbol is found then the library object module
343 * containing the symbol will be imported and linked.
349 register struct sym *sp;
350 register int i,symfnd;
353 * Look for undefined symbols. Keep
354 * searching until no more symbols are resolved.
360 * Look through all the symbols
362 for (i=0; i<NHASH; ++i) {
365 /* If we find an undefined symbol
366 * (one where S_DEF is not set), then
367 * try looking for it. If we find it
368 * in any of the libraries then
369 * increment symfnd. This will force
370 * another pass of symbol searching and
371 * make sure that back references work.
373 if ((sp->s_type & S_DEF) == 0) {
374 if (fndsym(sp->s_id)) {
384 /*Load a .rel file embedded in a sdcclib file*/
385 void LoadRel(FILE * libfp, char * ModName)
390 while (fgets(str, NINPUT, libfp) != NULL)
392 str[NINPUT+1] = '\0';
397 if(EQ(str, "<FILE>"))
399 fgets(str, NINPUT, libfp);
400 str[NINPUT+1] = '\0';
402 if(EQ(str, ModName)) state=1;
405 printf("Bad offset in library file str=%s, Modname=%s\n", str, ModName);
411 if(EQ(str, "<REL>")) state=2;
414 if(EQ(str, "</REL>")) return;
422 /*Load an .adb file embedded in a sdcclib file. If there is
423 something between <ADB> and </ADB> returns 1, otherwise returns 0.
424 This way the aomf51 will not have uselless empty modules. */
426 int LoadAdb(FILE * libfp)
432 while (fgets(str, MAXLINE, libfp) != NULL)
434 str[NINPUT+1] = '\0';
439 if(EQ(str, "<ADB>")) state=1;
442 if(EQ(str, "</ADB>")) return ToReturn;
443 fprintf(dfp, "%s\n", str);
451 /*Check for a symbol in a SDCC library. If found, add the embedded .rel and
452 .adb files from the library. The library must be created with the SDCC
453 librarian 'sdcclib' since the linking process depends on the correct file offsets
454 embedded in the library file.*/
456 int SdccLib(char * PathLib, FILE * libfp, char * DirLib, char * SymName)
458 struct lbfile *lbfh, *lbf;
459 char ModName[NCPS]="";
460 char FLine[MAXLINE+1];
462 long IndexOffset=0, FileOffset;
467 fgets(FLine, MAXLINE, libfp);
473 if(EQ(FLine, "<INDEX>"))
475 /*The next line has the size of the index*/
477 fgets(FLine, MAXLINE, libfp);
479 IndexOffset=atol(FLine);
484 if(EQ(FLine, "<MODULE>"))
486 /*The next line has the name of the module and the offset
487 of the corresponding embedded file in the library*/
489 fgets(FLine, MAXLINE, libfp);
491 sscanf(FLine, "%s %ld", ModName, &FileOffset);
494 else if(EQ(FLine, "</INDEX>"))
496 /*Reached the end of the index. The symbol is not in this library.*/
501 if(EQ(FLine, "</MODULE>"))
503 /*The symbol is not in this module, try the next one*/
508 /*Check if this is the symbol we are looking for.*/
509 if (strncmp(SymName, FLine, NCPS)==0)
511 /*The symbol is in this module.*/
513 /*As in the original library format, it is assumed that the .rel
514 files reside in the same directory as the lib files.*/
515 strcat(DirLib, ModName);
516 sprintf(&DirLib[strlen(DirLib)], "%crel", FSEPX);
518 /*If this module has been loaded already don't load it again.*/
522 if(EQ(DirLib, lbf->filspc)) return 1;/*Already loaded*/
526 /*Add the embedded file to the list of files to be loaded in
527 the second pass. That is performed latter by the function
529 lbfh = (struct lbfile *) new (sizeof(struct lbfile));
542 lbfh->libspc = PathLib;
543 lbfh->filspc = DirLib;
544 lbfh->relfil = (char *) new (strlen(ModName) + 1);
545 strcpy(lbfh->relfil, ModName);
546 /*Library embedded file, so lbfh->offset must be >=0*/
547 lbfh->offset = IndexOffset+FileOffset;
549 /*Jump to where the .rel begins and load it.*/
550 fseek(libfp, lbfh->offset, SEEK_SET);
551 LoadRel(libfp, ModName);
553 /* if cdb information required & .adb file present */
557 SaveLinkedFilePath(DirLib);
559 return 1; /*Found the symbol, so success!*/
565 return 0; /*It should never reach this point, but just in case...*/
570 return 0; /*The symbol is not in this library*/
573 /*)Function VOID fndsym(name)
575 * char *name symbol name to find
577 * The function fndsym() searches through all combinations of the
578 * library path specifications (input by the -k option) and the
579 * library file specifications (input by the -l option) that
580 * lead to an existing file.
582 * The file specicifation may be formed in one of two ways:
584 * (1) If the library file contained an absolute
585 * path/file specification then this becomes filspc.
588 * (2) If the library file contains a relative path/file
589 * specification then the concatenation of the path
590 * and this file specification becomes filspc.
593 * The structure lbfile is created for the first library
594 * object file which contains the definition for the
595 * specified undefined symbol.
597 * If the library file [.LIB] contains file specifications for
598 * non existant files, no errors are returned.
601 * char buf[] [.REL] file input line
602 * char c [.REL] file input character
603 * FILE *fp file handle for object file
604 * lbfile *lbf temporary pointer
605 * lbfile *lbfh pointer to lbfile structure
606 * FILE *libfp file handle for library file
607 * lbname *lbnh pointer to lbname structure
608 * char *path file specification path
609 * char relfil[] [.REL] file specification
610 * char *str combined path and file specification
611 * char symname[] [.REL] file symbol string
614 * lbname *lbnhead The pointer to the first
616 * lbfile *lbfhead The pointer to the first
620 * int fclose() c_library
621 * int fgets() c_library
622 * FILE *fopen() c_library
623 * VOID free() c_library
624 * char getnb() lklex.c
625 * VOID lkexit() lkmain.c
626 * VOID loadfile() lklibr.c
627 * VOID * new() lksym.c
628 * char * sprintf() c_library
629 * int sscanf() c_library
630 * char * strcat() c_library
631 * char * strchr() c_library
632 * char * strcpy() c_library
633 * int strlen() c_library
634 * int strncmp() c_library
635 * VOID unget() lklex.c
638 * If the symbol is found then a new lbfile structure
639 * is created and added to the linked list of lbfile
640 * structures. The file containing the found symbol
646 /* First entry in the library object symbol cache */
649 int fndsym( char *name )
651 struct lbfile *lbfh, *lbf;
652 pmlibraryfile ThisLibr;
653 pmlibrarysymbol ThisSym = NULL;
655 pmlibraryfile FirstFound;
658 /* Build the index if this is the first call to fndsym */
662 /* Iterate through all library object files */
663 ThisLibr = libr.next;
664 FirstFound = libr.next; /*So gcc stops whining*/
667 /* Iterate through all symbols in an object file */
668 ThisSym = ThisLibr->symbols->next;
672 if (!strcmp(ThisSym->name, name))
674 if ((!ThisLibr->loaded) && (numfound==0))
676 /* Object file is not loaded - add it to the list */
677 lbfh = (struct lbfile *) new (sizeof(struct lbfile));
689 lbfh->libspc = ThisLibr->libspc;
690 lbfh->filspc = ThisLibr->str;
691 lbfh->relfil = (char *) new (strlen(ThisLibr->relfil) + 1);
692 strcpy(lbfh->relfil,ThisLibr->relfil);
693 lbfh->offset = ThisLibr->offset;
695 { /*For an embedded object file in a library*/
696 void loadfile_SdccLib(char * libspc, char * module, long offset);
697 loadfile_SdccLib(lbfh->libspc, lbfh->relfil, lbfh->offset);
700 { /*For a stand alone object file*/
701 /* if cdb information required & adb file present */
704 FILE *xfp = afile(lbfh->filspc, "adb",0);
707 SaveLinkedFilePath(lbfh->filspc);
712 loadfile(lbfh->filspc);
724 char absPath1[PATH_MAX];
725 char absPath2[PATH_MAX];
726 #if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
729 _fullpath(absPath1, FirstFound->libspc, PATH_MAX);
730 _fullpath(absPath2, ThisLibr->libspc, PATH_MAX);
731 for(j=0; absPath1[j]!=0; j++) absPath1[j]=tolower(absPath1[j]);
732 for(j=0; absPath2[j]!=0; j++) absPath2[j]=tolower(absPath2[j]);
734 realpath(FirstFound->libspc, absPath1);
735 realpath(ThisLibr->libspc, absPath2);
737 if( !( EQ(absPath1, absPath2) && EQ(FirstFound->relfil, ThisLibr->relfil) ) )
741 printf("?Aslink-Warning-Definition of public symbol '%s'"
742 " found more than once:\n", name);
743 printf(" Library: '%s', Module: '%s'\n",
744 FirstFound->libspc, FirstFound->relfil);
746 printf(" Library: '%s', Module: '%s'\n",
747 ThisLibr->libspc, ThisLibr->relfil);
752 ThisSym=ThisSym->next; /* Next sym in library */
754 ThisLibr=ThisLibr->next; /* Next library in list */
759 pmlibraryfile buildlibraryindex_SdccLib(char * PathLib, FILE * libfp, char * DirLib, pmlibraryfile This)
761 char ModName[NCPS]="";
762 char FLine[MAXLINE+1];
764 long IndexOffset=0, FileOffset;
765 pmlibrarysymbol ThisSym = NULL;
770 fgets(FLine, MAXLINE, libfp);
776 if(EQ(FLine, "<INDEX>"))
778 /*The next line has the size of the index*/
780 fgets(FLine, MAXLINE, libfp);
782 IndexOffset=atol(FLine);
787 if(EQ(FLine, "<MODULE>"))
789 /*The next line has the name of the module and the offset
790 of the corresponding embedded file in the library*/
792 fgets(FLine, MAXLINE, libfp);
794 sscanf(FLine, "%s %ld", ModName, &FileOffset);
797 /*create a new libraryfile object for this module*/
798 This->next = (pmlibraryfile)new( sizeof( mlibraryfile ));
799 if (This->next == NULL)
801 printf("panic: can't allocate memory.\n");
807 This->loaded=-1; /*Kind of useless, but...*/
808 This->offset=FileOffset+IndexOffset;
809 This->libspc=PathLib;
810 strcpy(This->relfil, ModName);
812 sprintf(This->filename, "%s%s%crel", DirLib, ModName, FSEPX);
814 This->str=This->filename;
816 ThisSym = This->symbols = (pmlibrarysymbol)malloc( sizeof(mlibrarysymbol));
817 ThisSym->next = NULL;
819 else if(EQ(FLine, "</INDEX>"))
821 return This; /*Finish, get out of here*/
825 if(EQ(FLine, "</MODULE>"))
828 /*Create the index for the next module*/
834 ThisSym->next = (pmlibrarysymbol)malloc(sizeof(mlibrarysymbol));
835 ThisSym=ThisSym->next;
838 printf("panic: can't allocate memory.\n");
842 strcpy(ThisSym->name, FLine);
847 return This; /*State machine should never reach this point, but just in case...*/
852 return This; /*State machine should never reach this point, but just in case...*/
856 /* buildlibraryindex - build an in-memory cache of the symbols contained in
859 int buildlibraryindex(void)
863 char relfil[NINPUT+2], *str, *path;
864 char buf[NINPUT+2], c;
865 char symname[NINPUT+2];
867 pmlibrarysymbol ThisSym;
872 * Search through every library in the linked list "lbnhead".
875 for (lbnh=lbnhead; lbnh; lbnh=lbnh->next)
877 if ((libfp = fopen(lbnh->libspc, "r")) == NULL)
879 fprintf(stderr, "Cannot open library file %s\n",
886 * Read in a line from the library file.
887 * This is the relative file specification
888 * for a .REL file in this library.
891 while (fgets(relfil, NINPUT, libfp) != NULL)
893 relfil[NINPUT+1] = '\0';
897 str = (char *)new(strlen(path)+strlen(relfil)+6);
900 if (str[strlen(str)-1] != '/')
908 str = (char *)new(strlen(relfil) + 5);
911 if(strcmp(relfil, "<SDCCLIB>")==0)
913 /*Get the built in index of a library*/
914 This=buildlibraryindex_SdccLib(lbnh->libspc, libfp, str, This);
917 break; /*get the index for next library*/
920 /*From here down, build the index for the original library format*/
922 if (relfil[0] == '\\')
924 strcat(str,relfil+1);
931 if(strchr(relfil, FSEPX) == NULL)
933 sprintf(&str[strlen(str)], "%crel", FSEPX);
936 if ((fp = fopen(str, "r")) != NULL)
938 /* Opened OK - create a new libraryfile object for it */
939 This->next = (pmlibraryfile)new( sizeof( mlibraryfile ));
940 if (This->next == NULL)
942 printf("panic: can't allocate memory.\n");
949 This->offset=-1; /*There should be a rel file*/
951 strcpy( This->filename, str );
953 ThisSym = This->symbols = (pmlibrarysymbol)malloc( sizeof(mlibrarysymbol));
954 ThisSym->next = NULL;
957 * Read in the object file. Look for lines that
958 * begin with "S" and end with "D". These are
959 * symbol table definitions. If we find one, see
960 * if it is our symbol. Make sure we only read in
961 * our object file and don't go into the next one.
964 while (fgets(buf, NINPUT, fp) != NULL)
966 buf[NINPUT+1] = '\0';
967 buf[strlen(buf) - 1] = '\0';
970 * Skip everything that's not a symbol record.
972 if (buf[0] != 'S') continue;
975 * When a 'T line' is found terminate file scan.
976 * All 'S line's preceed 'T line's in .REL files.
978 if (buf[0] == 'T') break;
980 sscanf(buf, "S %s %c", symname, &c);
982 /* If it's an actual symbol, record it */
985 ThisSym->next = (pmlibrarysymbol)malloc(sizeof(mlibrarysymbol));
986 ThisSym=ThisSym->next;
989 printf("panic: can't allocate memory.\n");
995 strcpy(This->relfil,relfil);
996 strcpy(ThisSym->name, symname);
997 This->libspc = lbnh->libspc;
999 } /* Closes while - read object file */
1001 } /* Closes if object file opened OK */
1002 } /* Ends while - processing all in libr */
1004 } /* Ends good open of libr file */
1007 #else /* INDEXLIB */
1014 struct lbname *lbnh;
1015 struct lbfile *lbfh, *lbf;
1016 char relfil[NINPUT+2];
1018 char symname[NINPUT];
1024 * Search through every library in the linked list "lbnhead".
1027 for (lbnh=lbnhead; lbnh; lbnh=lbnh->next)
1029 if ((libfp = fopen(lbnh->libspc, "r")) == NULL)
1031 fprintf(stderr, "Cannot open library file %s\n",
1038 * Read in a line from the library file.
1039 * This is the relative file specification
1040 * for a .REL file in this library.
1043 while (fgets(relfil, NINPUT, libfp) != NULL)
1045 relfil[NINPUT+1] = '\0';
1049 str = (char *) new (strlen(path)+strlen(relfil)+6);
1052 if (str[strlen(str)-1] != '/')
1060 str = (char *) new (strlen(relfil) + 5);
1063 if(strcmp(relfil, "<SDCCLIB>")==0)
1065 result=SdccLib(lbnh->libspc, libfp, str, name);
1067 if(result) return(1); /*Found the symbol*/
1069 /*The symbol is not in the current library,
1070 check the next library in the list*/
1074 /*From here down is the support for libraries in the original format*/
1075 if (relfil[0] == '\\')
1077 strcat(str,relfil+1);
1084 if(strchr(relfil, FSEPX) == NULL)
1086 sprintf(&str[strlen(str)], "%crel", FSEPX);
1089 if ((fp = fopen(str, "r")) != NULL)
1093 * Read in the object file. Look for lines that
1094 * begin with "S" and end with "D". These are
1095 * symbol table definitions. If we find one, see
1096 * if it is our symbol. Make sure we only read in
1097 * our object file and don't go into the next one.
1100 while (fgets(buf, NINPUT, fp) != NULL)
1102 buf[NINPUT+1] = '\0';
1105 * Skip everything that's not a symbol record.
1107 if (buf[0] != 'S') continue;
1110 * When a 'T line' is found terminate file scan.
1111 * All 'S line's preceed 'T line's in .REL files.
1113 if (buf[0] == 'T') break;
1115 sscanf(buf, "S %s %c", symname, &c);
1118 * If we find a symbol definition for the
1119 * symbol we're looking for, load in the
1120 * file and add it to lbfhead so it gets
1121 * loaded on pass number 2.
1123 if (strncmp(symname, name, NCPS) == 0 && c == 'D')
1125 lbfh = (struct lbfile *) new (sizeof(struct lbfile));
1126 if (lbfhead == NULL)
1138 lbfh->libspc = lbnh->libspc;
1140 lbfh->relfil = (char *) new (strlen(relfil) + 1);
1141 lbfh->offset = -1; /*Stand alone rel file*/
1142 strcpy(lbfh->relfil,relfil);
1146 /* if cdb information required & adb file present */
1149 FILE *xfp = afile(str,"adb",0); //JCF: Nov 30, 2002
1152 SaveLinkedFilePath(str);
1172 void loadfile_SdccLib(char * libspc, char * module, long offset)
1176 if ((fp = fopen(libspc,"r")) != NULL)
1178 fseek(fp, offset, SEEK_SET);
1179 LoadRel(fp, module);
1184 /*)Function VOID library()
1186 * The function library() links all the library object files
1187 * contained in the lbfile structures.
1190 * lbfile *lbfh pointer to lbfile structure
1193 * lbfile *lbfhead pointer to first lbfile structure
1196 * VOID loadfile lklibr.c
1199 * Links all files contained in the lbfile structures.
1205 struct lbfile *lbfh;
1207 for (lbfh=lbfhead; lbfh; lbfh=lbfh->next)
1211 /*Stand alone rel file (original lib format)*/
1212 loadfile(lbfh->filspc);
1216 /*rel file embedded in lib (new lib format)*/
1217 loadfile_SdccLib(lbfh->libspc, lbfh->relfil, lbfh->offset);
1222 /*)Function VOID loadfile(filspc)
1224 * char *filspc library object file specification
1226 * The function loadfile() links the library object module.
1229 * FILE *fp file handle
1230 * int i input line length
1231 * char str[] file input line
1234 * char *ip pointer to linker input string
1237 * int fclose() c_library
1238 * int fgets() c_library
1239 * FILE * fopen() c_library
1240 * VOID link_main() lkmain.c
1241 * int strlen() c_library
1244 * If file exists it is linked.
1254 if ((fp = fopen(filspc,"r")) != NULL) {
1255 while (fgets(str, NINPUT, fp) != NULL) {
1256 str[NINPUT+1] = '\0';