ack/util/led/sym.c
David Given 4cb4bdc85f There are two places where names are added to the global symbol table; one via
the -U command line option, and one via file scanning. Turns out only the
second would increment the number of global names, so adding names with -U
would cause names found via scanning to fall off the end of the list! This
wouldn't cause linker errors because fixups don't use the list, but would cause
the generated symbol table in the output to be incorrect.
2018-03-11 12:37:23 +01:00

152 lines
4 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
/*
* Symbol table management.
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include "out.h"
#include "const.h"
#include "memory.h"
#include "debug.h"
#include "sym.h"
/*
* Symbol table types. Each hash table entry contains the offset of a symbol
* struct. `Sy_name' contains the offset the name in the piece of global
* names. `Sy_next' contains the offset of the next symbol of which the
* corresponding name has the same hash value.
*/
struct symbol {
ind_t sy_name;
ind_t sy_next;
};
#define NHASH 307 /* Size of hash table. Must be odd. */
static ind_t hashtable[NHASH];
unsigned short NLocals = 0; /* Number of local names to be saved. */
unsigned short NGlobals = 0; /* Number of global names. */
/*
* Initialize the symbol table. All indices should be noticeably invalid.
*/
init_symboltable()
{
register ind_t *rap;
for (rap = hashtable; rap < &hashtable[NHASH]; rap++)
*rap = BADOFF;
}
/*
* Search for `string' in the symboltable. The hash value of `string' is in
* `hashval'. The linked list belonging to the entry of hashval
* in the hash table is followed. If the names match, a pointer to the outname
* in this element of the list is returned. When a match cannot be found,
* NIL is returned.
*/
struct outname *
searchname(string, hashval)
char *string;
int hashval;
{
register char *rcp;
register char *namestring;
register ind_t symindex;
register struct outname *name;
register struct symbol *sym;
symindex = hashtable[hashval];
debug("looking for %s %d %ld:", string, hashval, hashtable[hashval], 0);
while (symindex != BADOFF) {
sym = (struct symbol *)address(ALLOSYMB, symindex);
name = (struct outname *)address(ALLOGLOB, sym->sy_name);
namestring = address(ALLOGCHR, (ind_t)name->on_foff);
rcp = string;
debug("comp %s;", namestring, 0, 0, 0);
while (*rcp == *namestring++)
if (*rcp++ == '\0') {
debug("found %x, %x, %lx\n",
name->on_type, name->on_desc, name->on_valu, 0);
return name;
}
symindex = sym->sy_next;
}
/* Not found. */
debug("not found\n", 0, 0, 0, 0);
return (struct outname *)0;
}
/*
* Enter a new name in the symbol table. We must copy everything to a
* new entry. `Name' is a private copy, i.e. the pointer to it will not be
* destroyed by allocation. However, the string of which name->on_foff is the
* offset can be destroyed, so we save it first.
*/
void entername(struct outname* name, int hashval)
{
ind_t savindex;
ind_t symindex;
ind_t namindex;
register struct symbol *sym;
struct outname *newname;
extern ind_t savechar();
debug("entername %s %d %x %x", modulptr((ind_t)name->on_foff), hashval, name->on_type, name->on_desc);
savindex = savechar(ALLOGCHR, (ind_t)name->on_foff);
symindex = hard_alloc(ALLOSYMB, (long)sizeof(struct symbol));
debug("; %ld\n", symindex, 0, 0, 0);
namindex = hard_alloc(ALLOGLOB, (long)sizeof(struct outname));
if (savindex == BADOFF || symindex == BADOFF || namindex == BADOFF)
fatal("symbol table overflow");
sym = (struct symbol *)address(ALLOSYMB, symindex);
sym->sy_name = namindex;
newname = (struct outname *)address(ALLOGLOB, namindex);
*newname = *name;
newname->on_foff = savindex;
sym->sy_next = hashtable[hashval];
hashtable[hashval] = symindex;
NGlobals++;
}
/*
* Return the index of `name' in the symbol table in the order in which
* it was entered. We need a REAL index, not a byte offset.
*/
unsigned
indexof(name)
struct outname *name;
{
return name - (struct outname *)address(ALLOGLOB, (ind_t)0);
}
/*
* Assign an integer to the string in p.
* 0 <= hash(p) < NHASH, so it can - and will - be used
* as index in a hash table.
*/
int
hash(p)
register char *p;
{
register unsigned short h = 0;
register int c;
while (c = *p++) {
h <<= 2;
h += c;
}
return h % NHASH;
}