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*/
31 void ToCygWin(char * filspc)
33 char posix_path[PATH_MAX];
34 void cygwin_conv_to_full_posix_path(char * win_path, char * posix_path);
35 cygwin_conv_to_full_posix_path(filspc, posix_path);
36 strcpy(filspc, posix_path);
42 * The module lklibr.c contains the functions which
43 * (1) specify the path(s) to library files [.LIB]
44 * (2) specify the library file(s) [.LIB] to search
45 * (3) search the library files for specific symbols
46 * and link the module containing this symbol
48 * lklibr.c contains the following functions:
60 typedef struct slibrarysymbol mlibrarysymbol;
61 typedef struct slibrarysymbol *pmlibrarysymbol;
63 struct slibrarysymbol {
68 typedef struct slibraryfile mlibraryfile;
69 typedef struct slibraryfile *pmlibraryfile;
76 char filename[FILSPC];
77 long offset; //if > 0, the embedded file offset in the library file libspc
78 pmlibrarysymbol symbols;
82 int buildlibraryindex();
85 /*)Function VOID addpath()
87 * The function addpath() creates a linked structure containing
88 * the paths to various object module library files.
91 * lbpath *lbph pointer to new path structure
92 * lbpath *lbp temporary pointer
95 * lbpath *lbphead The pointer to the first
99 * char getnb() lklex.c
100 * VOID * new() lksym.c
101 * int strlen() c_library
102 * char * strcpy() c_library
103 * VOID unget() lklex.c
106 * An lbpath structure may be created.
112 struct lbpath *lbph, *lbp;
114 lbph = (struct lbpath *) new (sizeof(struct lbpath));
115 if (lbphead == NULL) {
124 lbph->path = (char *) new (strlen(ip)+1);
125 strcpy(lbph->path, ip);
128 /*)Function VOID addlib()
130 * The function addlib() tests for the existance of a
131 * library path structure to determine the method of
132 * adding this library file to the library search structure.
134 * This function calls the function addfile() to actually
135 * add the library file to the search list.
138 * lbpath *lbph pointer to path structure
141 * lbpath *lbphead The pointer to the first
145 * VOID addfile() lklibr.c
146 * char getnb() lklex.c
147 * VOID unget() lklex.c
150 * The function addfile() may add the file to
151 * the library search list.
161 if (lbphead == NULL) {
165 for (lbph=lbphead; lbph; lbph=lbph->next) {
166 addfile(lbph->path,ip);
170 /*)Function VOID addfile(path,libfil)
172 * char *path library path specification
173 * char *libfil library file specification
175 * The function addfile() searches for the library file
176 * by concatenating the path and libfil specifications.
177 * if the library is found, an lbname structure is created
178 * and linked to any previously defined structures. This
179 * linked list is used by the function fndsym() to attempt
180 * to find any undefined symbols.
182 * The function does not give report an error on invalid
183 * path / file specifications or if the file is not found.
186 * lbname *lbnh pointer to new name structure
187 * lbname *lbn temporary pointer
190 * lbname *lbnhead The pointer to the first
194 * char getnb() lklex.c
195 * VOID * new() lksym.c
196 * int strlen() c_library
197 * char * strcpy() c_library
198 * VOID unget() lklex.c
201 * An lbname structure may be created.
211 struct lbname *lbnh, *lbn;
213 if ((path != NULL) && (strchr(libfil,':') == NULL)){
214 str = (char *) new (strlen(path) + strlen(libfil) + 6);
219 if (str[strlen(str)-1] != '/') {
222 if (str[strlen(str)-1] != '\\') {
226 if (str[strlen(str)-1] != '\\') {
232 str = (char *) new (strlen(libfil) + 5);
237 if (libfil[0] == '/') { libfil++; }
239 if (libfil[0] == '\\') { libfil++; }
242 if (libfil[0] == '\\') { libfil++; }
246 if(strchr(libfil,FSEPX) == NULL) {
247 sprintf(&str[strlen(str)], "%clib", FSEPX);
249 if ((fp = fopen(str, "r")) != NULL) {
251 lbnh = (struct lbname *) new (sizeof(struct lbname));
252 if (lbnhead == NULL) {
260 if ((path != NULL) && (strchr(libfil,':') == NULL)){
263 lbnh->libfil = (char *) new (strlen(libfil) + 1);
264 strcpy(lbnh->libfil,libfil);
271 /*)Function VOID search()
273 * The function search() looks through all the symbol tables
274 * at the end of pass 1. If any undefined symbols are found
275 * then the function fndsym() is called. Function fndsym()
276 * searches any specified library files to automagically
277 * import the object modules containing the needed symbol.
279 * After a symbol is found and imported by the function
280 * fndsym() the symbol tables are again searched. The
281 * symbol tables are search until no more symbols can be
282 * resolved within the library files. This ensures that
283 * back references from one library module to another are
287 * int i temporary counter
288 * sym *sp pointer to a symbol structure
289 * int symfnd found a symbol flag
292 * sym *symhash[] array of pointers to symbol tables
295 * int fndsym() lklibr.c
298 * If a symbol is found then the library object module
299 * containing the symbol will be imported and linked.
305 register struct sym *sp;
306 register int i, symfnd;
309 * Look for undefined symbols. Keep
310 * searching until no more symbols are resolved.
316 * Look through all the symbols
318 for (i=0; i<NHASH; ++i) {
321 /* If we find an undefined symbol
322 * (one where S_DEF is not set), then
323 * try looking for it. If we find it
324 * in any of the libraries then
325 * increment symfnd. This will force
326 * another pass of symbol searching and
327 * make sure that back references work.
329 if ((sp->s_type & S_DEF) == 0) {
330 if (fndsym(sp->s_id)) {
340 /*Load a .rel file embedded in a sdcclib file*/
341 void LoadRel(FILE * libfp, char * ModName)
346 while (fgets(str, NINPUT, libfp) != NULL)
348 str[NINPUT+1] = '\0';
353 if(EQ(str, "<FILE>"))
355 fgets(str, NINPUT, libfp);
356 str[NINPUT+1] = '\0';
358 if(EQ(str, ModName)) state=1;
361 printf("Bad offset in library file str=%s, Modname=%s\n", str, ModName);
367 if(EQ(str, "<REL>")) state=2;
370 if(EQ(str, "</REL>")) return;
378 /*)Function VOID fndsym(name)
380 * char *name symbol name to find
382 * The function fndsym() searches through all combinations of the
383 * library path specifications (input by the -k option) and the
384 * library file specifications (input by the -l option) that
385 * lead to an existing file.
387 * The file specicifation may be formed in one of two ways:
389 * (1) If the library file contained an absolute
390 * path/file specification then this becomes filspc.
393 * (2) If the library file contains a relative path/file
394 * specification then the concatenation of the path
395 * and this file specification becomes filspc.
398 * The structure lbfile is created for the first library
399 * object file which contains the definition for the
400 * specified undefined symbol.
402 * If the library file [.LIB] contains file specifications for
403 * non existant files, no errors are returned.
406 * char buf[] [.REL] file input line
407 * char c [.REL] file input character
408 * FILE *fp file handle for object file
409 * lbfile *lbf temporary pointer
410 * lbfile *lbfh pointer to lbfile structure
411 * FILE *libfp file handle for library file
412 * lbname *lbnh pointer to lbname structure
413 * char *path file specification path
414 * char relfil[] [.REL] file specification
415 * char *str combined path and file specification
416 * char symname[] [.REL] file symbol string
419 * lbname *lbnhead The pointer to the first
421 * lbfile *lbfhead The pointer to the first
425 * int fclose() c_library
426 * int fgets() c_library
427 * FILE *fopen() c_library
428 * VOID free() c_library
429 * char getnb() lklex.c
430 * VOID lkexit() lkmain.c
431 * VOID loadfile() lklibr.c
432 * VOID * new() lksym.c
433 * char * sprintf() c_library
434 * int sscanf() c_library
435 * char * strcat() c_library
436 * char * strchr() c_library
437 * char * strcpy() c_library
438 * int strlen() c_library
439 * int strncmp() c_library
440 * VOID unget() lklex.c
443 * If the symbol is found then a new lbfile structure
444 * is created and added to the linked list of lbfile
445 * structures. The file containing the found symbol
451 /* First entry in the library object symbol cache */
454 int fndsym( char *name )
456 struct lbfile *lbfh, *lbf;
457 pmlibraryfile ThisLibr;
458 pmlibrarysymbol ThisSym = NULL;
460 /* Build the index if this is the first call to fndsym */
464 /* Iterate through all library object files */
465 ThisLibr = libr.next;
468 /* Iterate through all symbols in an object file */
469 ThisSym = ThisLibr->symbols->next;
472 //printf("ThisSym->name=%s\n", ThisSym->name);
473 if (!strcmp(ThisSym->name, name)) {
474 if (!ThisLibr->loaded) {
475 /* Object file is not loaded - add it to the list */
476 lbfh = (struct lbfile *) new (sizeof(struct lbfile));
477 if (lbfhead == NULL) {
485 lbfh->libspc = ThisLibr->libspc;
486 lbfh->filspc = ThisLibr->str;
487 lbfh->relfil = (char *) new (strlen(ThisLibr->relfil) + 1);
488 strcpy(lbfh->relfil,ThisLibr->relfil);
489 lbfh->offset = ThisLibr->offset;
491 { /*For an embedded object file in a library*/
492 void loadfile_SdccLib(char * libspc, char * module, long offset);
493 loadfile_SdccLib(lbfh->libspc, lbfh->relfil, lbfh->offset);
496 { /*For a stand alone object file*/
497 loadfile(lbfh->filspc);
501 return (1); /* Found the symbol, return */
503 ThisSym=ThisSym->next; /* Next sym in library */
505 ThisLibr=ThisLibr->next; /* Next library in list */
507 return 0; /* Failure - symbol not found in any library */
510 pmlibraryfile buildlibraryindex_SdccLib(char * PathLib, FILE * libfp, char * DirLib, pmlibraryfile This)
512 char ModName[NCPS]="";
513 char FLine[MAXLINE+1];
515 long IndexOffset=0, FileOffset;
516 pmlibrarysymbol ThisSym = NULL;
521 fgets(FLine, MAXLINE, libfp);
527 if(EQ(FLine, "<INDEX>"))
529 /*The next line has the size of the index*/
531 fgets(FLine, MAXLINE, libfp);
533 IndexOffset=atol(FLine);
538 if(EQ(FLine, "<MODULE>"))
540 /*The next line has the name of the module and the offset
541 of the corresponding embedded file in the library*/
543 fgets(FLine, MAXLINE, libfp);
545 sscanf(FLine, "%s %ld", ModName, &FileOffset);
548 /*create a new libraryfile object for this module*/
549 This->next = (pmlibraryfile)new( sizeof( mlibraryfile ));
550 if (This->next == NULL)
552 printf("panic: can't allocate memory.\n");
558 This->loaded=-1; /*Kind of useless, but...*/
559 This->offset=FileOffset+IndexOffset;
560 This->libspc=PathLib;
561 strcpy(This->relfil, ModName);
564 sprintf(This->filename, "%s%s%co", DirLib, ModName, FSEPX);
566 sprintf(This->filename, "%s%s%crel", DirLib, ModName, FSEPX);
569 This->str=This->filename;
571 ThisSym = This->symbols = (pmlibrarysymbol)malloc( sizeof(mlibrarysymbol));
572 ThisSym->next = NULL;
574 else if(EQ(FLine, "</INDEX>"))
576 return This; /*Finish, get out of here*/
580 if(EQ(FLine, "</MODULE>"))
583 /*Create the index for the next module*/
589 ThisSym->next = (pmlibrarysymbol)malloc(sizeof(mlibrarysymbol));
590 ThisSym=ThisSym->next;
593 printf("panic: can't allocate memory.\n");
597 strcpy(ThisSym->name, FLine);
602 return This; /*State machine should never reach this point, but just in case...*/
607 return This; /*State machine should never reach this point, but just in case...*/
611 /* buildlibraryindex - build an in-memory cache of the symbols contained in
614 int buildlibraryindex(void)
618 char relfil[NINPUT+2], *str, *path;
619 char buf[NINPUT+2], c;
620 char symname[NINPUT+2];
622 pmlibrarysymbol ThisSym;
626 /* Iterate through all library files */
627 /*1*/ for (lbnh=lbnhead; lbnh; lbnh=lbnh->next) {
628 libfp = fopen( lbnh->libspc, "r" );
633 * Read in a line from the library file.
634 * This is the relative file specification
635 * for a .REL file in this library.
638 /*2*/ while (fgets(relfil, NINPUT, libfp) != NULL) {
639 relfil[NINPUT+1] = '\0';
642 str = (char *)new(strlen(path)+strlen(relfil)+6);
647 if (str[strlen(str)-1] != '/') {
650 if (str[strlen(str)-1] != '\\') {
654 if (str[strlen(str)-1] != '\\') {
660 str = (char *)new(strlen(relfil) + 5);
663 if(strcmp(relfil, "<SDCCLIB>")==0)
665 /*Get the built in index of a library*/
666 This=buildlibraryindex_SdccLib(lbnh->libspc, libfp, str, This);
669 break; /*get the index for next library*/
672 /*From here down, build the index for the original library
676 if (relfil[0] == '/') {
678 if (relfil[0] == '\\') {
681 if (relfil[0] == '\\') {
683 strcat(str,relfil+1);
687 if(strchr(str,FSEPX) == NULL) {
689 sprintf(&str[strlen(str)], "%co", FSEPX);
691 sprintf(&str[strlen(str)], "%crel", FSEPX);
694 /*3*/ if ((fp = fopen(str, "r")) != NULL) {
696 /* Opened OK - create a new libraryfile object for it */
697 This->next = (pmlibraryfile)new( sizeof( mlibraryfile ));
698 if (This->next == NULL) {
699 printf("panic: can't allocate memory.\n");
706 This->offset=-1; /*There should be a rel file*/
708 strcpy( This->filename, str );
710 ThisSym = This->symbols = (pmlibrarysymbol)malloc( sizeof(mlibrarysymbol));
711 ThisSym->next = NULL;
714 * Read in the object file. Look for lines that
715 * begin with "S" and end with "D". These are
716 * symbol table definitions. If we find one, see
717 * if it is our symbol. Make sure we only read in
718 * our object file and don't go into the next one.
721 /*4*/ while (fgets(buf, NINPUT, fp) != NULL) {
723 buf[NINPUT+1] = '\0';
724 buf[strlen(buf) - 1] = '\0';
727 * Skip everything that's not a symbol record.
733 * When a 'T line' is found terminate file scan.
734 * All 'S line's preceed 'T line's in .REL files.
739 sscanf(buf, "S %s %c", symname, &c);
741 /* If it's an actual symbol, record it */
742 /*5*/ if (c == 'D') {
743 ThisSym->next = (pmlibrarysymbol)malloc(sizeof(mlibrarysymbol));
744 ThisSym=ThisSym->next;
745 if (ThisSym == NULL) {
746 printf("panic: can't allocate memory.\n");
752 strcpy(This->relfil,relfil);
753 strcpy(ThisSym->name, symname);
754 This->libspc = lbnh->libspc;
756 } /* Closes while - read object file */
758 } /* Closes if object file opened OK */
759 } /* Ends while - processing all in libr */
761 } /* Ends good open of libr file */
768 /*Check for a symbol in a SDCC library. If found, add the embedded .rel.
769 The library must be created with the SDCC librarian 'sdcclib' since the
770 linking process depends on the correct file offsets embedded in the library
773 int SdccLib(char * PathLib, FILE * libfp, char * DirLib, char * SymName)
775 struct lbfile *lbfh, *lbf;
776 char ModName[NCPS]="";
777 char FLine[MAXLINE+1];
779 long IndexOffset=0, FileOffset;
784 fgets(FLine, MAXLINE, libfp);
790 if(EQ(FLine, "<INDEX>"))
792 /*The next line has the size of the index*/
794 fgets(FLine, MAXLINE, libfp);
796 IndexOffset=atol(FLine);
801 if(EQ(FLine, "<MODULE>"))
803 /*The next line has the name of the module and the offset
804 of the corresponding embedded file in the library*/
806 fgets(FLine, MAXLINE, libfp);
808 sscanf(FLine, "%s %ld", ModName, &FileOffset);
811 else if(EQ(FLine, "</INDEX>"))
813 /*Reached the end of the index. The symbol is not in this library.*/
818 if(EQ(FLine, "</MODULE>"))
820 /*The symbol is not in this module, try the next one*/
825 /*Check if this is the symbol we are looking for.*/
826 if (strncmp(SymName, FLine, NCPS)==0)
828 /*The symbol is in this module.*/
830 /*As in the original library format, it is assumed that the .rel
831 files reside in the same directory as the lib files.*/
832 strcat(DirLib, ModName);
834 sprintf(&DirLib[strlen(DirLib)], "%co", FSEPX);
836 sprintf(&DirLib[strlen(DirLib)], "%crel", FSEPX);
839 /*If this module has been loaded already don't load it again.*/
843 if(EQ(DirLib, lbf->filspc)) return 1;/*Already loaded*/
847 /*Add the embedded file to the list of files to be loaded in
848 the second pass. That is performed latter by the function
850 lbfh = (struct lbfile *) new (sizeof(struct lbfile));
863 lbfh->libspc = PathLib;
864 lbfh->filspc = DirLib;
865 lbfh->relfil = (char *) new (strlen(ModName) + 1);
866 strcpy(lbfh->relfil, ModName);
867 /*Library embedded file, so lbfh->offset must be >=0*/
868 lbfh->offset = IndexOffset+FileOffset;
870 /*Jump to where the .rel begins and load it.*/
871 fseek(libfp, lbfh->offset, SEEK_SET);
872 LoadRel(libfp, ModName);
874 return 1; /*Found the symbol, so success!*/
880 return 0; /*It should never reach this point, but just in case...*/
885 return 0; /*The symbol is not in this library*/
894 struct lbfile *lbfh, *lbf;
895 char relfil[NINPUT+2];
897 char symname[NINPUT];
903 * Search through every library in the linked list "lbnhead".
906 /*1*/ for (lbnh=lbnhead; lbnh; lbnh=lbnh->next) {
907 if ((libfp = fopen(lbnh->libspc, "r")) == NULL) {
908 fprintf(stderr, "Cannot open library file %s\n",
915 * Read in a line from the library file.
916 * This is the relative file specification
917 * for a .REL file in this library.
920 /*2*/ while (fgets(relfil, NINPUT, libfp) != NULL) {
921 relfil[NINPUT+1] = '\0';
924 str = (char *) new (strlen(path)+strlen(relfil)+6);
929 if (str[strlen(str)-1] != '/') {
932 if (str[strlen(str)-1] != '\\') {
936 if (str[strlen(str)-1] != '\\') {
942 str = (char *) new (strlen(relfil) + 5);
945 /*See if this is a library with embedded files*/
946 if(strcmp(relfil, "<SDCCLIB>")==0)
948 result=SdccLib(lbnh->libspc, libfp, str, name);
950 if(result) return(1); /*Found the symbol*/
952 /*The symbol is not in the current library,
953 check the next library in the list*/
957 /*From here down is the support for libraries in the original format*/
960 if (relfil[0] == '/') {
962 if (relfil[0] == '\\') {
965 if (relfil[0] == '\\') {
967 strcat(str,relfil+1);
971 if(strchr(relfil,FSEPX) == NULL) {
973 sprintf(&str[strlen(str)], "%co", FSEPX);
975 sprintf(&str[strlen(str)], "%crel", FSEPX);
978 /*3*/ if ((fp = fopen(str, "r")) != NULL) {
981 * Read in the object file. Look for lines that
982 * begin with "S" and end with "D". These are
983 * symbol table definitions. If we find one, see
984 * if it is our symbol. Make sure we only read in
985 * our object file and don't go into the next one.
988 /*4*/ while (fgets(buf, NINPUT, fp) != NULL) {
990 buf[NINPUT+1] = '\0';
991 buf[strlen(buf) - 1] = '\0';
994 * Skip everything that's not a symbol record.
1000 * When a 'T line' is found terminate file scan.
1001 * All 'S line's preceed 'T line's in .REL files.
1006 sscanf(buf, "S %s %c", symname, &c);
1009 * If we find a symbol definition for the
1010 * symbol we're looking for, load in the
1011 * file and add it to lbfhead so it gets
1012 * loaded on pass number 2.
1014 /*5*/ if (strncmp(symname, name, NCPS) == 0 && c == 'D') {
1016 lbfh = (struct lbfile *) new (sizeof(struct lbfile));
1017 if (lbfhead == NULL) {
1025 lbfh->libspc = lbnh->libspc;
1027 lbfh->relfil = (char *) new (strlen(relfil) + 1);
1028 lbfh->offset = -1; /*Stand alone rel file*/
1029 strcpy(lbfh->relfil,relfil);
1047 #endif /* INDEXLIB */
1049 void loadfile_SdccLib(char * libspc, char * module, long offset)
1057 if ((fp = fopen(libspc,"r")) != NULL)
1059 fseek(fp, offset, SEEK_SET);
1060 LoadRel(fp, module);
1065 /*)Function VOID library()
1067 * The function library() links all the library object files
1068 * contained in the lbfile structures.
1071 * lbfile *lbfh pointer to lbfile structure
1074 * lbfile *lbfhead pointer to first lbfile structure
1077 * VOID loadfile lklibr.c
1080 * Links all files contained in the lbfile structures.
1086 struct lbfile *lbfh;
1088 for (lbfh=lbfhead; lbfh; lbfh=lbfh->next)
1092 /*Stand alone rel file (original lib format)*/
1093 loadfile(lbfh->filspc);
1097 /*rel file embedded in lib (new lib format)*/
1098 loadfile_SdccLib(lbfh->libspc, lbfh->relfil, lbfh->offset);
1103 /*)Function VOID loadfile(filspc)
1105 * char *filspc library object file specification
1107 * The function loadfile() links the library object module.
1110 * FILE *fp file handle
1111 * int i input line length
1112 * char str[] file input line
1115 * char *ip pointer to linker input string
1118 * int fclose() c_library
1119 * int fgets() c_library
1120 * FILE * fopen() c_library
1121 * VOID link() lkmain.c
1122 * int strlen() c_library
1125 * If file exists it is linked.
1140 if ((fp = fopen(filspc,"r")) != NULL) {
1141 while (fgets(str, NINPUT, fp) != NULL) {
1142 str[NINPUT+1] = '\0';
1143 i = strlen(str) - 1;
1153 printf("Couldn't find file %s\n", filspc);