4 * (C) Copyright 1989-1995
11 * With contributions for the
12 * object libraries from
14 * kenh@cmf.nrl.navy.mil
19 * Extensions: P. Felber
29 * The module lklibr.c contains the functions which
30 * (1) specify the path(s) to library files [.LIB]
31 * (2) specify the library file(s) [.LIB] to search
32 * (3) search the library files for specific symbols
33 * and link the module containing this symbol
35 * lklibr.c contains the following functions:
47 typedef struct slibrarysymbol mlibrarysymbol;
48 typedef struct slibrarysymbol *pmlibrarysymbol;
50 struct slibrarysymbol {
55 typedef struct slibraryfile mlibraryfile;
56 typedef struct slibraryfile *pmlibraryfile;
64 pmlibrarysymbol symbols;
68 int buildlibraryindex();
71 /*)Function VOID addpath()
73 * The function addpath() creates a linked structure containing
74 * the paths to various object module library files.
77 * lbpath *lbph pointer to new path structure
78 * lbpath *lbp temporary pointer
81 * lbpath *lbphead The pointer to the first
85 * char getnb() lklex.c
86 * VOID * new() lksym.c
87 * int strlen() c_library
88 * char * strcpy() c_library
89 * VOID unget() lklex.c
92 * An lbpath structure may be created.
98 struct lbpath *lbph, *lbp;
100 lbph = (struct lbpath *) new (sizeof(struct lbpath));
101 if (lbphead == NULL) {
110 lbph->path = (char *) new (strlen(ip)+1);
111 strcpy(lbph->path, ip);
114 /*)Function VOID addlib()
116 * The function addlib() tests for the existance of a
117 * library path structure to determine the method of
118 * adding this library file to the library search structure.
120 * This function calls the function addfile() to actually
121 * add the library file to the search list.
124 * lbpath *lbph pointer to path structure
127 * lbpath *lbphead The pointer to the first
131 * VOID addfile() lklibr.c
132 * char getnb() lklex.c
133 * VOID unget() lklex.c
136 * The function addfile() may add the file to
137 * the library search list.
147 if (lbphead == NULL) {
151 for (lbph=lbphead; lbph; lbph=lbph->next) {
152 addfile(lbph->path,ip);
156 /*)Function VOID addfile(path,libfil)
158 * char *path library path specification
159 * char *libfil library file specification
161 * The function addfile() searches for the library file
162 * by concatenating the path and libfil specifications.
163 * if the library is found, an lbname structure is created
164 * and linked to any previously defined structures. This
165 * linked list is used by the function fndsym() to attempt
166 * to find any undefined symbols.
168 * The function does not give report an error on invalid
169 * path / file specifications or if the file is not found.
172 * lbname *lbnh pointer to new name structure
173 * lbname *lbn temporary pointer
176 * lbname *lbnhead The pointer to the first
180 * char getnb() lklex.c
181 * VOID * new() lksym.c
182 * int strlen() c_library
183 * char * strcpy() c_library
184 * VOID unget() lklex.c
187 * An lbname structure may be created.
197 struct lbname *lbnh, *lbn;
199 if ((path != NULL) && (strchr(libfil,':') == NULL)){
200 str = (char *) new (strlen(path) + strlen(libfil) + 6);
205 if (str[strlen(str)-1] != '/') {
208 if (str[strlen(str)-1] != '\\') {
212 if (str[strlen(str)-1] != '\\') {
218 str = (char *) new (strlen(libfil) + 5);
223 if (libfil[0] == '/') { libfil++; }
225 if (libfil[0] == '\\') { libfil++; }
228 if (libfil[0] == '\\') { libfil++; }
232 if(strchr(str,FSEPX) == NULL) {
233 sprintf(&str[strlen(str)], "%clib", FSEPX);
235 if ((fp = fopen(str, "r")) != NULL) {
237 lbnh = (struct lbname *) new (sizeof(struct lbname));
238 if (lbnhead == NULL) {
246 if ((path != NULL) && (strchr(libfil,':') == NULL)){
249 lbnh->libfil = (char *) new (strlen(libfil) + 1);
250 strcpy(lbnh->libfil,libfil);
257 /*)Function VOID search()
259 * The function search() looks through all the symbol tables
260 * at the end of pass 1. If any undefined symbols are found
261 * then the function fndsym() is called. Function fndsym()
262 * searches any specified library files to automagically
263 * import the object modules containing the needed symbol.
265 * After a symbol is found and imported by the function
266 * fndsym() the symbol tables are again searched. The
267 * symbol tables are search until no more symbols can be
268 * resolved within the library files. This ensures that
269 * back references from one library module to another are
273 * int i temporary counter
274 * sym *sp pointer to a symbol structure
275 * int symfnd found a symbol flag
278 * sym *symhash[] array of pointers to symbol tables
281 * int fndsym() lklibr.c
284 * If a symbol is found then the library object module
285 * containing the symbol will be imported and linked.
291 register struct sym *sp;
292 register int i, symfnd;
295 * Look for undefined symbols. Keep
296 * searching until no more symbols are resolved.
302 * Look through all the symbols
304 for (i=0; i<NHASH; ++i) {
307 /* If we find an undefined symbol
308 * (one where S_DEF is not set), then
309 * try looking for it. If we find it
310 * in any of the libraries then
311 * increment symfnd. This will force
312 * another pass of symbol searching and
313 * make sure that back references work.
315 if ((sp->s_type & S_DEF) == 0) {
316 if (fndsym(sp->s_id)) {
327 /*)Function VOID fndsym(name)
329 * char *name symbol name to find
331 * The function fndsym() searches through all combinations of the
332 * library path specifications (input by the -k option) and the
333 * library file specifications (input by the -l option) that
334 * lead to an existing file.
336 * The file specicifation may be formed in one of two ways:
338 * (1) If the library file contained an absolute
339 * path/file specification then this becomes filspc.
342 * (2) If the library file contains a relative path/file
343 * specification then the concatenation of the path
344 * and this file specification becomes filspc.
347 * The structure lbfile is created for the first library
348 * object file which contains the definition for the
349 * specified undefined symbol.
351 * If the library file [.LIB] contains file specifications for
352 * non existant files, no errors are returned.
355 * char buf[] [.REL] file input line
356 * char c [.REL] file input character
357 * FILE *fp file handle for object file
358 * lbfile *lbf temporary pointer
359 * lbfile *lbfh pointer to lbfile structure
360 * FILE *libfp file handle for library file
361 * lbname *lbnh pointer to lbname structure
362 * char *path file specification path
363 * char relfil[] [.REL] file specification
364 * char *str combined path and file specification
365 * char symname[] [.REL] file symbol string
368 * lbname *lbnhead The pointer to the first
370 * lbfile *lbfhead The pointer to the first
374 * int fclose() c_library
375 * int fgets() c_library
376 * FILE *fopen() c_library
377 * VOID free() c_library
378 * char getnb() lklex.c
379 * VOID lkexit() lkmain.c
380 * VOID loadfile() lklibr.c
381 * VOID * new() lksym.c
382 * char * sprintf() c_library
383 * int sscanf() c_library
384 * char * strcat() c_library
385 * char * strchr() c_library
386 * char * strcpy() c_library
387 * int strlen() c_library
388 * int strncmp() c_library
389 * VOID unget() lklex.c
392 * If the symbol is found then a new lbfile structure
393 * is created and added to the linked list of lbfile
394 * structures. The file containing the found symbol
400 /* First entry in the library object symbol cache */
401 mlibraryfile libr = {
405 int fndsym( char *name )
407 struct lbfile *lbfh, *lbf;
408 pmlibraryfile ThisLibr;
409 pmlibrarysymbol ThisSym = NULL;
411 /* Build the index if this is the first call to fndsym */
415 /* Iterate through all library object files */
416 ThisLibr = libr.next;
419 /* Iterate through all symbols in an object file */
420 ThisSym = ThisLibr->symbols->next;
423 if (!strcmp(ThisSym->name, name)) {
424 if (!ThisLibr->loaded) {
425 /* Object file is not loaded - add it to the list */
426 lbfh = (struct lbfile *) new (sizeof(struct lbfile));
427 if (lbfhead == NULL) {
435 lbfh->libspc = ThisLibr->libspc;
436 lbfh->filspc = ThisLibr->str;
437 lbfh->relfil = (char *) new (strlen(ThisLibr->relfil) + 1);
438 strcpy(lbfh->relfil,ThisLibr->relfil);
439 loadfile(lbfh->filspc);
442 return (1); /* Found the symbol, return */
444 ThisSym=ThisSym->next; /* Next sym in library */
446 ThisLibr=ThisLibr->next; /* Next library in list */
448 return 0; /* Failure - symbol not found in any library */
451 /* buildlibraryindex - build an in-memory cache of the symbols contained in
455 int buildlibraryindex()
459 char relfil[NINPUT+2], *str, *path;
460 char buf[NINPUT+2], c;
461 char symname[NINPUT+2];
463 pmlibrarysymbol ThisSym;
467 /* Iterate through all library files */
468 /*1*/ for (lbnh=lbnhead; lbnh; lbnh=lbnh->next) {
469 libfp = fopen( lbnh->libspc, "r" );
474 * Read in a line from the library file.
475 * This is the relative file specification
476 * for a .REL file in this library.
479 /*2*/ while (fgets(relfil, NINPUT, libfp) != NULL) {
480 relfil[NINPUT+1] = '\0';
481 relfil[strlen(relfil) - 1] = '\0';
483 str = (char *)malloc(strlen(path)+strlen(relfil)+6);
488 if (str[strlen(str)-1] != '/') {
491 if (str[strlen(str)-1] != '\\') {
495 if (str[strlen(str)-1] != '\\') {
501 str = (char *)malloc(strlen(relfil) + 5);
505 if (relfil[0] == '/') {
507 if (relfil[0] == '\\') {
510 if (relfil[0] == '\\') {
512 strcat(str,relfil+1);
516 if(strchr(str,FSEPX) == NULL) {
518 sprintf(&str[strlen(str)], "%co", FSEPX);
520 sprintf(&str[strlen(str)], "%crel", FSEPX);
523 /*3*/ if ((fp = fopen(str, "r")) != NULL) {
525 /* Opened OK - create a new libraryfile object for it */
526 This->next = (pmlibraryfile)malloc( sizeof( mlibraryfile ));
527 if (This->next == NULL) {
528 printf("panic: cant allocate memory.\n");
536 strcpy( This->filename, str );
538 ThisSym = This->symbols = (pmlibrarysymbol)malloc( sizeof(mlibrarysymbol));
539 ThisSym->next = NULL;
542 * Read in the object file. Look for lines that
543 * begin with "S" and end with "D". These are
544 * symbol table definitions. If we find one, see
545 * if it is our symbol. Make sure we only read in
546 * our object file and don't go into the next one.
549 /*4*/ while (fgets(buf, NINPUT, fp) != NULL) {
551 buf[NINPUT+1] = '\0';
552 buf[strlen(buf) - 1] = '\0';
555 * Skip everything that's not a symbol record.
561 * When a 'T line' is found terminate file scan.
562 * All 'S line's preceed 'T line's in .REL files.
567 sscanf(buf, "S %s %c", symname, &c);
569 /* If it's an actual symbol, record it */
570 /*5*/ if (c == 'D') {
571 ThisSym->next = (pmlibrarysymbol)malloc(sizeof(mlibrarysymbol));
572 ThisSym=ThisSym->next;
573 if (ThisSym == NULL) {
574 printf("panic: cant allocate memory.\n");
580 strcpy(This->relfil,relfil);
581 strcpy(ThisSym->name, symname);
582 This->libspc = lbnh->libspc;
584 } /* Closes while - read object file */
586 } /* Closes if object file opened OK */
587 } /* Ends while - processing all in libr */
589 } /* Ends good open of libr file */
601 struct lbfile *lbfh, *lbf;
602 char relfil[NINPUT+2];
604 char symname[NINPUT];
609 * Search through every library in the linked list "lbnhead".
612 /*1*/ for (lbnh=lbnhead; lbnh; lbnh=lbnh->next) {
613 if ((libfp = fopen(lbnh->libspc, "r")) == NULL) {
614 fprintf(stderr, "Cannot open library file %s\n",
621 * Read in a line from the library file.
622 * This is the relative file specification
623 * for a .REL file in this library.
626 /*2*/ while (fgets(relfil, NINPUT, libfp) != NULL) {
627 relfil[NINPUT+1] = '\0';
628 relfil[strlen(relfil) - 1] = '\0';
630 str = (char *) new (strlen(path)+strlen(relfil)+6);
635 if (str[strlen(str)-1] != '/') {
638 if (str[strlen(str)-1] != '\\') {
642 if (str[strlen(str)-1] != '\\') {
648 str = (char *) new (strlen(relfil) + 5);
652 if (relfil[0] == '/') {
654 if (relfil[0] == '\\') {
657 if (relfil[0] == '\\') {
659 strcat(str,relfil+1);
663 if(strchr(str,FSEPX) == NULL) {
665 sprintf(&str[strlen(str)], "%co", FSEPX);
667 sprintf(&str[strlen(str)], "%crel", FSEPX);
670 /*3*/ if ((fp = fopen(str, "r")) != NULL) {
673 * Read in the object file. Look for lines that
674 * begin with "S" and end with "D". These are
675 * symbol table definitions. If we find one, see
676 * if it is our symbol. Make sure we only read in
677 * our object file and don't go into the next one.
680 /*4*/ while (fgets(buf, NINPUT, fp) != NULL) {
682 buf[NINPUT+1] = '\0';
683 buf[strlen(buf) - 1] = '\0';
686 * Skip everything that's not a symbol record.
692 * When a 'T line' is found terminate file scan.
693 * All 'S line's preceed 'T line's in .REL files.
698 sscanf(buf, "S %s %c", symname, &c);
701 * If we find a symbol definition for the
702 * symbol we're looking for, load in the
703 * file and add it to lbfhead so it gets
704 * loaded on pass number 2.
706 /*5*/ if (strncmp(symname, name, NCPS) == 0 && c == 'D') {
708 lbfh = (struct lbfile *) new (sizeof(struct lbfile));
709 if (lbfhead == NULL) {
717 lbfh->libspc = lbnh->libspc;
719 lbfh->relfil = (char *) new (strlen(relfil) + 1);
720 strcpy(lbfh->relfil,relfil);
738 #endif /* INDEXLIB */
740 /*)Function VOID library()
742 * The function library() links all the library object files
743 * contained in the lbfile structures.
746 * lbfile *lbfh pointer to lbfile structure
749 * lbfile *lbfhead pointer to first lbfile structure
752 * VOID loadfile lklibr.c
755 * Links all files contained in the lbfile structures.
763 for (lbfh=lbfhead; lbfh; lbfh=lbfh->next) {
764 loadfile(lbfh->filspc);
768 /*)Function VOID loadfile(filspc)
770 * char *filspc library object file specification
772 * The function loadfile() links the library object module.
775 * FILE *fp file handle
776 * int i input line length
777 * char str[] file input line
780 * char *ip pointer to linker input string
783 * int fclose() c_library
784 * int fgets() c_library
785 * FILE * fopen() c_library
786 * VOID link() lkmain.c
787 * int strlen() c_library
790 * If file exists it is linked.
801 if ((fp = fopen(filspc,"r")) != NULL) {
802 while (fgets(str, NINPUT, fp) != NULL) {
803 str[NINPUT+1] = '\0';