194 lines
5 KiB
C
194 lines
5 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 <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <stdint.h>
|
|
#include <stdbool.h>
|
|
#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. */
|
|
}
|