ack/util/led/archive.c
1994-06-24 11:31:16 +00:00

181 lines
4.7 KiB
C

/*
* (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 <arch.h>
#include <out.h>
#include <ranlib.h>
#include "const.h"
#include "debug.h"
#include "defs.h"
#include "memory.h"
#define ENDLIB ((long)0)
extern ind_t hard_alloc();
static struct ar_hdr arhdr;
/*
* 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()
{
register ind_t off;
register struct ranlib *ran;
register long count;
register long nran, nchar;
extern long rd_long();
extern int infile;
count = nran = rd_long(infile);
debug("%ld ranlib structs, ", nran, 0, 0, 0);
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 ((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.
*/
arch()
{
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.
*/
notelib(pos)
long pos;
{
register ind_t off;
if ((off = hard_alloc(ALLOARCH, (long)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.
*/
arch2()
{
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. */
}