/* * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands. * See the copyright notice in the ACK home directory, in the file "Copyright". */ #ifndef lint static char rcsid[] = "$Id$"; #endif #include #include #include #include #include "arch.h" #include "out.h" #include "ranlib.h" #include "object.h" #include "const.h" #include "debug.h" #include "finish.h" #include "extract.h" #include "defs.h" #include "memory.h" #include "scan.h" #include "error.h" #include "save.h" #define ENDLIB ((long)0) static struct ar_hdr arhdr; void notelib(long pos); /* * First read a long telling how many ranlib structs there are, then * the structs themselves. Second read a long telling how many chars there are * in the string table, then the string table itself. * We keep only one ranlib table in core, so this table always starts at offset * (ind_t)0 from its base. */ static long getsymdeftable(void) { register ind_t off; register struct ranlib *ran; register long count; register long nran, nchar; extern long rd_long(); extern FILE* infile; count = nran = rd_long(infile); debug("%ld ranlib structs, ", nran, 0, 0, 0); if (nran > SIZE_MAX / sizeof(struct ranlib)) off = BADOFF; /* nran * size would overflow. */ else off = hard_alloc(ALLORANL, nran * sizeof(struct ranlib)); if (off == BADOFF) fatal("no space for ranlib structs"); ran = (struct ranlib *)address(ALLORANL, off); rd_ranlib(infile, ran, count); nchar = rd_long(infile); debug("%ld ranlib chars\n", nchar, 0, 0, 0); if (nchar != (size_t)nchar || (off = hard_alloc(ALLORANL, nchar)) == BADOFF) fatal("no space for ranlib strings"); rd_bytes(infile, address(ALLORANL, off), nchar); ran = (struct ranlib *)address(ALLORANL, (ind_t)0); while (count--) { /* * Adjust because names are now in core, not on file. * Note that `ran_off' is measured from the beginning of the * string area, NOT from the beginning of the file. */ if (ran->ran_off >= nchar) fatal("bad ranlib string offset"); ran->ran_off += off; ran++; } return nran; } extern char *modulname; /* * Process archive with table of contents. The table of contents tells * of symbols in which module they are defined. We scan the table for * symbols that are known but not yet defined. Then we extract all necessary * information from the corresponding module. This module may need symbols that * were defined in modules located before this one in the archive, so we * scan the table again. We perform these actions as long as new symbols * are defined. */ void arch(void) { long nran; bool resolved; nran = getsymdeftable(); savemagic(); do { register ind_t ranindex; register long count; debug("(re)scan ranlib table\n", 0, 0, 0, 0); ranindex = (ind_t)0; count = nran; resolved = FALSE; while (count > 0) { register struct ranlib *ran; register char *string; register struct outname *name; register long pos; extern int hash(); extern struct outname *searchname(); ran = (struct ranlib *)address(ALLORANL, ranindex); string = address(ALLORANL, (ind_t)ran->ran_off); name = searchname(string, hash(string)); if (name == (struct outname *)0 || !ISUNDEFINED(name)) { ranindex += sizeof(struct ranlib); count--; continue; } seek(ran->ran_pos); get_archive_header(&arhdr); modulname = arhdr.ar_name; verbose("defines %s", string, 0, 0, 0); resolved = TRUE; /* * This archive member is going to be linked, * so we don't need to know what else it defines. * Note that we assume that all ranlib information of * one archive member is contiguous. */ pos = ran->ran_pos; do { count--; ran++; ranindex += sizeof(struct ranlib); } while (count > 0 && ran->ran_pos == pos); notelib(pos); savehdr(&arhdr); extract(); } } while (resolved); dealloc(ALLORANL); notelib(ENDLIB); } /* * An archive member that will be loaded is remembered by storing its position * in the archive into the table of positions. */ void notelib(long pos) { register ind_t off; if ((off = hard_alloc(ALLOARCH, sizeof(long))) == BADOFF) fatal("no space for archive position"); *(long *)address(ALLOARCH, off) = pos; } /* * Index of position of first archive member of next archive. */ static ind_t posindex = (ind_t)0; /* * Process the archive in pass 2. * We walk through the table of positions telling at what byte offset the * archive header + module is located, until this position is ENDLIB, meaning * that we've processed all needed modules in this archive. Each group of * positions of an archive is terminated with ENDLIB. */ void arch2(void) { register long *pos; register ind_t localpos; localpos = posindex; for ( pos = (long *)address(ALLOARCH, localpos); *pos != ENDLIB; pos++, localpos += sizeof(long) ) { seek(*pos); get_archive_header(&arhdr); modulname = arhdr.ar_name; debug("%s: archive member\n", modulname, 0, 0, 0); finish(); } localpos += sizeof(long); /* Skip ENDLIB. */ posindex = localpos; /* Remember for next call. */ }