ack/util/led/archive.c
1985-01-10 13:35:39 +00:00

179 lines
4.6 KiB
C

#ifndef lint
static char rcsid[] = "$Header$";
#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 getlong();
count = nran = getlong();
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);
read_table(ran, count);
nchar = getlong();
debug("%ld ranlib chars\n", nchar, 0, 0, 0);
if ((off = hard_alloc(ALLORANL, nchar)) == BADOFF)
fatal("no space for ranlib strings");
read_char(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;
extern long position;
/*
* 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;
debug("%s defines %s\n", modulname, string, 0, 0);
position = ran->ran_pos + SZ_ARCH;
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);
position = *pos + SZ_ARCH;
finish();
}
localpos += sizeof(long); /* Skip ENDLIB. */
posindex = localpos; /* Remember for next call. */
}