#include #include #include #include #define ALIGN(n) (((n) + 7) & ~7) static Sy *find(St *tab, const char *str, U32 hash, Z len) { if (tab->capacity == 0) return NULL; Z ix = hash % tab->capacity; for (Z i = 0; i < tab->capacity; i++) { Sy *s = tab->data[ix]; if (!s) return NULL; if (s->hash == hash && s->len == len) return s; if (memcmp(s->data, str, len) == 0) return s; ix = (ix + 1) % tab->capacity; } return NULL; } static V resize(St *tab) { Z cap = tab->capacity == 0 ? 16 : tab->capacity * 2; Sy **nb = calloc(cap, sizeof(Sy *)); for (Z i = 0; i < tab->capacity; i++) { if (tab->data[i]) { Sy *s = tab->data[i]; Z ix = s->hash % cap; while (nb[ix]) ix = (ix + 1) % cap; nb[ix] = s; } } if (tab->data != NULL) free(tab->data); tab->capacity = cap; tab->data = nb; } static U32 hashstr(const char *data, Z len) { U32 hash = 2166136261u; for (Z i = 0; i < len; i++) { hash ^= (uint8_t)data[i]; hash *= 16777619u; } return hash; } Sy *intern(St *tab, const char *str, Z len) { if (len == 0) len = strlen(str); U32 hash = hashstr(str, len); Sy *sym = find(tab, str, hash, len); if (sym) return sym; sym = aligned_alloc(8, ALIGN(sizeof(Sy))); if (!sym) { fprintf(stderr, "failed to allocate memory for symbol\n"); abort(); } sym->data = malloc(len); memcpy(sym->data, str, len); sym->len = len; sym->hash = hash; if (tab->count + 1 > tab->capacity) resize(tab); Z idx = hash % tab->capacity; while (tab->data[idx] != NULL) idx = (idx + 1) % tab->capacity; tab->data[idx] = sym; tab->count++; return sym; } O symbol_make(In *in, const char *str) { return BOX(TAG(intern(&in->symtab, str, 0), TAG_SYM)); }