aboutsummaryrefslogtreecommitdiff
path: root/bootstrap/util.c
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2022-08-03 20:24:47 +0200
committerlemon <lsof@mailbox.org>2022-08-03 20:24:47 +0200
commit1625c50f0c0e4b1c7ba01a5df5713efaf6dce606 (patch)
treebc5f24811413749b776964c1bbdec13a46dd9768 /bootstrap/util.c
initial
Diffstat (limited to 'bootstrap/util.c')
-rw-r--r--bootstrap/util.c105
1 files changed, 105 insertions, 0 deletions
diff --git a/bootstrap/util.c b/bootstrap/util.c
new file mode 100644
index 0000000..4aebbe6
--- /dev/null
+++ b/bootstrap/util.c
@@ -0,0 +1,105 @@
+#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 = 32, m;
+ char *str = xcalloc(n, 1);
+ va_start(ap, fmt);
+ m = vsnprintf(str, n, fmt, ap) + 1;
+ if (m > n) {
+ va_copy(aq, ap);
+ str = xrealloc(str, m);
+ vsprintf(str, fmt, ap);
+ va_end(aq);
+ }
+ va_end(ap);
+ 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;
+
+ fprintf(stderr, "%s:%d:%d: error: ", fileid2path(span.fileid), span.line, span.col);
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, "\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;
+ fprintf(stderr, " 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) {
+ fprintf(stderr, " ... (some expansions omitted)\n");
+ }
+ }
+ va_end(ap);
+ exit(127);
+}