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);
215 /*)Function VOID search()
217 * The function search() looks through all the symbol tables
218 * at the end of pass 1. If any undefined symbols are found
219 * then the function fndsym() is called. Function fndsym()
220 * searches any specified library files to automagically
221 * import the object modules containing the needed symbol.
223 * After a symbol is found and imported by the function
224 * fndsym() the symbol tables are again searched. The
225 * symbol tables are search until no more symbols can be
226 * resolved within the library files. This ensures that
227 * back references from one library module to another are
231 * int i temporary counter
232 * sym *sp pointer to a symbol structure
233 * int symfnd found a symbol flag
236 * sym *symhash[] array of pointers to symbol tables
239 * int fndsym() lklibr.c
242 * If a symbol is found then the library object module
243 * containing the symbol will be imported and linked.
249 register struct sym *sp;
250 register int i,symfnd;
253 * Look for undefined symbols. Keep
254 * searching until no more symbols are resolved.
260 * Look through all the symbols
262 for (i=0; i<NHASH; ++i) {
265 /* If we find an undefined symbol
266 * (one where S_DEF is not set), then
267 * try looking for it. If we find it
268 * in any of the libraries then
269 * increment symfnd. This will force
270 * another pass of symbol searching and
271 * make sure that back references work.
273 if ((sp->s_type & S_DEF) == 0) {
274 if (fndsym(sp->s_id)) {
284 /*)Function VOID fndsym(name)
286 * char *name symbol name to find
288 * The function fndsym() searches through all combinations of the
289 * library path specifications (input by the -k option) and the
290 * library file specifications (input by the -l option) that
291 * lead to an existing file.
293 * The file specicifation may be formed in one of two ways:
295 * (1) If the library file contained an absolute
296 * path/file specification then this becomes filspc.
299 * (2) If the library file contains a relative path/file
300 * specification then the concatenation of the path
301 * and this file specification becomes filspc.
304 * The structure lbfile is created for the first library
305 * object file which contains the definition for the
306 * specified undefined symbol.
308 * If the library file [.LIB] contains file specifications for
309 * non existant files, no errors are returned.
312 * char buf[] [.REL] file input line
313 * char c [.REL] file input character
314 * FILE *fp file handle for object file
315 * lbfile *lbf temporary pointer
316 * lbfile *lbfh pointer to lbfile structure
317 * FILE *libfp file handle for library file
318 * lbname *lbnh pointer to lbname structure
319 * char *path file specification path
320 * char relfil[] [.REL] file specification
321 * char *str combined path and file specification
322 * char symname[] [.REL] file symbol string
325 * lbname *lbnhead The pointer to the first
327 * lbfile *lbfhead The pointer to the first
331 * int fclose() c_library
332 * int fgets() c_library
333 * FILE *fopen() c_library
334 * VOID free() c_library
335 * char getnb() lklex.c
336 * VOID lkexit() lkmain.c
337 * VOID loadfile() lklibr.c
338 * VOID * new() lksym.c
339 * char * sprintf() c_library
340 * int sscanf() c_library
341 * char * strcat() c_library
342 * char * strchr() c_library
343 * char * strcpy() c_library
344 * int strlen() c_library
345 * int strncmp() c_library
346 * VOID unget() lklex.c
349 * If the symbol is found then a new lbfile structure
350 * is created and added to the linked list of lbfile
351 * structures. The file containing the found symbol
361 struct lbfile *lbfh, *lbf;
362 char relfil[NINPUT+2];
364 char symname[NINPUT];
369 * Search through every library in the linked list "lbnhead".
372 /*1*/ for (lbnh=lbnhead; lbnh; lbnh=lbnh->next) {
373 if ((libfp = fopen(lbnh->libspc, "r")) == NULL) {
374 fprintf(stderr, "Cannot open library file %s\n",
381 * Read in a line from the library file.
382 * This is the relative file specification
383 * for a .REL file in this library.
386 /*2*/ while (fgets(relfil, NINPUT, libfp) != NULL) {
387 relfil[NINPUT+1] = '\0';
390 str = (char *) new (strlen(path)+strlen(relfil)+6);
393 if (str[strlen(str)-1] != '/') {
398 str = (char *) new (strlen(relfil) + 5);
400 if (relfil[0] == '\\') {
401 strcat(str,relfil+1);
405 if(strchr(relfil,FSEPX) == NULL) {
406 sprintf(&str[strlen(str)], "%crel", FSEPX);
408 /*3*/ if ((fp = fopen(str, "r")) != NULL) {
411 * Read in the object file. Look for lines that
412 * begin with "S" and end with "D". These are
413 * symbol table definitions. If we find one, see
414 * if it is our symbol. Make sure we only read in
415 * our object file and don't go into the next one.
418 /*4*/ while (fgets(buf, NINPUT, fp) != NULL) {
420 buf[NINPUT+1] = '\0';
424 * Skip everything that's not a symbol record.
430 * When a 'T line' is found terminate file scan.
431 * All 'S line's preceed 'T line's in .REL files.
436 sscanf(buf, "S %s %c", symname, &c);
439 * If we find a symbol definition for the
440 * symbol we're looking for, load in the
441 * file and add it to lbfhead so it gets
442 * loaded on pass number 2.
444 /*5*/ if (strncmp(symname, name, NCPS) == 0 && c == 'D') {
446 lbfh = (struct lbfile *) new (sizeof(struct lbfile));
447 if (lbfhead == NULL) {
455 lbfh->libspc = lbnh->libspc;
457 lbfh->relfil = (char *) new (strlen(relfil) + 1);
458 strcpy(lbfh->relfil,relfil);
461 /* if cdb information required & cdb file present */
463 FILE *xfp = afile(str,"cdb",0);
485 /*)Function VOID library()
487 * The function library() links all the library object files
488 * contained in the lbfile structures.
491 * lbfile *lbfh pointer to lbfile structure
494 * lbfile *lbfhead pointer to first lbfile structure
497 * VOID loadfile lklibr.c
500 * Links all files contained in the lbfile structures.
508 for (lbfh=lbfhead; lbfh; lbfh=lbfh->next) {
509 loadfile(lbfh->filspc);
513 /*)Function VOID loadfile(filspc)
515 * char *filspc library object file specification
517 * The function loadfile() links the library object module.
520 * FILE *fp file handle
521 * int i input line length
522 * char str[] file input line
525 * char *ip pointer to linker input string
528 * int fclose() c_library
529 * int fgets() c_library
530 * FILE * fopen() c_library
531 * VOID link_main() lkmain.c
532 * int strlen() c_library
535 * If file exists it is linked.
545 if ((fp = fopen(filspc,"r")) != NULL) {
546 while (fgets(str, NINPUT, fp) != NULL) {
547 str[NINPUT+1] = '\0';