3 Copyright (C) 1989-1995 Alan R. Baldwin
4 721 Berkeley St., Kent, Ohio 44240
5 Copyright (C) 2008-2009 Borut Razem, borut dot razem at siol dot net
7 This program is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation; either version 3, or (at your option) any
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
21 * With contributions for the
22 * object libraries from
24 * kenh@cmf.nrl.navy.mil
29 * Extensions: P. Felber
44 * The module lklibr.c contains the functions which
45 * (1) specify the path(s) to library files [.LIB]
46 * (2) specify the library file(s) [.LIB] to search
47 * (3) search the library files for specific symbols
48 * and link the module containing this symbol
50 * lklibr.c contains the following functions:
61 #define EQ(A,B) !strcmp((A),(B))
62 #define NELEM(x) (sizeof (x) / sizeof (*x))
65 /* First entry in the library object symbol cache */
66 pmlibraryfile libr = NULL;
68 int buildlibraryindex (void);
69 void freelibraryindex (void);
72 struct aslib_target *aslib_targets[] = {
73 &aslib_target_sdcclib,
78 /*)Function VOID addpath()
80 * The function addpath() creates a linked structure containing
81 * the paths to various object module library files.
84 * lbpath *lbph pointer to new path structure
85 * lbpath *lbp temporary pointer
88 * lbpath *lbphead The pointer to the first
92 * char getnb() lklex.c
93 * VOID * new() lksym.c
94 * int strlen() c_library
95 * char * strcpy() c_library
96 * VOID unget() lklex.c
99 * An lbpath structure may be created.
105 struct lbpath *lbph, *lbp;
107 lbph = (struct lbpath *) new (sizeof (struct lbpath));
122 lbph->path = strdup (ip);
125 /*)Function VOID addlib()
127 * The function addlib() tests for the existance of a
128 * library path structure to determine the method of
129 * adding this library file to the library search structure.
131 * This function calls the function addfile() to actually
132 * add the library file to the search list.
135 * lbpath *lbph pointer to path structure
138 * lbpath *lbphead The pointer to the first
140 * ip a pointer to the library name
143 * VOID addfile() lklibr.c
144 * char getnb() lklex.c
145 * VOID unget() lklex.c
148 * The function addfile() may add the file to
149 * the library search list.
162 foundcount = addfile (NULL, ip);
166 for (lbph = lbphead; lbph; lbph = lbph->next)
168 foundcount += addfile (lbph->path, ip);
173 fprintf (stderr, "?ASlink-Warning-Couldn't find library '%s'\n", ip);
177 /*)Function int addfile(path,libfil)
179 * char *path library path specification
180 * char *libfil library file specification
182 * The function addfile() searches for the library file
183 * by concatenating the path and libfil specifications.
184 * if the library is found, an lbname structure is created
185 * and linked to any previously defined structures. This
186 * linked list is used by the function fndsym() to attempt
187 * to find any undefined symbols.
189 * The function does not give report an error on invalid
190 * path / file specifications or if the file is not found.
193 * lbname *lbnh pointer to new name structure
194 * lbname *lbn temporary pointer
197 * lbname *lbnhead The pointer to the first
201 * char getnb() lklex.c
202 * VOID * new() lksym.c
203 * int strlen() c_library
204 * char * strcpy() c_library
205 * VOID unget() lklex.c
208 * An lbname structure may be created.
211 * 1: the library was found
212 * 0: the library was not found
216 addfile (char *path, char *libfil)
220 struct lbname *lbnh, *lbn;
227 str = (char *) new (strlen (path) + strlen (libfil) + 6);
230 if (strlen (str) && (str[strlen (str) - 1] != '/') && (str[strlen (str) - 1] != LKDIRSEP))
232 strcat (str, LKDIRSEPSTR);
238 str = (char *) new (strlen (libfil) + 5);
242 if ((libfil[0] == '/') || (libfil[0] == LKDIRSEP))
249 strcat (str, libfil);
250 if (strchr (libfil, FSEPX) == NULL)
252 sprintf (&str[strlen (str)], "%clib", FSEPX);
255 fp = fopen (str, "rb");
258 /*Ok, that didn't work. Try with the 'libfil' name only */
263 fp = fopen (libfil, "rb");
266 /*Bingo! 'libfil' is the absolute path of the library */
267 strcpy (str, libfil);
268 path = NULL; /*This way 'libfil' and 'path' will be rebuilt from 'str' */
274 /*'path' can not be null since it is needed to find the object files associated with
275 the library. So, get 'path' from 'str' and then chop it off and recreate 'libfil'.
276 That way putting 'path' and 'libfil' together will result into the original filepath
277 as contained in 'str'. */
280 for (j = strlen (path) - 1; j >= 0; j--)
282 if ((path[j] == '/') || (path[j] == LKDIRSEP))
284 strcpy (libfil, &path[j + 1]);
296 lbnh = (struct lbname *) new (sizeof (struct lbname));
312 lbnh->libfil = strdup (libfil);
323 /*)Function VOID search()
325 * The function search() looks through all the symbol tables
326 * at the end of pass 1. If any undefined symbols are found
327 * then the function fndsym() is called. Function fndsym()
328 * searches any specified library files to automagically
329 * import the object modules containing the needed symbol.
331 * After a symbol is found and imported by the function
332 * fndsym() the symbol tables are again searched. The
333 * symbol tables are search until no more symbols can be
334 * resolved within the library files. This ensures that
335 * back references from one library module to another are
339 * int i temporary counter
340 * sym *sp pointer to a symbol structure
341 * int symfnd found a symbol flag
344 * sym *symhash[] array of pointers to symbol tables
347 * int fndsym() lklibr.c
350 * If a symbol is found then the library object module
351 * containing the symbol will be imported and linked.
357 register struct sym *sp;
358 register int i, symfnd;
361 * Look for undefined symbols. Keep
362 * searching until no more symbols are resolved.
369 * Look through all the symbols
371 for (i = 0; i < NHASH; ++i)
376 /* If we find an undefined symbol
377 * (one where S_DEF is not set), then
378 * try looking for it. If we find it
379 * in any of the libraries then
380 * increment symfnd. This will force
381 * another pass of symbol searching and
382 * make sure that back references work.
384 if ((sp->s_type & S_DEF) == 0)
386 if (fndsym (sp->s_id))
397 /*)Function VOID fndsym(name)
399 * char *name symbol name to find
401 * The function fndsym() searches through all combinations of the
402 * library path specifications (input by the -k option) and the
403 * library file specifications (input by the -l option) that
404 * lead to an existing file.
406 * The file specicifation may be formed in one of two ways:
408 * (1) If the library file contained an absolute
409 * path/file specification then this becomes filspc.
412 * (2) If the library file contains a relative path/file
413 * specification then the concatenation of the path
414 * and this file specification becomes filspc.
417 * The structure lbfile is created for the first library
418 * object file which contains the definition for the
419 * specified undefined symbol.
421 * If the library file [.LIB] contains file specifications for
422 * non existant files, no errors are returned.
425 * char buf[] [.REL] file input line
426 * char c [.REL] file input character
427 * FILE *fp file handle for object file
428 * lbfile *lbf temporary pointer
429 * lbfile *lbfh pointer to lbfile structure
430 * FILE *libfp file handle for library file
431 * lbname *lbnh pointer to lbname structure
432 * char *path file specification path
433 * char relfil[] [.REL] file specification
434 * char *str combined path and file specification
435 * char symname[] [.REL] file symbol string
438 * lbname *lbnhead The pointer to the first
440 * lbfile *lbfhead The pointer to the first
444 * int fclose() c_library
445 * FILE *fopen() c_library
446 * VOID free() c_library
447 * char getnb() lklex.c
448 * VOID lkexit() lkmain.c
449 * VOID loadfile() lklibr.c
450 * VOID * new() lksym.c
451 * char * sprintf() c_library
452 * int sscanf() c_library
453 * char * strcat() c_library
454 * char * strchr() c_library
455 * char * strcpy() c_library
456 * int strlen() c_library
457 * int strncmp() c_library
458 * VOID unget() lklex.c
461 * If the symbol is found then a new lbfile structure
462 * is created and added to the linked list of lbfile
463 * structures. The file containing the found symbol
471 struct lbfile *lbfh, *lbf;
472 pmlibraryfile ThisLibr;
473 pmlibrarysymbol ThisSym = NULL;
475 pmlibraryfile FirstFound;
478 D ("Searching symbol: %s\n", name);
480 /* Build the index if this is the first call to fndsym */
482 buildlibraryindex ();
484 /* Iterate through all library object files */
485 FirstFound = libr; /* So gcc stops whining */
486 for (ThisLibr = libr; ThisLibr != NULL; ThisLibr = ThisLibr->next)
488 /* Iterate through all symbols in an object file */
489 for (ThisSym = ThisLibr->symbols; ThisSym != NULL; ThisSym = ThisSym->next)
491 if (!strcmp (ThisSym->name, name))
493 if ((!ThisLibr->loaded) && (numfound == 0))
495 /* Object file is not loaded - add it to the list */
496 lbfh = (struct lbfile *) new (sizeof (struct lbfile));
503 for (lbf = lbfhead; lbf->next != NULL; lbf = lbf->next)
508 lbfh->libspc = ThisLibr->libspc;
509 lbfh->filspc = ThisLibr->filspc;
510 lbfh->relfil = strdup (ThisLibr->relfil);
511 lbfh->offset = ThisLibr->offset;
512 lbfh->type = ThisLibr->type;
514 (*aslib_targets[lbfh->type]->loadfile) (lbfh);
516 ThisLibr->loaded = 1;
522 FirstFound = ThisLibr;
526 char absPath1[PATH_MAX];
527 char absPath2[PATH_MAX];
528 #if defined(__BORLANDC__) || defined(_MSC_VER) || defined(__MINGW32__)
531 _fullpath (absPath1, FirstFound->libspc, PATH_MAX);
532 _fullpath (absPath2, ThisLibr->libspc, PATH_MAX);
533 for (j = 0; absPath1[j] != 0; j++)
534 absPath1[j] = tolower ((unsigned char) absPath1[j]);
535 for (j = 0; absPath2[j] != 0; j++)
536 absPath2[j] = tolower ((unsigned char) absPath2[j]);
538 realpath (FirstFound->libspc, absPath1);
539 realpath (ThisLibr->libspc, absPath2);
541 if (!(EQ (absPath1, absPath2) && EQ (FirstFound->relfil, ThisLibr->relfil)))
545 fprintf (stderr, "?ASlink-Warning-Definition of public symbol '%s'" " found more than once:\n", name);
546 fprintf (stderr, " Library: '%s', Module: '%s'\n", FirstFound->libspc, FirstFound->relfil);
548 fprintf (stderr, " Library: '%s', Module: '%s'\n", ThisLibr->libspc, ThisLibr->relfil);
565 add_sybmol (const char *sym, void *param)
567 struct add_sym_s *as = (struct add_sym_s *) param;
568 pmlibrarysymbol ps = (pmlibrarysymbol) new (sizeof (mlibrarysymbol));
570 D (" Indexing symbol: %s\n", sym);
574 ps->name = strdup (sym);
578 as->pls = as->plf->symbols = ps;
583 as->pls = as->pls->next;
590 add_rel_index (FILE * fp, long size, pmlibraryfile This)
594 as.pls = This->symbols;
596 assert (This->symbols == NULL);
598 enum_symbols (fp, size, &add_sybmol, &as);
603 /* buildlibraryindex - build an in-memory cache of the symbols contained in
607 buildlibraryindex (void)
609 pmlibraryfile This = NULL;
613 * Search through every library in the linked list "lbnhead".
615 for (lbnh = lbnhead; lbnh; lbnh = lbnh->next)
620 D ("Indexing library: %s\n", lbnh->libspc);
622 if ((libfp = fopen (lbnh->libspc, "rb")) == NULL)
624 fprintf (stderr, "?ASlink-Error-Cannot open library file %s\n", lbnh->libspc);
628 for (i = 0; i < NELEM (aslib_targets); ++i)
630 if ((*aslib_targets[i]->is_lib) (libfp))
632 This = (*aslib_targets[i]->buildlibraryindex) (lbnh, libfp, This, i);
637 if (i >= NELEM (aslib_targets))
638 fprintf (stderr, "?ASlink-Error-Unknown library file format %s\n", lbnh->libspc);
646 /* Release all memory allocated for the in-memory library index */
648 freelibraryindex (void)
650 pmlibraryfile ThisLibr, ThisLibr2Free;
651 pmlibrarysymbol ThisSym, ThisSym2Free;
657 ThisSym = ThisLibr->symbols;
661 free (ThisSym->name);
662 ThisSym2Free = ThisSym;
663 ThisSym = ThisSym->next;
666 free (ThisLibr->filspc);
667 free (ThisLibr->relfil);
668 ThisLibr2Free = ThisLibr;
669 ThisLibr = ThisLibr->next;
670 free (ThisLibr2Free);
689 load_sybmol (const char *sym, void *params)
691 struct load_sym_s *ls = (struct load_sym_s *) params;
693 D (" Symbol: %s\n", sym);
695 if (strcmp (ls->name, sym) == 0)
697 struct lbfile *lbfh, *lbf;
699 D (" Symbol %s found in module %s!\n", sym, ls->relfil);
701 lbfh = (struct lbfile *) new (sizeof (struct lbfile));
702 lbfh->libspc = ls->lbnh->libspc;
703 lbfh->relfil = strdup (ls->relfil);
704 lbfh->filspc = strdup (ls->filspc);
705 lbfh->offset = ls->offset;
706 lbfh->type = ls->type;
712 for (lbf = lbfhead; lbf->next != NULL; lbf = lbf->next)
716 (*aslib_targets[ls->type]->loadfile) (lbfh);
724 /*)Function int is_module_loaded(filspc)
726 * If this module has been already loaded
730 is_module_loaded (const char *filspc)
734 for (lbf = lbfhead; lbf != NULL; lbf = lbf->next)
736 if (EQ (filspc, lbf->filspc))
738 D (" Module %s already loaded!\n", filspc);
739 return 1; /* Module already loaded */
746 add_rel_file (const char *name, struct lbname *lbnh, const char *relfil,
747 const char *filspc, int offset, FILE * fp, long size, int type)
749 struct load_sym_s ls;
751 /* If this module has been loaded already don't load it again. */
752 if (is_module_loaded (filspc))
763 return enum_symbols (fp, size, &load_sybmol, &ls);
768 fndsym (const char *name)
775 * Search through every library in the linked list "lbnhead".
778 D ("Searching symbol: %s\n", name);
780 for (lbnh = lbnhead; lbnh; lbnh = lbnh->next)
784 D ("Library: %s\n", lbnh->libspc);
786 if ((libfp = fopen (lbnh->libspc, "rb")) == NULL)
788 fprintf (stderr, "?ASlink-Error-Cannot open library file %s\n", lbnh->libspc);
792 for (i = 0; i < NELEM (aslib_targets); ++i)
794 if ((*aslib_targets[i]->is_lib) (libfp))
796 ret = (*aslib_targets[i]->fndsym) (name, lbnh, libfp, i);
801 if (i >= NELEM (aslib_targets))
802 fprintf (stderr, "?ASlink-Error-Unknown library file format %s\n", lbnh->libspc);
809 } /* Ends good open of libr file */
812 #endif /* INDEXLIB */
814 /*)Function VOID library()
816 * The function library() links all the library object files
817 * contained in the lbfile structures.
820 * lbfile *lbfh pointer to lbfile structure
823 * lbfile *lbfhead pointer to first lbfile structure
826 * VOID loadfile lklibr.c
829 * Links all files contained in the lbfile structures.
837 for (lbfh = lbfhead; lbfh; lbfh = lbfh->next)
838 (*aslib_targets[lbfh->type]->loadfile) (lbfh);