4 * (C) Copyright 1989-1995
11 * With contributions for the
12 * object libraries from
14 * kenh@cmf.nrl.navy.mil
25 * The module lklibr.c contains the functions which
26 * (1) specify the path(s) to library files [.LIB]
27 * (2) specify the library file(s) [.LIB] to search
28 * (3) search the library files for specific symbols
29 * and link the module containing this symbol
31 * lklibr.c contains the following functions:
42 /*)Function VOID addpath()
44 * The function addpath() creates a linked structure containing
45 * the paths to various object module library files.
48 * lbpath *lbph pointer to new path structure
49 * lbpath *lbp temporary pointer
52 * lbpath *lbphead The pointer to the first
56 * char getnb() lklex.c
57 * VOID * new() lksym.c
58 * int strlen() c_library
59 * char * strcpy() c_library
60 * VOID unget() lklex.c
63 * An lbpath structure may be created.
69 struct lbpath *lbph, *lbp;
71 lbph = (struct lbpath *) new (sizeof(struct lbpath));
72 if (lbphead == NULL) {
81 lbph->path = (char *) new (strlen(ip)+1);
82 strcpy(lbph->path, ip);
85 /*)Function VOID addlib()
87 * The function addlib() tests for the existance of a
88 * library path structure to determine the method of
89 * adding this library file to the library search structure.
91 * This function calls the function addfile() to actually
92 * add the library file to the search list.
95 * lbpath *lbph pointer to path structure
98 * lbpath *lbphead The pointer to the first
102 * VOID addfile() lklibr.c
103 * char getnb() lklex.c
104 * VOID unget() lklex.c
107 * The function addfile() may add the file to
108 * the library search list.
118 if (lbphead == NULL) {
122 for (lbph=lbphead; lbph; lbph=lbph->next) {
123 addfile(lbph->path,ip);
127 /*)Function VOID addfile(path,libfil)
129 * char *path library path specification
130 * char *libfil library file specification
132 * The function addfile() searches for the library file
133 * by concatenating the path and libfil specifications.
134 * if the library is found, an lbname structure is created
135 * and linked to any previously defined structures. This
136 * linked list is used by the function fndsym() to attempt
137 * to find any undefined symbols.
139 * The function does not give report an error on invalid
140 * path / file specifications or if the file is not found.
143 * lbname *lbnh pointer to new name structure
144 * lbname *lbn temporary pointer
147 * lbname *lbnhead The pointer to the first
151 * char getnb() lklex.c
152 * VOID * new() lksym.c
153 * int strlen() c_library
154 * char * strcpy() c_library
155 * VOID unget() lklex.c
158 * An lbname structure may be created.
168 struct lbname *lbnh, *lbn;
170 if ((path != NULL) && (strchr(libfil,':') == NULL)){
171 str = (char *) new (strlen(path) + strlen(libfil) + 6);
174 if (str[strlen(str)-1] != '/') {
179 str = (char *) new (strlen(libfil) + 5);
182 if (libfil[0] == '/') { libfil++; }
185 if(strchr(libfil,FSEPX) == NULL) {
186 sprintf(&str[strlen(str)], "%clib", FSEPX);
188 if ((fp = fopen(str, "r")) != NULL) {
190 lbnh = (struct lbname *) new (sizeof(struct lbname));
191 if (lbnhead == NULL) {
199 if ((path != NULL) && (strchr(libfil,':') == NULL)){
202 lbnh->libfil = (char *) new (strlen(libfil) + 1);
203 strcpy(lbnh->libfil,libfil);
205 fprintf(stderr,"library file %s\n",str);
211 /*)Function VOID search()
213 * The function search() looks through all the symbol tables
214 * at the end of pass 1. If any undefined symbols are found
215 * then the function fndsym() is called. Function fndsym()
216 * searches any specified library files to automagically
217 * import the object modules containing the needed symbol.
219 * After a symbol is found and imported by the function
220 * fndsym() the symbol tables are again searched. The
221 * symbol tables are search until no more symbols can be
222 * resolved within the library files. This ensures that
223 * back references from one library module to another are
227 * int i temporary counter
228 * sym *sp pointer to a symbol structure
229 * int symfnd found a symbol flag
232 * sym *symhash[] array of pointers to symbol tables
235 * int fndsym() lklibr.c
238 * If a symbol is found then the library object module
239 * containing the symbol will be imported and linked.
245 register struct sym *sp;
246 register int i,symfnd;
249 * Look for undefined symbols. Keep
250 * searching until no more symbols are resolved.
256 * Look through all the symbols
258 for (i=0; i<NHASH; ++i) {
261 /* If we find an undefined symbol
262 * (one where S_DEF is not set), then
263 * try looking for it. If we find it
264 * in any of the libraries then
265 * increment symfnd. This will force
266 * another pass of symbol searching and
267 * make sure that back references work.
269 if ((sp->s_type & S_DEF) == 0) {
270 if (fndsym(sp->s_id)) {
280 /*)Function VOID fndsym(name)
282 * char *name symbol name to find
284 * The function fndsym() searches through all combinations of the
285 * library path specifications (input by the -k option) and the
286 * library file specifications (input by the -l option) that
287 * lead to an existing file.
289 * The file specicifation may be formed in one of two ways:
291 * (1) If the library file contained an absolute
292 * path/file specification then this becomes filspc.
295 * (2) If the library file contains a relative path/file
296 * specification then the concatenation of the path
297 * and this file specification becomes filspc.
300 * The structure lbfile is created for the first library
301 * object file which contains the definition for the
302 * specified undefined symbol.
304 * If the library file [.LIB] contains file specifications for
305 * non existant files, no errors are returned.
308 * char buf[] [.REL] file input line
309 * char c [.REL] file input character
310 * FILE *fp file handle for object file
311 * lbfile *lbf temporary pointer
312 * lbfile *lbfh pointer to lbfile structure
313 * FILE *libfp file handle for library file
314 * lbname *lbnh pointer to lbname structure
315 * char *path file specification path
316 * char relfil[] [.REL] file specification
317 * char *str combined path and file specification
318 * char symname[] [.REL] file symbol string
321 * lbname *lbnhead The pointer to the first
323 * lbfile *lbfhead The pointer to the first
327 * int fclose() c_library
328 * int fgets() c_library
329 * FILE *fopen() c_library
330 * VOID free() c_library
331 * char getnb() lklex.c
332 * VOID lkexit() lkmain.c
333 * VOID loadfile() lklibr.c
334 * VOID * new() lksym.c
335 * char * sprintf() c_library
336 * int sscanf() c_library
337 * char * strcat() c_library
338 * char * strchr() c_library
339 * char * strcpy() c_library
340 * int strlen() c_library
341 * int strncmp() c_library
342 * VOID unget() lklex.c
345 * If the symbol is found then a new lbfile structure
346 * is created and added to the linked list of lbfile
347 * structures. The file containing the found symbol
357 struct lbfile *lbfh, *lbf;
358 char relfil[NINPUT+2];
360 char symname[NINPUT];
365 * Search through every library in the linked list "lbnhead".
368 /*1*/ for (lbnh=lbnhead; lbnh; lbnh=lbnh->next) {
369 if ((libfp = fopen(lbnh->libspc, "r")) == NULL) {
370 fprintf(stderr, "Cannot open library file %s\n",
377 * Read in a line from the library file.
378 * This is the relative file specification
379 * for a .REL file in this library.
382 /*2*/ while (fgets(relfil, NINPUT, libfp) != NULL) {
383 relfil[NINPUT+1] = '\0';
386 str = (char *) new (strlen(path)+strlen(relfil)+6);
389 if (str[strlen(str)-1] != '/') {
394 str = (char *) new (strlen(relfil) + 5);
396 if (relfil[0] == '\\') {
397 strcat(str,relfil+1);
401 if(strchr(relfil,FSEPX) == NULL) {
402 sprintf(&str[strlen(str)], "%crel", FSEPX);
404 /*3*/ if ((fp = fopen(str, "r")) != NULL) {
407 * Read in the object file. Look for lines that
408 * begin with "S" and end with "D". These are
409 * symbol table definitions. If we find one, see
410 * if it is our symbol. Make sure we only read in
411 * our object file and don't go into the next one.
414 /*4*/ while (fgets(buf, NINPUT, fp) != NULL) {
416 buf[NINPUT+1] = '\0';
420 * Skip everything that's not a symbol record.
426 * When a 'T line' is found terminate file scan.
427 * All 'S line's preceed 'T line's in .REL files.
432 sscanf(buf, "S %s %c", symname, &c);
435 * If we find a symbol definition for the
436 * symbol we're looking for, load in the
437 * file and add it to lbfhead so it gets
438 * loaded on pass number 2.
440 /*5*/ if (strncmp(symname, name, NCPS) == 0 && c == 'D') {
442 lbfh = (struct lbfile *) new (sizeof(struct lbfile));
443 if (lbfhead == NULL) {
451 lbfh->libspc = lbnh->libspc;
453 lbfh->relfil = (char *) new (strlen(relfil) + 1);
454 strcpy(lbfh->relfil,relfil);
457 /* if cdb information required & cdb file present */
459 FILE *xfp = afile(str,"cdb",0);
481 /*)Function VOID library()
483 * The function library() links all the library object files
484 * contained in the lbfile structures.
487 * lbfile *lbfh pointer to lbfile structure
490 * lbfile *lbfhead pointer to first lbfile structure
493 * VOID loadfile lklibr.c
496 * Links all files contained in the lbfile structures.
504 for (lbfh=lbfhead; lbfh; lbfh=lbfh->next) {
505 loadfile(lbfh->filspc);
509 /*)Function VOID loadfile(filspc)
511 * char *filspc library object file specification
513 * The function loadfile() links the library object module.
516 * FILE *fp file handle
517 * int i input line length
518 * char str[] file input line
521 * char *ip pointer to linker input string
524 * int fclose() c_library
525 * int fgets() c_library
526 * FILE * fopen() c_library
527 * VOID link_main() lkmain.c
528 * int strlen() c_library
531 * If file exists it is linked.
541 if ((fp = fopen(filspc,"r")) != NULL) {
542 while (fgets(str, NINPUT, fp) != NULL) {
543 str[NINPUT+1] = '\0';