| #ifdef UEMF |
| #include "uemf.h" |
| #else |
| #include "basic/basicInternal.h" |
| #endif |
| |
| static int calcPrime(int size); |
| |
| typedef struct { |
| int inuse; |
| int hash_size; |
| sym_t **hash_table; |
| } sym_tabent_t; |
| |
| static int symMax; |
| static int hashIndex(sym_tabent_t *tp, char_t *name); |
| static int htIndex; |
| static sym_t *hash(sym_tabent_t *tp, char_t *name); |
| static sym_t *next; |
| static sym_tabent_t **sym; |
| |
| sym_fd_t symOpen(int hash_size) |
| { |
| sym_fd_t sd; |
| sym_tabent_t *tp; |
| |
| a_assert(hash_size > 2); |
| |
| if ((sd = hAlloc((void***) &sym)) < 0) { |
| return -1; |
| } |
| |
| if ((tp = (sym_tabent_t*) balloc(B_L, sizeof(sym_tabent_t))) == NULL) { |
| symMax = hFree((void***) &sym, sd); |
| return -1; |
| } |
| memset(tp, 0, sizeof(sym_tabent_t)); |
| if (sd >= symMax) { |
| symMax = sd + 1; |
| } |
| a_assert(0 <= sd && sd < symMax); |
| sym[sd] = tp; |
| |
| tp->hash_size = calcPrime(hash_size); |
| tp->hash_table = (sym_t**) balloc(B_L, tp->hash_size * sizeof(sym_t*)); |
| a_assert(tp->hash_table); |
| if(tp->hash_table) |
| memset(tp->hash_table, 0, tp->hash_size * sizeof(sym_t*)); |
| |
| return sd; |
| } |
| |
| void symClose(sym_fd_t sd) |
| { |
| sym_tabent_t *tp; |
| sym_t *sp, *forw; |
| int i; |
| |
| a_assert(0 <= sd && sd < symMax); |
| tp = sym[sd]; |
| a_assert(tp); |
| |
| for (i = 0; i < tp->hash_size; i++) { |
| for (sp = tp->hash_table[i]; sp; sp = forw) { |
| forw = sp->forw; |
| valueFree(&sp->name); |
| valueFree(&sp->content); |
| bfree(B_L, (void*) sp); |
| sp = forw; |
| } |
| } |
| bfree(B_L, (void*) tp->hash_table); |
| |
| symMax = hFree((void***) &sym, sd); |
| bfree(B_L, (void*) tp); |
| } |
| |
| sym_t* symFirst(sym_fd_t sd) |
| { |
| sym_tabent_t *tp; |
| sym_t *sp, *forw; |
| int i; |
| |
| a_assert(0 <= sd && sd < symMax); |
| tp = sym[sd]; |
| a_assert(tp); |
| |
| for (i = 0; i < tp->hash_size; i++) { |
| |
| #if 0 // KW 3 cov M |
| for (sp = tp->hash_table[i]; sp; sp = forw) { |
| forw = sp->forw; |
| |
| if (forw == NULL) { |
| htIndex = i + 1; |
| next = tp->hash_table[htIndex]; |
| } else { |
| htIndex = i; |
| next = forw; |
| } |
| return sp; |
| } |
| #else |
| sp = tp->hash_table[i]; |
| if(NULL != sp){ |
| forw = sp->forw; |
| |
| if (forw == NULL) { |
| htIndex = i + 1; |
| next = tp->hash_table[htIndex]; |
| } else { |
| htIndex = i; |
| next = forw; |
| } |
| return sp; |
| } |
| |
| #endif |
| } |
| return NULL; |
| } |
| |
| sym_t* symNext(sym_fd_t sd) |
| { |
| sym_tabent_t *tp; |
| sym_t *sp, *forw; |
| int i; |
| |
| a_assert(0 <= sd && sd < symMax); |
| tp = sym[sd]; |
| a_assert(tp); |
| |
| for (i = htIndex; i < tp->hash_size; i++) { |
| |
| #if 0 // kw 3 cov M |
| for (sp = next; sp; sp = forw) { |
| forw = sp->forw; |
| |
| if (forw == NULL) { |
| htIndex = i + 1; |
| next = tp->hash_table[htIndex]; |
| } else { |
| htIndex = i; |
| next = forw; |
| } |
| return sp; |
| } |
| #else |
| sp = next; |
| if(NULL != sp) { |
| forw = sp->forw; |
| |
| if (forw == NULL) { |
| htIndex = i + 1; |
| next = tp->hash_table[htIndex]; |
| } else { |
| htIndex = i; |
| next = forw; |
| } |
| return sp; |
| } |
| |
| #endif |
| next = tp->hash_table[i + 1]; |
| } |
| return NULL; |
| } |
| |
| |
| sym_t *symEnter(sym_fd_t sd, char_t *name, value_t v, int arg) |
| { |
| sym_tabent_t *tp; |
| sym_t *sp, *last; |
| char_t *cp; |
| int hindex; |
| |
| a_assert(name); |
| a_assert(0 <= sd && sd < symMax); |
| tp = sym[sd]; |
| a_assert(tp); |
| |
| last = NULL; |
| hindex = hashIndex(tp, name); |
| if ((sp = tp->hash_table[hindex]) != NULL) { |
| for (; sp; sp = sp->forw) { |
| cp = sp->name.value.string; |
| if (cp[0] == name[0] && gstrcmp(cp, name) == 0) { |
| break; |
| } |
| last = sp; |
| } |
| if (sp) { |
| |
| if (sp->content.valid) { |
| valueFree(&sp->content); |
| } |
| sp->content = v; |
| sp->arg = arg; |
| return sp; |
| } |
| |
| sp = (sym_t*) balloc(B_L, sizeof(sym_t)); |
| if (sp == NULL) { |
| return NULL; |
| } |
| sp->content = v; |
| sp->forw = (sym_t*) NULL; |
| sp->name = valueString(name, VALUE_ALLOCATE); |
| sp->arg = arg; |
| last->forw = sp; |
| |
| } else { |
| sp = (sym_t*) balloc(B_L, sizeof(sym_t)); |
| if (sp == NULL) { |
| return NULL; |
| } |
| tp->hash_table[hindex] = sp; |
| tp->hash_table[hashIndex(tp, name)] = sp; |
| |
| sp->arg = arg; |
| sp->content = v; |
| sp->name = valueString(name, VALUE_ALLOCATE); |
| sp->forw = (sym_t*) NULL; |
| } |
| return sp; |
| } |
| |
| sym_t *symLookup(sym_fd_t sd, char_t *name) |
| { |
| sym_tabent_t *tp; |
| sym_t *sp; |
| char_t *cp; |
| |
| a_assert(0 <= sd && sd < symMax); |
| if ((tp = sym[sd]) == NULL) { |
| return NULL; |
| } |
| |
| if (name == NULL || *name == '\0') { |
| return NULL; |
| } |
| |
| |
| for (sp = hash(tp, name); sp; sp = sp->forw) { |
| cp = sp->name.value.string; |
| if (cp[0] == name[0] && gstrcmp(cp, name) == 0) { |
| break; |
| } |
| } |
| return sp; |
| } |
| |
| int symDelete(sym_fd_t sd, char_t *name) |
| { |
| sym_t *last = NULL; |
| int hindex; |
| char_t *cp; |
| sym_t *sp; |
| sym_tabent_t *tp; |
| |
| a_assert(name && *name); |
| a_assert(0 <= sd && sd < symMax); |
| tp = sym[sd]; |
| a_assert(tp); |
| |
| hindex = hashIndex(tp, name); |
| if ((sp = tp->hash_table[hindex]) != NULL) { |
| for ( ; sp; sp = sp->forw) { |
| cp = sp->name.value.string; |
| if (cp[0] == name[0] && gstrcmp(cp, name) == 0) { |
| break; |
| } |
| last = sp; |
| } |
| } |
| if (sp == (sym_t*) NULL) { |
| return -1; |
| } |
| |
| if (last) { |
| last->forw = sp->forw; |
| } else { |
| tp->hash_table[hindex] = sp->forw; |
| } |
| valueFree(&sp->name); |
| valueFree(&sp->content); |
| bfree(B_L, (void*) sp); |
| |
| return 0; |
| } |
| |
| |
| |
| static int hashIndex(sym_tabent_t *tp, char_t *name) |
| { |
| unsigned int sum; |
| int i; |
| |
| a_assert(tp); |
| |
| i = 0; |
| sum = 0; |
| while (*name) { |
| sum += (((int) *name++) << i); |
| i = (i + 7) % (BITS(int) - BITSPERBYTE); |
| } |
| return sum % tp->hash_size; |
| } |
| |
| static int isPrime(int n) |
| { |
| int i, max; |
| |
| a_assert(n > 0); |
| |
| max = n / 2; |
| for (i = 2; i <= max; i++) { |
| if (n % i == 0) { |
| return 0; |
| } |
| } |
| return 1; |
| } |
| |
| static sym_t *hash(sym_tabent_t *tp, char_t *name) |
| { |
| a_assert(tp); |
| |
| return tp->hash_table[hashIndex(tp, name)]; |
| } |
| |
| static int calcPrime(int size) |
| { |
| int count; |
| |
| a_assert(size > 0); |
| |
| for (count = size; count > 0; count--) { |
| if (isPrime(count)) { |
| return count; |
| } |
| } |
| return 1; |
| } |
| |