4 * (C) Copyright 1989-1995
11 * With contributions for the
12 * object libraries from
14 * kenh@cmf.nrl.navy.mil
18 #if defined(__APPLE__) && defined(__MACH__)
19 #include <sys/types.h>
20 #include <sys/malloc.h>
30 * The module lklibr.c contains the functions which
31 * (1) specify the path(s) to library files [.LIB]
32 * (2) specify the library file(s) [.LIB] to search
33 * (3) search the library files for specific symbols
34 * and link the module containing this symbol
36 * lklibr.c contains the following functions:
47 /*)Function VOID addpath()
49 * The function addpath() creates a linked structure containing
50 * the paths to various object module library files.
53 * lbpath *lbph pointer to new path structure
54 * lbpath *lbp temporary pointer
57 * lbpath *lbphead The pointer to the first
61 * char getnb() lklex.c
62 * VOID * new() lksym.c
63 * int strlen() c_library
64 * char * strcpy() c_library
65 * VOID unget() lklex.c
68 * An lbpath structure may be created.
74 struct lbpath *lbph, *lbp;
76 lbph = (struct lbpath *) new (sizeof(struct lbpath));
77 if (lbphead == NULL) {
86 lbph->path = (char *) new (strlen(ip)+1);
87 strcpy(lbph->path, ip);
90 /*)Function VOID addlib()
92 * The function addlib() tests for the existance of a
93 * library path structure to determine the method of
94 * adding this library file to the library search structure.
96 * This function calls the function addfile() to actually
97 * add the library file to the search list.
100 * lbpath *lbph pointer to path structure
103 * lbpath *lbphead The pointer to the first
107 * VOID addfile() lklibr.c
108 * char getnb() lklex.c
109 * VOID unget() lklex.c
112 * The function addfile() may add the file to
113 * the library search list.
123 if (lbphead == NULL) {
127 for (lbph=lbphead; lbph; lbph=lbph->next) {
128 addfile(lbph->path,ip);
132 /*)Function VOID addfile(path,libfil)
134 * char *path library path specification
135 * char *libfil library file specification
137 * The function addfile() searches for the library file
138 * by concatenating the path and libfil specifications.
139 * if the library is found, an lbname structure is created
140 * and linked to any previously defined structures. This
141 * linked list is used by the function fndsym() to attempt
142 * to find any undefined symbols.
144 * The function does not give report an error on invalid
145 * path / file specifications or if the file is not found.
148 * lbname *lbnh pointer to new name structure
149 * lbname *lbn temporary pointer
152 * lbname *lbnhead The pointer to the first
156 * char getnb() lklex.c
157 * VOID * new() lksym.c
158 * int strlen() c_library
159 * char * strcpy() c_library
160 * VOID unget() lklex.c
163 * An lbname structure may be created.
173 struct lbname *lbnh, *lbn;
175 if ((path != NULL) && (strchr(libfil,':') == NULL)){
176 str = (char *) new (strlen(path) + strlen(libfil) + 6);
179 if (str[strlen(str)-1] != '/') {
184 str = (char *) new (strlen(libfil) + 5);
187 if (libfil[0] == '/') { libfil++; }
190 if(strchr(libfil,FSEPX) == NULL) {
191 sprintf(&str[strlen(str)], "%clib", FSEPX);
193 if ((fp = fopen(str, "r")) != NULL) {
195 lbnh = (struct lbname *) new (sizeof(struct lbname));
196 if (lbnhead == NULL) {
204 if ((path != NULL) && (strchr(libfil,':') == NULL)){
207 lbnh->libfil = (char *) new (strlen(libfil) + 1);
208 strcpy(lbnh->libfil,libfil);
210 fprintf(stderr,"library file %s\n",str);
216 /*)Function VOID search()
218 * The function search() looks through all the symbol tables
219 * at the end of pass 1. If any undefined symbols are found
220 * then the function fndsym() is called. Function fndsym()
221 * searches any specified library files to automagically
222 * import the object modules containing the needed symbol.
224 * After a symbol is found and imported by the function
225 * fndsym() the symbol tables are again searched. The
226 * symbol tables are search until no more symbols can be
227 * resolved within the library files. This ensures that
228 * back references from one library module to another are
232 * int i temporary counter
233 * sym *sp pointer to a symbol structure
234 * int symfnd found a symbol flag
237 * sym *symhash[] array of pointers to symbol tables
240 * int fndsym() lklibr.c
243 * If a symbol is found then the library object module
244 * containing the symbol will be imported and linked.
250 register struct sym *sp;
251 register int i,symfnd;
254 * Look for undefined symbols. Keep
255 * searching until no more symbols are resolved.
261 * Look through all the symbols
263 for (i=0; i<NHASH; ++i) {
266 /* If we find an undefined symbol
267 * (one where S_DEF is not set), then
268 * try looking for it. If we find it
269 * in any of the libraries then
270 * increment symfnd. This will force
271 * another pass of symbol searching and
272 * make sure that back references work.
274 if ((sp->s_type & S_DEF) == 0) {
275 if (fndsym(sp->s_id)) {
285 /*)Function VOID fndsym(name)
287 * char *name symbol name to find
289 * The function fndsym() searches through all combinations of the
290 * library path specifications (input by the -k option) and the
291 * library file specifications (input by the -l option) that
292 * lead to an existing file.
294 * The file specicifation may be formed in one of two ways:
296 * (1) If the library file contained an absolute
297 * path/file specification then this becomes filspc.
300 * (2) If the library file contains a relative path/file
301 * specification then the concatenation of the path
302 * and this file specification becomes filspc.
305 * The structure lbfile is created for the first library
306 * object file which contains the definition for the
307 * specified undefined symbol.
309 * If the library file [.LIB] contains file specifications for
310 * non existant files, no errors are returned.
313 * char buf[] [.REL] file input line
314 * char c [.REL] file input character
315 * FILE *fp file handle for object file
316 * lbfile *lbf temporary pointer
317 * lbfile *lbfh pointer to lbfile structure
318 * FILE *libfp file handle for library file
319 * lbname *lbnh pointer to lbname structure
320 * char *path file specification path
321 * char relfil[] [.REL] file specification
322 * char *str combined path and file specification
323 * char symname[] [.REL] file symbol string
326 * lbname *lbnhead The pointer to the first
328 * lbfile *lbfhead The pointer to the first
332 * int fclose() c_library
333 * int fgets() c_library
334 * FILE *fopen() c_library
335 * VOID free() c_library
336 * char getnb() lklex.c
337 * VOID lkexit() lkmain.c
338 * VOID loadfile() lklibr.c
339 * VOID * new() lksym.c
340 * char * sprintf() c_library
341 * int sscanf() c_library
342 * char * strcat() c_library
343 * char * strchr() c_library
344 * char * strcpy() c_library
345 * int strlen() c_library
346 * int strncmp() c_library
347 * VOID unget() lklex.c
350 * If the symbol is found then a new lbfile structure
351 * is created and added to the linked list of lbfile
352 * structures. The file containing the found symbol
362 struct lbfile *lbfh, *lbf;
363 char relfil[NINPUT+2];
365 char symname[NINPUT];
370 * Search through every library in the linked list "lbnhead".
373 /*1*/ for (lbnh=lbnhead; lbnh; lbnh=lbnh->next) {
374 if ((libfp = fopen(lbnh->libspc, "r")) == NULL) {
375 fprintf(stderr, "Cannot open library file %s\n",
382 * Read in a line from the library file.
383 * This is the relative file specification
384 * for a .REL file in this library.
387 /*2*/ while (fgets(relfil, NINPUT, libfp) != NULL) {
388 relfil[NINPUT+1] = '\0';
391 str = (char *) new (strlen(path)+strlen(relfil)+6);
394 if (str[strlen(str)-1] != '/') {
399 str = (char *) new (strlen(relfil) + 5);
401 if (relfil[0] == '\\') {
402 strcat(str,relfil+1);
406 if(strchr(relfil,FSEPX) == NULL) {
407 sprintf(&str[strlen(str)], "%crel", FSEPX);
409 /*3*/ if ((fp = fopen(str, "r")) != NULL) {
412 * Read in the object file. Look for lines that
413 * begin with "S" and end with "D". These are
414 * symbol table definitions. If we find one, see
415 * if it is our symbol. Make sure we only read in
416 * our object file and don't go into the next one.
419 /*4*/ while (fgets(buf, NINPUT, fp) != NULL) {
421 buf[NINPUT+1] = '\0';
425 * Skip everything that's not a symbol record.
431 * When a 'T line' is found terminate file scan.
432 * All 'S line's preceed 'T line's in .REL files.
437 sscanf(buf, "S %s %c", symname, &c);
440 * If we find a symbol definition for the
441 * symbol we're looking for, load in the
442 * file and add it to lbfhead so it gets
443 * loaded on pass number 2.
445 /*5*/ if (strncmp(symname, name, NCPS) == 0 && c == 'D') {
447 lbfh = (struct lbfile *) new (sizeof(struct lbfile));
448 if (lbfhead == NULL) {
456 lbfh->libspc = lbnh->libspc;
458 lbfh->relfil = (char *) new (strlen(relfil) + 1);
459 strcpy(lbfh->relfil,relfil);
462 /* if cdb information required & cdb file present */
464 FILE *xfp = afile(str,"cdb",0);
486 /*)Function VOID library()
488 * The function library() links all the library object files
489 * contained in the lbfile structures.
492 * lbfile *lbfh pointer to lbfile structure
495 * lbfile *lbfhead pointer to first lbfile structure
498 * VOID loadfile lklibr.c
501 * Links all files contained in the lbfile structures.
509 for (lbfh=lbfhead; lbfh; lbfh=lbfh->next) {
510 loadfile(lbfh->filspc);
514 /*)Function VOID loadfile(filspc)
516 * char *filspc library object file specification
518 * The function loadfile() links the library object module.
521 * FILE *fp file handle
522 * int i input line length
523 * char str[] file input line
526 * char *ip pointer to linker input string
529 * int fclose() c_library
530 * int fgets() c_library
531 * FILE * fopen() c_library
532 * VOID link_main() lkmain.c
533 * int strlen() c_library
536 * If file exists it is linked.
546 if ((fp = fopen(filspc,"r")) != NULL) {
547 while (fgets(str, NINPUT, fp) != NULL) {
548 str[NINPUT+1] = '\0';