/*
* Copyright (c) 2004 - 2007, Nils R. Weller
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This module contains a primitive function to build a linked list for
* symbols. Because every scope has its own symbol ``table'', speeding
* this stuff up, e.g. by using a skip list, would probably buy very
* little, maybe even make it slower. Implementing a unified lookup
* mechanism for all symbols might be a reasonable future goal though
*/
#include "symlist.h"
#include <string.h>
#include "misc.h"
#include "decl.h"
#include "type.h"
#include "scope.h"
#include "debug.h"
#include "token.h"
#include "n_libc.h"
#define HASH_SYM_ENTRY 1
static int
hash_symbol(const char *name, int tabsize) {
int key = 0;
for (; *name != 0; ++name) {
key = (33 * key + *name) & (tabsize - 1);
}
return key;
}
void
new_make_hash_table(struct sym_hash_table *tab, int size) {
int nbytes = size * sizeof *tab->hash_slots_head;
tab->n_hash_slots = size;
tab->hash_slots_head = n_xmalloc(nbytes);
tab->hash_slots_tail = n_xmalloc(nbytes);
memset(tab->hash_slots_head, 0, nbytes);
memset(tab->hash_slots_tail, 0, nbytes);
tab->used = 1;
}
void
new_put_hash_table(struct sym_hash_table *htab, struct sym_entry *item) {
int key = hash_symbol(item->name, htab->n_hash_slots);
if (htab->hash_slots_head[key] == NULL) {
htab->hash_slots_head[key] = item;
htab->hash_slots_tail[key] = item;
} else {
htab->hash_slots_tail[key]->next = item;
htab->hash_slots_tail[key] = item;
}
}
struct sym_entry *
new_lookup_hash(struct sym_hash_table *htab, const char *name, size_t len) {
int key = hash_symbol(name, htab->n_hash_slots);
struct sym_entry *hp;
for (hp = htab->hash_slots_head[key]; hp != NULL; hp = hp->next) {
#if 0
if (hp->item->namelen == len) {
#endif
if (strcmp(hp->name, name) == 0) {
return hp;
}
}
return NULL;
}
#if 0
void
put_hash_table(
struct hash_node **table,
size_t nslots,
struct sym_entry *item) {
struct hash_node *hn;
struct hash_node *newnode;
int idx;
int lastchar = 0;
struct hash_node *patchskip = NULL;
char *name = (char *)item->name;
size_t namelen = item->namelen;
if (namelen >= nslots) {
idx = nslots;
} else {
idx = namelen - 1;
}
newnode = n_xmalloc(sizeof *newnode);
newnode->item = item;
newnode->skip = NULL;
if (table[idx] != NULL) {
/* Collision */
for (hn = table[idx];;) {
char *curname;
struct sym_entry *se = hn->item;
curname = (char *)se->name;
if (curname[0] == name[0]) {
newnode->next = hn->next;
hn->next = newnode;
break;
} else if (lastchar != curname[0]) {
lastchar = curname[0];
patchskip = hn;
}
if (hn->next == NULL) {
newnode->next = NULL;
hn->next = newnode;
patchskip->skip = newnode;
break;
} else {
hn = hn->next;
}
}
} else {
table[idx] = newnode;
newnode->next = NULL;
}
}
#endif
struct sym_entry *
make_sym_entry(struct decl *dec) {
struct sym_entry *s;
s = n_xmalloc(sizeof *s);
s->name = dec->dtype->name;
if (s->name != NULL) {
s->namelen = strlen(dec->dtype->name);
} else {
s->namelen = 0;
}
s->dec = dec;
s->next = NULL;
return s;
}
void
append_symlist(
struct scope *scope,
struct sym_entry **head,
struct sym_entry **tail,
struct decl *dec) {
struct sym_entry *s;
s = make_sym_entry(dec);
if (scope != NULL && scope->type != SCOPE_STRUCT) {
/* XXX this stuff does not belong here! it should go to
* new_scope() or something
*/
if (!scope->sym_hash.used) {
if (scope == &global_scope) {
#if 0
scope->sym_hash = n_xmalloc(64 * sizeof *scope->sym_hash);
scope->n_hash_slots = 63;
memset(scope->sym_hash, 0, 64 * sizeof *scope->sym_hash);
#endif
new_make_hash_table(&scope->sym_hash,
SYM_HTAB_GLOBAL_SCOPE);
#if 0
} else if (scope->parent == NULL
|| scope->parent->parent == NULL) {
new_make_hash_table(&scope->sym_hash,
SYM_HTAB_FUNC_TOP_BLOCK);
#endif
}
}
}
if (scope && scope->sym_hash.used) {
if (s->name != NULL) {
#if 0
put_hash_table(scope->sym_hash, scope->n_hash_slots, s);
#endif
new_put_hash_table(&scope->sym_hash, s);
}
} else {
if (*head == NULL) {
*head = *tail = s;
} else {
(*tail)->next = s;
s->prev = *tail;
*tail = s;
}
}
}
#if 0
struct sym_entry *
lookup_hash(struct hash_node **tab, size_t nslots,
const char *name, size_t len) {
struct hash_node *hn;
struct sym_entry *se;
if (len >= nslots) {
hn = tab[nslots];
} else {
hn = tab[len - 1];
}
if (hn == NULL) {
return NULL;
}
for (;;) {
se = hn->item;
if (se->name[0] != name[0]) {
hn = hn->skip;
} else if (strcmp(se->name, name) != 0) {
hn = hn->next;
} else {
/* Found */
return se;
}
if (hn == NULL) {
break;
}
}
/* NOTREACHED */
return NULL;
}
#endif
syntax highlighted by Code2HTML, v. 0.9.1