/* * $Id: symbol.c,v 1.23 2007-04-22 13:55:18 bacon Exp $ */ #include #include #include static void __grow_symtab (ase_stx_t* stx) { ase_word_t capa, ncapa, i, j; ase_word_t* nspace; capa = stx->symtab.capacity; ncapa = capa << 1; nspace = (ase_word_t*)ase_malloc(ase_sizeof(ase_word_t) * ncapa); if (nspace == ASE_NULL) { /* TODO: handle memory error */ } for (i = 0; i < capa; i++) { ase_word_t x = stx->symtab.datum[i]; if (x == stx->nil) continue; j = ase_stx_strxhash ( ASE_STX_DATA(stx,x), ASE_STX_SIZE(stx,x)) % ncapa; while (1) { if (nspace[j] == stx->nil) { nspace[j] = x; break; } j = (j % ncapa) + 1; } } stx->symtab.capacity = ncapa; ase_free (stx->symtab.datum); stx->symtab.datum = nspace; } ase_word_t ase_stx_new_symbol (ase_stx_t* stx, const ase_char_t* name) { return ase_stx_new_symbolx (stx, name, ase_strlen(name)); } ase_word_t ase_stx_new_symbolx ( ase_stx_t* stx, const ase_char_t* name, ase_word_t len) { ase_word_t capa, hash, index, size, x; capa = stx->symtab.capacity; size = stx->symtab.size; if (capa <= size + 1) { __grow_symtab (stx); capa = stx->symtab.capacity; } hash = ase_stx_strxhash(name,len); index = hash % stx->symtab.capacity; while (1) { x = stx->symtab.datum[index]; if (x == stx->nil) { /* insert a new item into an empty slot */ x = ase_stx_alloc_char_objectx (stx, name, len); ASE_STX_CLASS(stx,x) = stx->class_symbol; stx->symtab.datum[index] = x; stx->symtab.size++; break; } if (ase_strxncmp(name, len, ASE_STX_DATA(stx,x), ASE_STX_SIZE(stx,x)) == 0) break; index = (index % stx->symtab.capacity) + 1; } return x; } void ase_stx_traverse_symbol_table ( ase_stx_t* stx, void (*func) (ase_stx_t*,ase_word_t,void*), void* data) { ase_word_t index, x; for (index = 0; index < stx->symtab.capacity; index++) { x = stx->symtab.datum[index]; if (x != stx->nil) func (stx, x, data); } }