Files
Arquivotheca.SunOS-4.1.4/lang/ld/incl.c
seta75D ff309bfe1c Init
2021-10-11 18:37:13 -03:00

319 lines
6.9 KiB
C

#ifndef lint
static char sccsid[] = "@(#)incl.c 1.1 94/10/31 Copyr 1991 Sun Micro";
#endif
/*
* Copyright (c) 1986, 1991 by Sun Microsystems, Inc.
*/
#include <stdio.h>
#include <a.out.h>
#include <stab.h>
#include <ctype.h>
/*
* Info about each include file
*/
struct incl {
char *name; /* Name of header file */
int nstatic; /* # of statics in the file */
int nsymbols; /* # of symbols in header file */
int checksum; /* Checksum for header file */
int ord; /* Ordinal # of header file */
int exclude; /* Flag: include/exclude syms */
struct incl *next; /* Linked Hash list */
};
#define NINCL_STACK 10 /* Size of the include stack */
#define INCL_HASH 64 /* Size of header file hash table */
static struct incl **incl_stack; /* Include file stack */
static int stack_size; /* Size of incl_stack */
static struct incl **stkp; /* Stack pointer */
static struct incl *incl_table[INCL_HASH]; /* Table saved for pass 2 */
static struct incl *cur_incl; /* Current header file */
static int obj_ord; /* Saved value of header_num */
extern int ssize; /* Size of symbol section */
extern int header_num; /* Ordinal value of next header file */
struct incl *find_ord();
char *strcpy();
char *mymalloc();
char *realloc();
/*
* Allocate the intial include file stack.
* The stack will grow if necessary.
*/
alloc_inclstack()
{
if ((incl_stack = (struct incl **) mymalloc(NINCL_STACK*sizeof(struct incl *))) == 0)
error(1, "ran out of memory (alloc_inclstack)");
stkp = incl_stack;
stack_size = NINCL_STACK;
}
/*
* Beginning a new object file. Remember the ordinal number
* of the next header file in case this object file is not
* used and everything needs to be ripped out and thrown away.
*/
new_obj1()
{
obj_ord = header_num;
}
/*
* Enter a new include file.
* Stack the current one, if it is active.
* Allocate a structure and initialize it.
*/
start_incl1(sym, ord)
struct nlist *sym;
int ord;
{
char *name;
int n;
register char *namespace;
if (stkp >= &incl_stack[stack_size]) {
n = stkp - incl_stack;
stack_size += NINCL_STACK;
if ((incl_stack = (struct incl **) realloc(incl_stack,
stack_size * sizeof(struct incl *))) == 0)
error(1, "ran out of memory (start_incl1)");
stkp = &incl_stack[n];
}
*stkp++ = cur_incl;
name = sym->n_un.n_name;
if ((cur_incl = (struct incl *) mymalloc(sizeof(struct incl))) == 0)
error(1, "ran out of memory (start_incl1)");
if ((namespace = mymalloc(strlen(name) + 1)) == 0)
error(1, "ran out of memory (start_incl1)");
cur_incl->name = strcpy(namespace, name);
cur_incl->nstatic = 0;
cur_incl->nsymbols = 0;
cur_incl->checksum = 0;
cur_incl->ord = ord;
cur_incl->exclude = 0;
cur_incl->next = NULL;
}
/*
* Found the end of an include file.
* Hash on its name and enter it into the
* has table. Pass two will find it by
* its name and ordinal number.
* Also, pop one off of the stack.
*/
end_incl1()
{
int h;
h = hash(cur_incl->name);
cur_incl->next = incl_table[h];
incl_table[h] = cur_incl;
cur_incl = *--stkp;
}
/*
*
* Found a dbx symbol in pass one.
* If there is an active header file, include the info.
* The checksum is the summation of all the characters except for
* filenumbers which are digits immediately following an open
* parenthesis in the n_name field of the nlist
* structure.
*/
stab1(sym)
struct nlist *sym;
{
register char *cp;
if (cur_incl == NULL) {
return;
}
cur_incl->nsymbols++;
if (sym->n_type == N_STSYM || sym->n_type == N_LCSYM || sym->n_type == N_EXCL ) {
cur_incl->nstatic++;
}
cp = sym->n_un.n_name;
if (sym->n_type != N_EXCL && cp != NULL) {
while (*cp != '\0') {
cur_incl->checksum += *cp;
if (*cp == '(') {
while (*++cp != '\0' && isdigit(*cp))
;
/*
If no more symbols then return
else continue at the top loop
*/
if (*cp == '\0')
return;
else
continue;
}
cp++;
}
}
}
/*
* An object file was not used.
* Must remove any header files it had from the hash table.
*/
incl_free()
{
struct incl *ip;
struct incl *next;
struct incl **ipp;
struct incl **bpatch;
int nhdrs;
int removed;
if (obj_ord == header_num) {
return;
}
removed = 0;
nhdrs = header_num - obj_ord;
for (ipp = incl_table; ipp < &incl_table[INCL_HASH]; ipp++) {
bpatch = ipp;
for (ip = *ipp; ip != NULL; ip = next) {
next = ip->next;
if (ip->ord >= obj_ord) {
*bpatch = ip->next;
free((char *) ip);
removed++;
} else {
bpatch = &ip->next;
}
}
}
if (removed != nhdrs) {
fprintf(stderr, "incl_free removed %d nhdrs %d\n",
removed, nhdrs);
}
header_num = obj_ord;
}
/*
* See what header files can be excluded from the final output.
* The important goal here is to determine how many symbols
* will be excluded so that "ssize" can be adjusted. "Ssize"
* determines the value that will be stored into the a_syms
* field of the a.out header and also determines where the
* string table will begin.
*/
merge_headers()
{
register struct incl *ip;
register struct incl **ipp;
for (ipp = incl_table; ipp < &incl_table[INCL_HASH]; ipp++) {
for (ip = *ipp; ip != NULL; ip = ip->next) {
ip->exclude = find_prev(ip);
if (ip->exclude) {
ssize -= (ip->nsymbols + 1) *
sizeof(struct nlist);
}
}
}
cur_incl = NULL;
}
/*
* Found the beginning of a header file in pass2.
* Find the struct for the header file created in pass1.
* See if there is an identical struct for a header file
* with a lower ordinal value. If so, the symbols in this
* file can be discarded.
*/
start_incl2(sym, ord)
struct nlist *sym;
int ord;
{
struct incl *ip;
int r;
if (stkp > &incl_stack[stack_size]) {
error(1, "include stack too deep");
}
*stkp++ = cur_incl;
cur_incl = find_ord(sym, ord);
sym->n_value = cur_incl->checksum;
if (cur_incl->exclude) {
sym->n_type = N_EXCL;
}
return(cur_incl->exclude);
}
end_incl2()
{
cur_incl = *--stkp;
return(cur_incl != NULL && cur_incl->exclude);
}
/*
* Find a header file with a given ordinal number.
*/
struct incl *
find_ord(sym, ord)
struct nlist *sym;
int ord;
{
register struct incl *ip;
int h;
h = hash(sym->n_un.n_name);
for (ip = incl_table[h]; ip != NULL; ip = ip->next) {
if (ip->ord == ord) {
return(ip);
}
}
error(1, "no include table entry for header file '%s'",
sym->n_un.n_name);
}
/*
* Try to find an identical header file with a lower ordinal number.
*/
find_prev(incl)
register struct incl *incl;
{
register struct incl *ip;
int h;
if (incl->nstatic > 0) {
return(0);
}
h = hash(incl->name);
for (ip = incl_table[h]; ip != NULL; ip = ip->next) {
if (ip->nsymbols == incl->nsymbols &&
ip->nstatic == 0 &&
ip->checksum == incl->checksum &&
ip->ord < incl->ord &&
strcmp(incl->name, ip->name) == 0) {
return(1);
}
}
return(0);
}
/*
* Compute a hash from a string.
* Simply sum the characters and mod.
*/
hash(str)
char *str;
{
register int sum;
register char *cp;
sum = 0;
for (cp = str; *cp; cp++) {
sum += *cp;
}
return(sum % INCL_HASH);
}