aboutsummaryrefslogtreecommitdiff
path: root/bootstrap/util.c
blob: 4aebbe6fb0aaedd6572ed786fb8e34b986570dc4 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
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);
}