aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--c/lex.c53
-rw-r--r--common.h3
-rw-r--r--io.c2
3 files changed, 43 insertions, 15 deletions
diff --git a/c/lex.c b/c/lex.c
index 7ee1c0b..0680e58 100644
--- a/c/lex.c
+++ b/c/lex.c
@@ -1,6 +1,7 @@
#include "lex.h"
#include "../version.h"
#include <string.h>
+#include <stdlib.h>
/* fill internal circular character buffer with input after translation phase 1 & 2
* (trigraph substitution and backslash-newline deletion */
@@ -729,6 +730,41 @@ findmac(internstr name)
static void popmac(struct lexer *);
+static struct macrostack {
+ struct rlist rlist;
+ struct span0 exspan;
+ int idx;
+ short macid;
+ bool stop;
+ bool dofree;
+} mstk[64];
+
+static void NORETURN
+lxfatal(struct lexer *lx, const struct span *span, const char *fmt, ...)
+{
+ if (fmt) {
+ va_list ap;
+ va_start(ap, fmt);
+ vdiag(span, DGERROR, fmt, ap);
+ va_end(ap);
+ }
+ int n = lx->macstk ? lx->macstk - mstk : 0, i = 0;
+ for (struct macrostack *l = lx->macstk; l && l > mstk; --l, ++i) {
+ if (i < 4 || i > n - 5) {
+ note(&(struct span){l->exspan}, "expanded from here");
+ } else if (i == 5) {
+ efmt(" (...) \n");
+ }
+ }
+ for (struct lexer *sv = lx->save; sv; sv = sv->save) {
+ int line;
+ const char *f = getfilepos(&line, NULL, sv->fileid, sv->chridx-2);
+ note(NULL, "in file included from %s:%d", f, line);
+ }
+ if (!fmt || span) efmt("Aborting due to previous error.\n");
+ exit(1);
+}
+
static void
ppskipline(struct lexer *lx)
{
@@ -740,7 +776,7 @@ ppskipline(struct lexer *lx)
while (!((c = peek(lx, 0)) == '*' && peek(lx, 1) == '/')) {
if (lx->eof) {
struct span span = {{ lx->idx, lx->chridx - lx->idx, lx->fileid }};
- fatal(&span, "unterminated comment");
+ lxfatal(lx, &span, "unterminated comment");
}
done = c == '\n';
next(lx);
@@ -927,21 +963,12 @@ ppundef(struct lexer *lx)
delmac(tk.name);
}
-static struct macrostack {
- struct rlist rlist;
- struct span0 exspan;
- int idx;
- short macid;
- bool stop;
- bool dofree;
-} mstk[64];
-
static void
pushmacstk(struct lexer *lx, const struct span *span, const struct macrostack *m)
{
struct macrostack *l = lx->macstk;
if (!l) l = mstk;
- else if ((++l == mstk+countof(mstk))) fatal(span, "macro depth limit reached");
+ else if ((++l == mstk+countof(mstk))) lxfatal(lx, span, "macro depth limit reached");
*l = *m;
l->idx = 0;
l->exspan = span->ex;
@@ -1065,7 +1092,7 @@ expandfnmacro(struct lexer *lx, struct span *span, internstr mname, struct macro
if (tk.t == TKEOF) {
joinspan(&span->ex, tk.span.ex);
- fatal(span, "unterminated function-like macro invocation");
+ lxfatal(lx, span, "unterminated function-like macro invocation");
} else if (i < mac->nparam) {
++narg;
args[i].idx = cur;
@@ -1599,7 +1626,7 @@ tryinclude(struct lexer *lx, const struct span *span, char *path)
*lx = new;
if (++includedepth == MAXINCLUDE)
- fatal(span, "Maximum nested include depth of %d reached", includedepth);
+ lxfatal(lx, span, "Maximum nested include depth of %d reached", includedepth);
break;
case LXFILESKIP:
xbfree(path);
diff --git a/common.h b/common.h
index ef4d4d7..0c4945e 100644
--- a/common.h
+++ b/common.h
@@ -435,6 +435,9 @@ void markfileonce(int id, internstr guard);
void markfileseen(int id);
bool isfileseen(int id);
void closefile(int id);
+
+enum diagkind { DGERROR, DGWARN, DGNOTE, };
+void vdiag(const struct span *, enum diagkind, const char *, va_list);
NORETURN void fatal(const struct span *, const char *, ...);
void error(const struct span *, const char *, ...);
void warn(const struct span *, const char *, ...);
diff --git a/io.c b/io.c
index 0211320..e10c798 100644
--- a/io.c
+++ b/io.c
@@ -1022,8 +1022,6 @@ closefile(int id)
mapclose(&fileht[id]->f);
}
-enum diagkind { DGERROR, DGWARN, DGNOTE, };
-
void
vdiag(const struct span *span, enum diagkind kind, const char *fmt, va_list ap)
{