4 * (C) Copyright 1989-1995
11 * With contributions for the
12 * object libraries from
14 * kenh@cmf.nrl.navy.mil
19 * Extensions: P. Felber
34 * The module lklibr.c contains the functions which
35 * (1) specify the path(s) to library files [.LIB]
36 * (2) specify the library file(s) [.LIB] to search
37 * (3) search the library files for specific symbols
38 * and link the module containing this symbol
40 * lklibr.c contains the following functions:
51 #define EQ(A,B) !strcmp((A),(B))
52 #define NELEM(x) (sizeof (x) / sizeof (*x))
55 /* First entry in the library object symbol cache */
56 pmlibraryfile libr = NULL;
58 int buildlibraryindex (void);
59 void freelibraryindex (void);
62 struct aslib_target *aslib_targets[] = {
63 &aslib_target_sdcclib,
67 /*)Function VOID addpath()
69 * The function addpath() creates a linked structure containing
70 * the paths to various object module library files.
73 * lbpath *lbph pointer to new path structure
74 * lbpath *lbp temporary pointer
77 * lbpath *lbphead The pointer to the first
81 * char getnb() lklex.c
82 * VOID * new() lksym.c
83 * int strlen() c_library
84 * char * strcpy() c_library
85 * VOID unget() lklex.c
88 * An lbpath structure may be created.
94 struct lbpath *lbph, *lbp;
96 lbph = (struct lbpath *) new (sizeof (struct lbpath));
111 lbph->path = strdup (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
129 * ip a pointer to the library name
132 * VOID addfile() lklibr.c
133 * char getnb() lklex.c
134 * VOID unget() lklex.c
137 * The function addfile() may add the file to
138 * the library search list.
151 foundcount = addfile (NULL, ip);
155 for (lbph = lbphead; lbph; lbph = lbph->next)
157 foundcount += addfile (lbph->path, ip);
162 fprintf (stderr, "?ASlink-Warning-Couldn't find library '%s'\n", ip);
166 /*)Function int addfile(path,libfil)
168 * char *path library path specification
169 * char *libfil library file specification
171 * The function addfile() searches for the library file
172 * by concatenating the path and libfil specifications.
173 * if the library is found, an lbname structure is created
174 * and linked to any previously defined structures. This
175 * linked list is used by the function fndsym() to attempt
176 * to find any undefined symbols.
178 * The function does not give report an error on invalid
179 * path / file specifications or if the file is not found.
182 * lbname *lbnh pointer to new name structure
183 * lbname *lbn temporary pointer
186 * lbname *lbnhead The pointer to the first
190 * char getnb() lklex.c
191 * VOID * new() lksym.c
192 * int strlen() c_library
193 * char * strcpy() c_library
194 * VOID unget() lklex.c
197 * An lbname structure may be created.
200 * 1: the library was found
201 * 0: the library was not found
205 addfile (char *path, char *libfil)
209 struct lbname *lbnh, *lbn;
216 str = (char *) new (strlen (path) + strlen (libfil) + 6);
219 if (strlen (str) && (str[strlen (str) - 1] != '/') && (str[strlen (str) - 1] != LKDIRSEP))
221 strcat (str, LKDIRSEPSTR);
227 str = (char *) new (strlen (libfil) + 5);
231 if ((libfil[0] == '/') || (libfil[0] == LKDIRSEP))
238 strcat (str, libfil);
239 if (strchr (libfil, FSEPX) == NULL)
241 sprintf (&str[strlen (str)], "%clib", FSEPX);
244 fp = fopen (str, "rb");
247 /*Ok, that didn't work. Try with the 'libfil' name only */
252 fp = fopen (libfil, "rb");
255 /*Bingo! 'libfil' is the absolute path of the library */
256 strcpy (str, libfil);
257 path = NULL; /*This way 'libfil' and 'path' will be rebuilt from 'str' */
263 /*'path' can not be null since it is needed to find the object files associated with
264 the library. So, get 'path' from 'str' and then chop it off and recreate 'libfil'.
265 That way putting 'path' and 'libfil' together will result into the original filepath
266 as contained in 'str'. */
269 for (j = strlen (path) - 1; j >= 0; j--)
271 if ((path[j] == '/') || (path[j] == LKDIRSEP))
273 strcpy (libfil, &path[j + 1]);
285 lbnh = (struct lbname *) new (sizeof (struct lbname));
301 lbnh->libfil = strdup (libfil);
312 /*)Function VOID search()
314 * The function search() looks through all the symbol tables
315 * at the end of pass 1. If any undefined symbols are found
316 * then the function fndsym() is called. Function fndsym()
317 * searches any specified library files to automagically
318 * import the object modules containing the needed symbol.
320 * After a symbol is found and imported by the function
321 * fndsym() the symbol tables are again searched. The
322 * symbol tables are search until no more symbols can be
323 * resolved within the library files. This ensures that
324 * back references from one library module to another are
328 * int i temporary counter
329 * sym *sp pointer to a symbol structure
330 * int symfnd found a symbol flag
333 * sym *symhash[] array of pointers to symbol tables
336 * int fndsym() lklibr.c
339 * If a symbol is found then the library object module
340 * containing the symbol will be imported and linked.
346 register struct sym *sp;
347 register int i, symfnd;
350 * Look for undefined symbols. Keep
351 * searching until no more symbols are resolved.
358 * Look through all the symbols
360 for (i = 0; i < NHASH; ++i)
365 /* If we find an undefined symbol
366 * (one where S_DEF is not set), then
367 * try looking for it. If we find it
368 * in any of the libraries then
369 * increment symfnd. This will force
370 * another pass of symbol searching and
371 * make sure that back references work.
373 if ((sp->s_type & S_DEF) == 0)
375 if (fndsym (sp->s_id))
386 /*)Function VOID fndsym(name)
388 * char *name symbol name to find
390 * The function fndsym() searches through all combinations of the
391 * library path specifications (input by the -k option) and the
392 * library file specifications (input by the -l option) that
393 * lead to an existing file.
395 * The file specicifation may be formed in one of two ways:
397 * (1) If the library file contained an absolute
398 * path/file specification then this becomes filspc.
401 * (2) If the library file contains a relative path/file
402 * specification then the concatenation of the path
403 * and this file specification becomes filspc.
406 * The structure lbfile is created for the first library
407 * object file which contains the definition for the
408 * specified undefined symbol.
410 * If the library file [.LIB] contains file specifications for
411 * non existant files, no errors are returned.
414 * char buf[] [.REL] file input line
415 * char c [.REL] file input character
416 * FILE *fp file handle for object file
417 * lbfile *lbf temporary pointer
418 * lbfile *lbfh pointer to lbfile structure
419 * FILE *libfp file handle for library file
420 * lbname *lbnh pointer to lbname structure
421 * char *path file specification path
422 * char relfil[] [.REL] file specification
423 * char *str combined path and file specification
424 * char symname[] [.REL] file symbol string
427 * lbname *lbnhead The pointer to the first
429 * lbfile *lbfhead The pointer to the first
433 * int fclose() c_library
434 * FILE *fopen() c_library
435 * VOID free() c_library
436 * char getnb() lklex.c
437 * VOID lkexit() lkmain.c
438 * VOID loadfile() lklibr.c
439 * VOID * new() lksym.c
440 * char * sprintf() c_library
441 * int sscanf() c_library
442 * char * strcat() c_library
443 * char * strchr() c_library
444 * char * strcpy() c_library
445 * int strlen() c_library
446 * int strncmp() c_library
447 * VOID unget() lklex.c
450 * If the symbol is found then a new lbfile structure
451 * is created and added to the linked list of lbfile
452 * structures. The file containing the found symbol
460 struct lbfile *lbfh, *lbf;
461 pmlibraryfile ThisLibr;
462 pmlibrarysymbol ThisSym = NULL;
464 pmlibraryfile FirstFound;
467 /* Build the index if this is the first call to fndsym */
469 buildlibraryindex ();
471 /* Iterate through all library object files */
473 FirstFound = libr; /*So gcc stops whining */
476 /* Iterate through all symbols in an object file */
477 ThisSym = ThisLibr->symbols;
481 if (!strcmp (ThisSym->name, name))
483 if ((!ThisLibr->loaded) && (numfound == 0))
485 /* Object file is not loaded - add it to the list */
486 lbfh = (struct lbfile *) new (sizeof (struct lbfile));
500 lbfh->libspc = ThisLibr->libspc;
501 lbfh->filspc = ThisLibr->filename;
502 lbfh->relfil = strdup (ThisLibr->relfil);
503 lbfh->offset = ThisLibr->offset;
504 lbfh->type = ThisLibr->type;
506 (*aslib_targets[lbfh->type]->loadfile) (lbfh);
508 ThisLibr->loaded = 1;
514 FirstFound = ThisLibr;
518 char absPath1[PATH_MAX];
519 char absPath2[PATH_MAX];
520 #if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
523 _fullpath (absPath1, FirstFound->libspc, PATH_MAX);
524 _fullpath (absPath2, ThisLibr->libspc, PATH_MAX);
525 for (j = 0; absPath1[j] != 0; j++)
526 absPath1[j] = tolower ((unsigned char) absPath1[j]);
527 for (j = 0; absPath2[j] != 0; j++)
528 absPath2[j] = tolower ((unsigned char) absPath2[j]);
530 realpath (FirstFound->libspc, absPath1);
531 realpath (ThisLibr->libspc, absPath2);
533 if (!(EQ (absPath1, absPath2) && EQ (FirstFound->relfil, ThisLibr->relfil)))
537 fprintf (stderr, "?ASlink-Warning-Definition of public symbol '%s'" " found more than once:\n", name);
538 fprintf (stderr, " Library: '%s', Module: '%s'\n", FirstFound->libspc, FirstFound->relfil);
540 fprintf (stderr, " Library: '%s', Module: '%s'\n", ThisLibr->libspc, ThisLibr->relfil);
545 ThisSym = ThisSym->next; /* Next sym in library */
547 ThisLibr = ThisLibr->next; /* Next library in list */
559 add_sybmol (const char *sym, void *param)
561 struct add_sym_s *as = (struct add_sym_s *) param;
562 pmlibrarysymbol ps = (pmlibrarysymbol) new (sizeof (mlibrarysymbol));
566 ps->name = strdup (sym);
570 as->pls = as->plf->symbols = ps;
575 as->pls = as->pls->next;
582 add_rel_index (FILE * fp, long size, pmlibraryfile This)
586 as.pls = This->symbols;
588 assert (This->symbols == NULL);
590 enum_symbols (fp, size, &add_sybmol, &as);
595 /* buildlibraryindex - build an in-memory cache of the symbols contained in
599 buildlibraryindex (void)
601 pmlibraryfile This = NULL;
605 * Search through every library in the linked list "lbnhead".
607 for (lbnh = lbnhead; lbnh; lbnh = lbnh->next)
612 if ((libfp = fopen (lbnh->libspc, "rb")) == NULL)
614 fprintf (stderr, "?ASlink-Error-Cannot open library file %s\n", lbnh->libspc);
618 for (i = 0; i < NELEM (aslib_targets); ++i)
620 if ((*aslib_targets[i]->is_lib) (libfp))
622 This = (*aslib_targets[i]->buildlibraryindex) (lbnh, libfp, This, i);
627 if (i >= NELEM (aslib_targets))
628 fprintf (stderr, "?ASlink-Error-Unknown library file format %s\n", lbnh->libspc);
636 /*Release all memory allocated for the in-memory library index*/
638 freelibraryindex (void)
640 pmlibraryfile ThisLibr, ThisLibr2Free;
641 pmlibrarysymbol ThisSym, ThisSym2Free;
647 ThisSym = ThisLibr->symbols;
651 free (ThisSym->name);
652 ThisSym2Free = ThisSym;
653 ThisSym = ThisSym->next;
656 free (ThisLibr->filename);
657 free (ThisLibr->relfil);
658 ThisLibr2Free = ThisLibr;
659 ThisLibr = ThisLibr->next;
660 free (ThisLibr2Free);
679 load_sybmol (const char *sym, void *params)
681 struct load_sym_s *ls = (struct load_sym_s *) params;
683 if (strcmp (ls->name, sym) == 0)
685 struct lbfile *lbfh, *lbf;
687 lbfh = (struct lbfile *) new (sizeof (struct lbfile));
688 lbfh->libspc = ls->lbnh->libspc;
689 lbfh->relfil = strdup (ls->relfil);
690 lbfh->filspc = strdup (ls->filspc);
691 lbfh->offset = ls->offset;
692 lbfh->type = ls->type;
708 (*aslib_targets[ls->type]->loadfile) (lbfh);
717 add_rel_file (const char *name, struct lbname *lbnh, const char *relfil,
718 const char *filspc, int offset, FILE * fp, long size, int type)
720 struct load_sym_s ls;
728 return enum_symbols (fp, size, &load_sybmol, &ls);
732 fndsym (const char *name)
739 * Search through every library in the linked list "lbnhead".
741 for (lbnh = lbnhead; lbnh; lbnh = lbnh->next)
745 if ((libfp = fopen (lbnh->libspc, "rb")) == NULL)
747 fprintf (stderr, "?ASlink-Error-Cannot open library file %s\n", lbnh->libspc);
751 for (i = 0; i < NELEM (aslib_targets); ++i)
753 if ((*aslib_targets[i]->is_lib) (libfp))
755 ret = (*aslib_targets[i]->fndsym) (name, lbnh, libfp, i);
760 if (i >= NELEM (aslib_targets))
761 fprintf (stderr, "?ASlink-Error-Unknown library file format %s\n", lbnh->libspc);
768 } /* Ends good open of libr file */
771 #endif /* INDEXLIB */
773 /*)Function VOID library()
775 * The function library() links all the library object files
776 * contained in the lbfile structures.
779 * lbfile *lbfh pointer to lbfile structure
782 * lbfile *lbfhead pointer to first lbfile structure
785 * VOID loadfile lklibr.c
788 * Links all files contained in the lbfile structures.
796 for (lbfh = lbfhead; lbfh; lbfh = lbfh->next)
797 (*aslib_targets[lbfh->type]->loadfile) (lbfh);