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;
63 char filename[FILSPC];
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 */
403 int fndsym( char *name )
405 struct lbfile *lbfh, *lbf;
406 pmlibraryfile ThisLibr;
407 pmlibrarysymbol ThisSym = NULL;
409 /* Build the index if this is the first call to fndsym */
413 /* Iterate through all library object files */
414 ThisLibr = libr.next;
417 /* Iterate through all symbols in an object file */
418 ThisSym = ThisLibr->symbols->next;
421 if (!strcmp(ThisSym->name, name)) {
422 if (!ThisLibr->loaded) {
423 /* Object file is not loaded - add it to the list */
424 lbfh = (struct lbfile *) new (sizeof(struct lbfile));
425 if (lbfhead == NULL) {
433 lbfh->libspc = ThisLibr->libspc;
434 lbfh->filspc = ThisLibr->str;
435 lbfh->relfil = (char *) new (strlen(ThisLibr->relfil) + 1);
436 strcpy(lbfh->relfil,ThisLibr->relfil);
437 loadfile(lbfh->filspc);
440 return (1); /* Found the symbol, return */
442 ThisSym=ThisSym->next; /* Next sym in library */
444 ThisLibr=ThisLibr->next; /* Next library in list */
446 return 0; /* Failure - symbol not found in any library */
449 /* buildlibraryindex - build an in-memory cache of the symbols contained in
453 int buildlibraryindex()
457 char relfil[NINPUT+2], *str, *path;
458 char buf[NINPUT+2], c;
459 char symname[NINPUT+2];
461 pmlibrarysymbol ThisSym;
465 /* Iterate through all library files */
466 /*1*/ for (lbnh=lbnhead; lbnh; lbnh=lbnh->next) {
467 libfp = fopen( lbnh->libspc, "r" );
472 * Read in a line from the library file.
473 * This is the relative file specification
474 * for a .REL file in this library.
477 /*2*/ while (fgets(relfil, NINPUT, libfp) != NULL) {
478 relfil[NINPUT+1] = '\0';
479 relfil[strlen(relfil) - 1] = '\0';
481 str = (char *)new(strlen(path)+strlen(relfil)+6);
486 if (str[strlen(str)-1] != '/') {
489 if (str[strlen(str)-1] != '\\') {
493 if (str[strlen(str)-1] != '\\') {
499 str = (char *)new(strlen(relfil) + 5);
503 if (relfil[0] == '/') {
505 if (relfil[0] == '\\') {
508 if (relfil[0] == '\\') {
510 strcat(str,relfil+1);
514 if(strchr(str,FSEPX) == NULL) {
516 sprintf(&str[strlen(str)], "%co", FSEPX);
518 sprintf(&str[strlen(str)], "%crel", FSEPX);
521 /*3*/ if ((fp = fopen(str, "r")) != NULL) {
523 /* Opened OK - create a new libraryfile object for it */
524 This->next = (pmlibraryfile)new( sizeof( mlibraryfile ));
525 if (This->next == NULL) {
526 printf("panic: cant allocate memory.\n");
534 strcpy( This->filename, str );
536 ThisSym = This->symbols = (pmlibrarysymbol)malloc( sizeof(mlibrarysymbol));
537 ThisSym->next = NULL;
540 * Read in the object file. Look for lines that
541 * begin with "S" and end with "D". These are
542 * symbol table definitions. If we find one, see
543 * if it is our symbol. Make sure we only read in
544 * our object file and don't go into the next one.
547 /*4*/ while (fgets(buf, NINPUT, fp) != NULL) {
549 buf[NINPUT+1] = '\0';
550 buf[strlen(buf) - 1] = '\0';
553 * Skip everything that's not a symbol record.
559 * When a 'T line' is found terminate file scan.
560 * All 'S line's preceed 'T line's in .REL files.
565 sscanf(buf, "S %s %c", symname, &c);
567 /* If it's an actual symbol, record it */
568 /*5*/ if (c == 'D') {
569 ThisSym->next = (pmlibrarysymbol)malloc(sizeof(mlibrarysymbol));
570 ThisSym=ThisSym->next;
571 if (ThisSym == NULL) {
572 printf("panic: cant allocate memory.\n");
578 strcpy(This->relfil,relfil);
579 strcpy(ThisSym->name, symname);
580 This->libspc = lbnh->libspc;
582 } /* Closes while - read object file */
584 } /* Closes if object file opened OK */
585 } /* Ends while - processing all in libr */
587 } /* Ends good open of libr file */
599 struct lbfile *lbfh, *lbf;
600 char relfil[NINPUT+2];
602 char symname[NINPUT];
607 * Search through every library in the linked list "lbnhead".
610 /*1*/ for (lbnh=lbnhead; lbnh; lbnh=lbnh->next) {
611 if ((libfp = fopen(lbnh->libspc, "r")) == NULL) {
612 fprintf(stderr, "Cannot open library file %s\n",
619 * Read in a line from the library file.
620 * This is the relative file specification
621 * for a .REL file in this library.
624 /*2*/ while (fgets(relfil, NINPUT, libfp) != NULL) {
625 relfil[NINPUT+1] = '\0';
626 relfil[strlen(relfil) - 1] = '\0';
628 str = (char *) new (strlen(path)+strlen(relfil)+6);
633 if (str[strlen(str)-1] != '/') {
636 if (str[strlen(str)-1] != '\\') {
640 if (str[strlen(str)-1] != '\\') {
646 str = (char *) new (strlen(relfil) + 5);
650 if (relfil[0] == '/') {
652 if (relfil[0] == '\\') {
655 if (relfil[0] == '\\') {
657 strcat(str,relfil+1);
661 if(strchr(str,FSEPX) == NULL) {
663 sprintf(&str[strlen(str)], "%co", FSEPX);
665 sprintf(&str[strlen(str)], "%crel", FSEPX);
668 /*3*/ if ((fp = fopen(str, "r")) != NULL) {
671 * Read in the object file. Look for lines that
672 * begin with "S" and end with "D". These are
673 * symbol table definitions. If we find one, see
674 * if it is our symbol. Make sure we only read in
675 * our object file and don't go into the next one.
678 /*4*/ while (fgets(buf, NINPUT, fp) != NULL) {
680 buf[NINPUT+1] = '\0';
681 buf[strlen(buf) - 1] = '\0';
684 * Skip everything that's not a symbol record.
690 * When a 'T line' is found terminate file scan.
691 * All 'S line's preceed 'T line's in .REL files.
696 sscanf(buf, "S %s %c", symname, &c);
699 * If we find a symbol definition for the
700 * symbol we're looking for, load in the
701 * file and add it to lbfhead so it gets
702 * loaded on pass number 2.
704 /*5*/ if (strncmp(symname, name, NCPS) == 0 && c == 'D') {
706 lbfh = (struct lbfile *) new (sizeof(struct lbfile));
707 if (lbfhead == NULL) {
715 lbfh->libspc = lbnh->libspc;
717 lbfh->relfil = (char *) new (strlen(relfil) + 1);
718 strcpy(lbfh->relfil,relfil);
736 #endif /* INDEXLIB */
738 /*)Function VOID library()
740 * The function library() links all the library object files
741 * contained in the lbfile structures.
744 * lbfile *lbfh pointer to lbfile structure
747 * lbfile *lbfhead pointer to first lbfile structure
750 * VOID loadfile lklibr.c
753 * Links all files contained in the lbfile structures.
761 for (lbfh=lbfhead; lbfh; lbfh=lbfh->next) {
762 loadfile(lbfh->filspc);
766 /*)Function VOID loadfile(filspc)
768 * char *filspc library object file specification
770 * The function loadfile() links the library object module.
773 * FILE *fp file handle
774 * int i input line length
775 * char str[] file input line
778 * char *ip pointer to linker input string
781 * int fclose() c_library
782 * int fgets() c_library
783 * FILE * fopen() c_library
784 * VOID link() lkmain.c
785 * int strlen() c_library
788 * If file exists it is linked.
799 if ((fp = fopen(filspc,"r")) != NULL) {
800 while (fgets(str, NINPUT, fp) != NULL) {
801 str[NINPUT+1] = '\0';