import "util.hff"; import "cffc.hff"; import "set.hff"; import "mem.hff"; import "common.hff"; extern fn xmalloc(n usize) *void { let p = malloc(n); assert(p != #null, "malloc"); return p; } extern fn xcalloc(n usize, m usize) *void { let p = calloc(n, m); assert(p != #null, "calloc"); return p; } extern fn xrealloc(p *void, n usize) *void { let p = realloc(p, n); assert(p != #null, "realloc"); return p; } extern fn xstrdup(str *const u8) *u8 { let p = xmalloc(strlen(str) + 1); strcpy(p, str); return p; } extern fn fnv1a(h u32, d [#]const u8) u32 { foreach(i, x, d) { h ^= x; h *= 0x01000193; } return h; } extern fn fnv1a_s(h u32, str *const u8) u32 { while *str != 0 { h ^= *str++; h *= 0x01000193; } return h; } extern fn fnv1a_i(h u32, x i64) u32 { return fnv1a(h, (as(*u8)&x)[0::8]); } static filepaths [64]*const u8 = {}; static nfilepaths int = 0; extern fn addfilepath(s *const u8) int { let i0 = fnv1a_s(FNV1A_INI, s) % filepaths.#len; let i int = i0; do { if filepaths[i] == #null { break; } else if streq(filepaths[i], s) { return i; } } while (i = (i + 1) % filepaths.#len) != i0; assert(nfilepaths++ < filepaths.#len, "too many files"); filepaths[i] = s; return i; } extern fn fileid2path(id int) *const u8 { assert(id >= 0 and id < filepaths.#len, "fileid"); let s = filepaths[id]; // assert(s != #null, "fileid %d", id); return s; } extern fn internstr(s *const u8) *const u8 { static set Set<*const u8, struct { fn hash(s *const u8) u32 { return fnv1a_s(FNV1A_INI, s); } fn eq(a *const u8, b *const u8) bool { return a != #null and b != #null and streq(a, b); } fn dup(s *const u8) *const u8 { return xstrdup(s); } }> = {}; return *set->intern(s); }