4 * (C) Copyright 1989-1995
11 * With contributions for the
12 * object libraries from
14 * kenh@cmf.nrl.navy.mil
19 * Extensions: P. Felber
22 #define EQ(A,B) !strcmp((A),(B))
36 * The module lklibr.c contains the functions which
37 * (1) specify the path(s) to library files [.LIB]
38 * (2) specify the library file(s) [.LIB] to search
39 * (3) search the library files for specific symbols
40 * and link the module containing this symbol
42 * lklibr.c contains the following functions:
53 #define NELEM(x) (sizeof (x) / sizeof (*x))
56 /* First entry in the library object symbol cache */
57 pmlibraryfile libr = NULL;
59 int buildlibraryindex (void);
60 void freelibraryindex (void);
63 struct aslib_target *aslib_targets[] = {
64 &aslib_target_sdcclib,
68 /*)Function VOID addpath()
70 * The function addpath() creates a linked structure containing
71 * the paths to various object module library files.
74 * lbpath *lbph pointer to new path structure
75 * lbpath *lbp temporary pointer
78 * lbpath *lbphead The pointer to the first
82 * char getnb() lklex.c
83 * VOID * new() lksym.c
84 * int strlen() c_library
85 * char * strcpy() c_library
86 * VOID unget() lklex.c
89 * An lbpath structure may be created.
95 struct lbpath *lbph, *lbp;
97 lbph = (struct lbpath *) new (sizeof (struct lbpath));
112 lbph->path = strdup (ip);
115 /*)Function VOID addlib()
117 * The function addlib() tests for the existance of a
118 * library path structure to determine the method of
119 * adding this library file to the library search structure.
121 * This function calls the function addfile() to actually
122 * add the library file to the search list.
125 * lbpath *lbph pointer to path structure
128 * lbpath *lbphead The pointer to the first
130 * ip a pointer to the library name
133 * VOID addfile() lklibr.c
134 * char getnb() lklex.c
135 * VOID unget() lklex.c
138 * The function addfile() may add the file to
139 * the library search list.
152 foundcount = addfile (NULL, ip);
156 for (lbph = lbphead; lbph; lbph = lbph->next)
158 foundcount += addfile (lbph->path, ip);
163 fprintf (stderr, "?ASlink-Warning-Couldn't find library '%s'\n", ip);
167 /*)Function int addfile(path,libfil)
169 * char *path library path specification
170 * char *libfil library file specification
172 * The function addfile() searches for the library file
173 * by concatenating the path and libfil specifications.
174 * if the library is found, an lbname structure is created
175 * and linked to any previously defined structures. This
176 * linked list is used by the function fndsym() to attempt
177 * to find any undefined symbols.
179 * The function does not give report an error on invalid
180 * path / file specifications or if the file is not found.
183 * lbname *lbnh pointer to new name structure
184 * lbname *lbn temporary pointer
187 * lbname *lbnhead The pointer to the first
191 * char getnb() lklex.c
192 * VOID * new() lksym.c
193 * int strlen() c_library
194 * char * strcpy() c_library
195 * VOID unget() lklex.c
198 * An lbname structure may be created.
201 * 1: the library was found
202 * 0: the library was not found
206 addfile (char *path, char *libfil)
210 struct lbname *lbnh, *lbn;
217 str = (char *) new (strlen (path) + strlen (libfil) + 6);
220 if (strlen (str) && (str[strlen (str) - 1] != '/') && (str[strlen (str) - 1] != LKDIRSEP))
222 strcat (str, LKDIRSEPSTR);
228 str = (char *) new (strlen (libfil) + 5);
232 if ((libfil[0] == '/') || (libfil[0] == LKDIRSEP))
239 strcat (str, libfil);
240 if (strchr (libfil, FSEPX) == NULL)
242 sprintf (&str[strlen (str)], "%clib", FSEPX);
245 fp = fopen (str, "rb");
248 /*Ok, that didn't work. Try with the 'libfil' name only */
253 fp = fopen (libfil, "rb");
256 /*Bingo! 'libfil' is the absolute path of the library */
257 strcpy (str, libfil);
258 path = NULL; /*This way 'libfil' and 'path' will be rebuilt from 'str' */
264 /*'path' can not be null since it is needed to find the object files associated with
265 the library. So, get 'path' from 'str' and then chop it off and recreate 'libfil'.
266 That way putting 'path' and 'libfil' together will result into the original filepath
267 as contained in 'str'. */
270 for (j = strlen (path) - 1; j >= 0; j--)
272 if ((path[j] == '/') || (path[j] == LKDIRSEP))
274 strcpy (libfil, &path[j + 1]);
286 lbnh = (struct lbname *) new (sizeof (struct lbname));
302 lbnh->libfil = strdup (libfil);
313 /*)Function VOID search()
315 * The function search() looks through all the symbol tables
316 * at the end of pass 1. If any undefined symbols are found
317 * then the function fndsym() is called. Function fndsym()
318 * searches any specified library files to automagically
319 * import the object modules containing the needed symbol.
321 * After a symbol is found and imported by the function
322 * fndsym() the symbol tables are again searched. The
323 * symbol tables are search until no more symbols can be
324 * resolved within the library files. This ensures that
325 * back references from one library module to another are
329 * int i temporary counter
330 * sym *sp pointer to a symbol structure
331 * int symfnd found a symbol flag
334 * sym *symhash[] array of pointers to symbol tables
337 * int fndsym() lklibr.c
340 * If a symbol is found then the library object module
341 * containing the symbol will be imported and linked.
347 register struct sym *sp;
348 register int i, symfnd;
351 * Look for undefined symbols. Keep
352 * searching until no more symbols are resolved.
359 * Look through all the symbols
361 for (i = 0; i < NHASH; ++i)
366 /* If we find an undefined symbol
367 * (one where S_DEF is not set), then
368 * try looking for it. If we find it
369 * in any of the libraries then
370 * increment symfnd. This will force
371 * another pass of symbol searching and
372 * make sure that back references work.
374 if ((sp->s_type & S_DEF) == 0)
376 if (fndsym (sp->s_id))
387 /*)Function VOID fndsym(name)
389 * char *name symbol name to find
391 * The function fndsym() searches through all combinations of the
392 * library path specifications (input by the -k option) and the
393 * library file specifications (input by the -l option) that
394 * lead to an existing file.
396 * The file specicifation may be formed in one of two ways:
398 * (1) If the library file contained an absolute
399 * path/file specification then this becomes filspc.
402 * (2) If the library file contains a relative path/file
403 * specification then the concatenation of the path
404 * and this file specification becomes filspc.
407 * The structure lbfile is created for the first library
408 * object file which contains the definition for the
409 * specified undefined symbol.
411 * If the library file [.LIB] contains file specifications for
412 * non existant files, no errors are returned.
415 * char buf[] [.REL] file input line
416 * char c [.REL] file input character
417 * FILE *fp file handle for object file
418 * lbfile *lbf temporary pointer
419 * lbfile *lbfh pointer to lbfile structure
420 * FILE *libfp file handle for library file
421 * lbname *lbnh pointer to lbname structure
422 * char *path file specification path
423 * char relfil[] [.REL] file specification
424 * char *str combined path and file specification
425 * char symname[] [.REL] file symbol string
428 * lbname *lbnhead The pointer to the first
430 * lbfile *lbfhead The pointer to the first
434 * int fclose() c_library
435 * FILE *fopen() c_library
436 * VOID free() c_library
437 * char getnb() lklex.c
438 * VOID lkexit() lkmain.c
439 * VOID loadfile() lklibr.c
440 * VOID * new() lksym.c
441 * char * sprintf() c_library
442 * int sscanf() c_library
443 * char * strcat() c_library
444 * char * strchr() c_library
445 * char * strcpy() c_library
446 * int strlen() c_library
447 * int strncmp() c_library
448 * VOID unget() lklex.c
451 * If the symbol is found then a new lbfile structure
452 * is created and added to the linked list of lbfile
453 * structures. The file containing the found symbol
461 struct lbfile *lbfh, *lbf;
462 pmlibraryfile ThisLibr;
463 pmlibrarysymbol ThisSym = NULL;
465 pmlibraryfile FirstFound;
468 /* Build the index if this is the first call to fndsym */
470 buildlibraryindex ();
472 /* Iterate through all library object files */
474 FirstFound = libr; /*So gcc stops whining */
477 /* Iterate through all symbols in an object file */
478 ThisSym = ThisLibr->symbols;
482 if (!strcmp (ThisSym->name, name))
484 if ((!ThisLibr->loaded) && (numfound == 0))
486 /* Object file is not loaded - add it to the list */
487 lbfh = (struct lbfile *) new (sizeof (struct lbfile));
501 lbfh->libspc = ThisLibr->libspc;
502 lbfh->filspc = ThisLibr->filename;
503 lbfh->relfil = strdup (ThisLibr->relfil);
504 lbfh->offset = ThisLibr->offset;
505 lbfh->type = ThisLibr->type;
507 (*aslib_targets[lbfh->type]->loadfile) (lbfh);
509 ThisLibr->loaded = 1;
515 FirstFound = ThisLibr;
519 char absPath1[PATH_MAX];
520 char absPath2[PATH_MAX];
521 #if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
524 _fullpath (absPath1, FirstFound->libspc, PATH_MAX);
525 _fullpath (absPath2, ThisLibr->libspc, PATH_MAX);
526 for (j = 0; absPath1[j] != 0; j++)
527 absPath1[j] = tolower ((unsigned char) absPath1[j]);
528 for (j = 0; absPath2[j] != 0; j++)
529 absPath2[j] = tolower ((unsigned char) absPath2[j]);
531 realpath (FirstFound->libspc, absPath1);
532 realpath (ThisLibr->libspc, absPath2);
534 if (!(EQ (absPath1, absPath2) && EQ (FirstFound->relfil, ThisLibr->relfil)))
538 fprintf (stderr, "?ASlink-Warning-Definition of public symbol '%s'" " found more than once:\n", name);
539 fprintf (stderr, " Library: '%s', Module: '%s'\n", FirstFound->libspc, FirstFound->relfil);
541 fprintf (stderr, " Library: '%s', Module: '%s'\n", ThisLibr->libspc, ThisLibr->relfil);
546 ThisSym = ThisSym->next; /* Next sym in library */
548 ThisLibr = ThisLibr->next; /* Next library in list */
560 add_sybmol (const char *sym, void *param)
562 struct add_sym_s *as = (struct add_sym_s *) param;
563 pmlibrarysymbol ps = (pmlibrarysymbol) new (sizeof (mlibrarysymbol));
567 ps->name = strdup (sym);
571 as->pls = as->plf->symbols = ps;
576 as->pls = as->pls->next;
583 add_rel_index (FILE * fp, long size, pmlibraryfile This)
587 as.pls = This->symbols;
589 assert (This->symbols == NULL);
591 enum_symbols (fp, size, &add_sybmol, &as);
596 /* buildlibraryindex - build an in-memory cache of the symbols contained in
600 buildlibraryindex (void)
602 pmlibraryfile This = NULL;
606 * Search through every library in the linked list "lbnhead".
608 for (lbnh = lbnhead; lbnh; lbnh = lbnh->next)
613 if ((libfp = fopen (lbnh->libspc, "rb")) == NULL)
615 fprintf (stderr, "?ASlink-Error-Cannot open library file %s\n", lbnh->libspc);
619 for (i = 0; i < NELEM (aslib_targets); ++i)
621 if ((*aslib_targets[i]->is_lib) (libfp))
623 This = (*aslib_targets[i]->buildlibraryindex) (lbnh, libfp, This, i);
628 if (i >= NELEM (aslib_targets))
629 fprintf (stderr, "?ASlink-Error-Unknown library file format %s\n", lbnh->libspc);
637 /*Release all memory allocated for the in-memory library index*/
639 freelibraryindex (void)
641 pmlibraryfile ThisLibr, ThisLibr2Free;
642 pmlibrarysymbol ThisSym, ThisSym2Free;
648 ThisSym = ThisLibr->symbols;
652 free (ThisSym->name);
653 ThisSym2Free = ThisSym;
654 ThisSym = ThisSym->next;
657 free (ThisLibr->filename);
658 free (ThisLibr->relfil);
659 ThisLibr2Free = ThisLibr;
660 ThisLibr = ThisLibr->next;
661 free (ThisLibr2Free);
680 load_sybmol (const char *sym, void *params)
682 struct load_sym_s *ls = (struct load_sym_s *) params;
684 if (strcmp (ls->name, sym) == 0)
686 struct lbfile *lbfh, *lbf;
688 lbfh = (struct lbfile *) new (sizeof (struct lbfile));
689 lbfh->libspc = ls->lbnh->libspc;
690 lbfh->relfil = strdup (ls->relfil);
691 lbfh->filspc = strdup (ls->filspc);
692 lbfh->offset = ls->offset;
693 lbfh->type = ls->type;
709 (*aslib_targets[ls->type]->loadfile) (lbfh);
718 add_rel_file (const char *name, struct lbname *lbnh, const char *relfil,
719 const char *filspc, int offset, FILE * fp, long size, int type)
721 struct load_sym_s ls;
729 return enum_symbols (fp, size, &load_sybmol, &ls);
733 fndsym (const char *name)
740 * Search through every library in the linked list "lbnhead".
742 for (lbnh = lbnhead; lbnh; lbnh = lbnh->next)
746 if ((libfp = fopen (lbnh->libspc, "rb")) == NULL)
748 fprintf (stderr, "?ASlink-Error-Cannot open library file %s\n", lbnh->libspc);
752 for (i = 0; i < NELEM (aslib_targets); ++i)
754 if ((*aslib_targets[i]->is_lib) (libfp))
756 ret = (*aslib_targets[i]->fndsym) (name, lbnh, libfp, i);
761 if (i >= NELEM (aslib_targets))
762 fprintf (stderr, "?ASlink-Error-Unknown library file format %s\n", lbnh->libspc);
769 } /* Ends good open of libr file */
772 #endif /* INDEXLIB */
774 /*)Function VOID library()
776 * The function library() links all the library object files
777 * contained in the lbfile structures.
780 * lbfile *lbfh pointer to lbfile structure
783 * lbfile *lbfhead pointer to first lbfile structure
786 * VOID loadfile lklibr.c
789 * Links all files contained in the lbfile structures.
797 for (lbfh = lbfhead; lbfh; lbfh = lbfh->next)
798 (*aslib_targets[lbfh->type]->loadfile) (lbfh);