/* @@@HEAD@@@
// The global identifier table.
*/
#include <stdio.h>
#include <string.h>
#include "config.h"
#include "defs.h"
#include "cdc_types.h"
#include "memory.h"
#include "util.h"
#include "log.h"
#define FWRITE(v, fp) fwrite(&v, sizeof(v), 1, fp)
#define FREAD(v, fp) fread(&v, sizeof(v), 1, fp)
/* We use MALLOC_DELTA to keep the table sizes at least 32 bytes below a power
* of two, assuming an int is four bytes. */
#define MALLOC_DELTA 8
#define INIT_TAB_SIZE (512 - MALLOC_DELTA)
typedef struct xident_entry {
char *s;
int refs;
long next;
} xIdent_entry;
static xIdent_entry *tab;
static long *hashtab;
static long tab_size, blanks;
Ident perm_id, type_id, div_id, integer_id, float_id, string_id, dbref_id,
list_id, symbol_id, error_id, frob_id, methodnf_id, methoderr_id,
parent_id, maxdepth_id, objnf_id, numargs_id, range_id, paramnf_id,
file_id, ticks_id, connect_id, disconnect_id, startup_id, parse_id,
socket_id, bind_id, servnf_id, paramexists_id, dictionary_id, keynf_id,
address_id, refused_id, net_id, timeout_id, other_id, failed_id,
heartbeat_id, regexp_id, buffer_id, namenf_id, salt_id, function_id,
opcode_id, method_id, interpreter_id, signal_id, directory_id;
Ident public_id, protected_id, private_id, root_id, driver_id,
noover_id, sync_id, locked_id, native_id;
void init_ident(void)
{
long i;
tab_size = INIT_TAB_SIZE;
tab = EMALLOC(xIdent_entry, tab_size);
hashtab = EMALLOC(long, tab_size);
for (i = 0; i < tab_size; i++) {
tab[i].s = NULL;
tab[i].next = i + 1;
hashtab[i] = -1;
}
tab[tab_size - 1].next = -1;
blanks = 0;
perm_id = ident_get("perm");
type_id = ident_get("type");
div_id = ident_get("div");
integer_id = ident_get("integer");
float_id = ident_get("float");
string_id = ident_get("string");
dbref_id = ident_get("dbref");
list_id = ident_get("list");
symbol_id = ident_get("symbol");
error_id = ident_get("error");
frob_id = ident_get("frob");
methodnf_id = ident_get("methodnf");
methoderr_id = ident_get("methoderr");
parent_id = ident_get("parent");
maxdepth_id = ident_get("maxdepth");
objnf_id = ident_get("objnf");
numargs_id = ident_get("numargs");
range_id = ident_get("range");
paramnf_id = ident_get("paramnf");
file_id = ident_get("file");
ticks_id = ident_get("ticks");
connect_id = ident_get("connect");
disconnect_id = ident_get("disconnect");
parse_id = ident_get("parse");
startup_id = ident_get("startup");
socket_id = ident_get("socket");
bind_id = ident_get("bind");
servnf_id = ident_get("servnf");
paramexists_id = ident_get("paramexists");
dictionary_id = ident_get("dictionary");
keynf_id = ident_get("keynf");
address_id = ident_get("address");
refused_id = ident_get("refused");
net_id = ident_get("net");
timeout_id = ident_get("timeout");
other_id = ident_get("other");
failed_id = ident_get("failed");
heartbeat_id = ident_get("heartbeat");
regexp_id = ident_get("regexp");
buffer_id = ident_get("buffer");
namenf_id = ident_get("namenf");
salt_id = ident_get("salt");
function_id = ident_get("function");
opcode_id = ident_get("opcode");
method_id = ident_get("method");
interpreter_id = ident_get("interpreter");
signal_id = ident_get("signal");
directory_id = ident_get("directory");
public_id = ident_get("public");
protected_id = ident_get("protected");
private_id = ident_get("private");
root_id = ident_get("root");
driver_id = ident_get("driver");
noover_id = ident_get("disallow_overrides");
sync_id = ident_get("synchronized");
locked_id = ident_get("locked");
native_id = ident_get("native");
}
void ident_dump(int id, char *msg) {
write_err("##ident_dump: %s name:%s number:%d refs:%d",
msg, tab[id].s, id, tab[id].refs);
}
Ident ident_get(char *s)
{
unsigned long hval = hash(s);
long ind, new_size, i;
/* Look for an existing identifier. */
ind = hashtab[hval % tab_size];
while (ind != -1) {
if (strcmp(tab[ind].s, s) == 0) {
tab[ind].refs++;
#ifdef IDENT_DEBUG
write_err("get(old) %s: %d refs %d", s, ind, tab[ind].refs);
#endif
return ind;
}
ind = tab[ind].next;
}
/* Check if we have to resize the table. */
if (blanks == -1) {
/* Allocate new space for table. */
new_size = tab_size * 2 + MALLOC_DELTA;
tab = EREALLOC(tab, xIdent_entry, new_size);
hashtab = EREALLOC(hashtab, long, new_size);
/* Make new string of blanks. */
for (i = tab_size; i < new_size - 1; i++)
tab[i].next = i + 1;
tab[i].next = -1;
blanks = tab_size;
/* Reset hash table. */
for (i = 0; i < new_size; i++)
hashtab[i] = -1;
/* Install old symbols in hash table. */
for (i = 0; i < tab_size; i++) {
ind = hash(tab[i].s) % new_size;
tab[i].next = hashtab[ind];
hashtab[ind] = i;
}
tab_size = new_size;
}
/* Install symbol at first blank. */
ind = blanks;
blanks = tab[ind].next;
tab[ind].s = tstrdup(s);
tab[ind].refs = 1;
tab[ind].next = hashtab[hval % tab_size];
hashtab[hval % tab_size] = ind;
#ifdef IDENT_DEBUG
write_err("get(new) %s: %d refs %d", s, ind, tab[ind].refs);
#endif
return ind;
}
void ident_discard(Ident id)
{
long ind, *p;
tab[id].refs--;
#ifdef IDENT_DEBUG
write_err("discard %s: %d refs %d", tab[id].s, id, tab[id].refs);
#endif
if (!tab[id].refs) {
/* Get the hash table thread for this entry. */
ind = hash(tab[id].s) % tab_size;
/* Free the string. */
tfree_chars(tab[id].s);
tab[id].s = NULL;
/* Find the pointer to this entry. */
for (p = &hashtab[ind]; *p != id; p = &tab[*p].next);
/* Remove this entry and add it to blanks. */
*p = tab[id].next;
tab[id].next = blanks;
blanks = id;
}
}
Ident ident_dup(Ident id)
{
tab[id].refs++;
if (!tab[id].s)
panic("ident_dup tried to duplicate freed name.");
#ifdef IDENT_DEBUG
write_err("dup %s: %d refs %d", tab[id].s, id, tab[id].refs);
#endif
return id;
}
char *ident_name(Ident id)
{
return tab[id].s;
}