#include "all.h" // Bob Jenkins's one_at_a_time hash u32 jkhash(u32 h, const u8 *data, size_t length) { size_t i = 0; while (i != length) { h += data[i++]; h += h << 10; h ^= h >> 6; } h += h << 3; h ^= h >> 11; h += h << 15; return h; } static const char *filepaths[100]; static int nfilepaths = 0; int addfilepath(const char *s) { for (int i = 0; i < nfilepaths; ++i) if (!strcmp(filepaths[i], s)) return i; assert(nfilepaths < sizeof filepaths); filepaths[nfilepaths] = s; return nfilepaths++; } const char *fileid2path(int id) { assert(id < nfilepaths); return filepaths[id]; } void * xmalloc(size_t n) { void *p = malloc(n); assert(p && "malloc"); return p; } void * xcalloc(size_t n, size_t m) { void *p = calloc(n,m); assert(p && "calloc"); return p; } void * xrealloc(void *p, size_t n) { if (!p) return xmalloc(n); if (!n) return free(p), NULL; p = realloc(p, n); assert(p && "realloc"); return p; } char * xasprintf(const char *fmt, ...) { va_list ap, aq; int n = 16, m; char *str = xcalloc(n, 1); va_start(ap, fmt); m = vsnprintf(str, n, fmt, ap) + 1; str = xrealloc(str, m); if (m > n) { va_copy(aq, ap); vsprintf(str, fmt, ap); va_end(aq); } va_end(ap); assert(str); return str; } char * xstrdup(const char *s) { return strcpy(xmalloc(strlen(s) + 1), s); } void noreturn fatal(struct parser *P, struct span span, const char *fmt, ...) { va_list ap; va_start(ap, fmt); int i = 0; epri("%s:%d:%d: error: ", fileid2path(span.fileid), span.line, span.col); vepri(fmt, ap); epri("\n"); for (struct expan *ep = P->curexpan; ep; ep = ep->prev, ++i) { if (ep->name && (i < 8 || !ep->prev || !ep->prev->prev)) { span = ep->span; epri(" while expanding macro `%s' at %s:%d:%d\n", ep->name, fileid2path(ep->span.fileid), span.line, span.col); } else if (ep->name && i == 10) { epri(" ... (some expansions omitted)\n"); } } va_end(ap); exit(127); }