aboutsummaryrefslogtreecommitdiffhomepage
path: root/io.c
diff options
context:
space:
mode:
author lemon<lsof@mailbox.org>2026-02-24 14:09:50 +0100
committer lemon<lsof@mailbox.org>2026-02-24 14:17:54 +0100
commitfa8c39d6dfdecc8285b09de86b70c28ebd06e152 (patch)
tree30adfe0ea6807ecf7dd527b941870e08f2ac0f35 /io.c
parentf73f0301fd2d4306f173984fc8089ad463da26fe (diff)
io: use distinct output buffer for diagnostics
Prevents concurrent invokations of the compiler from mixing up and mangling diagnostics from unbuffered stderr.
Diffstat (limited to 'io.c')
-rw-r--r--io.c38
1 files changed, 24 insertions, 14 deletions
diff --git a/io.c b/io.c
index 9da7b7c..e4e04bb 100644
--- a/io.c
+++ b/io.c
@@ -1025,22 +1025,30 @@ closefile(int id)
void
vdiag(const struct span *span, enum diagkind kind, const char *fmt, va_list ap)
{
+ /* to avoid concurrent invocations of the compiler mixing up the diagnostics
+ * in the unbuffered stderr output, use a separate buffer here and write()
+ * it all out bypassing stdio */
+ static char ebuf[4096];
+ struct wbuf out = FDBUF(ebuf, sizeof ebuf, STDERR_FILENO);
+ static int depth = 0; /* needed for nested note() calls */
+
static const char *label[] = { "error", "warning", "note" };
static const char *color[] = { "%g1;31.", "%g1;35.", "%g1;36." };
int line, col;
struct memfile *f;
const struct span0 *loc;
+ ++depth;
if (span) {
loc = span->ex.len ? &span->ex : &span->sl;
f = getfile(loc->file);
const char *file = getfilepos(&line, &col, loc->file, loc->off);
- efmt("%s:%d:%d: ", file, line, col);
+ bfmt(&out, "%s:%d:%d: ", file, line, col);
}
- efmt(color[kind]);
- efmt("%s: %g.", label[kind]);
- vbfmt(&bstderr, fmt, ap);
- efmt("\n");
+ bfmt(&out, color[kind]);
+ bfmt(&out, "%s: %g.", label[kind]);
+ vbfmt(&out, fmt, ap);
+ bfmt(&out, "\n");
if (span) {
uint i;
int nmark;
@@ -1053,7 +1061,7 @@ vdiag(const struct span *span, enum diagkind kind, const char *fmt, va_list ap)
nmark = loc->len;
while (i < loc->off + loc->len) {
int j, end;
- int curoff = efmt("%5d | ", line);
+ int curoff = bfmt(&out, "%5d | ", line);
const uchar *linep = &f->p[i];
bool begintabs = 1;
for (end = 0; f->p[i] != '\n' && i < f->n; ++i, ++end) {
@@ -1063,13 +1071,13 @@ vdiag(const struct span *span, enum diagkind kind, const char *fmt, va_list ap)
} else {
begintabs = 0;
}
- ioputc(&bstderr, c);
+ ioputc(&out, c);
}
- ioputc(&bstderr, '\n');
+ ioputc(&out, '\n');
++i;
for (j = -curoff; j < 0; ++j)
- ioputc(&bstderr, j == -2 ? '|' : ' ');
+ ioputc(&out, j == -2 ? '|' : ' ');
for (begintabs = 1; j < col-1; ++j) {
uchar c = *linep++;
if (c == '\t') {
@@ -1078,24 +1086,26 @@ vdiag(const struct span *span, enum diagkind kind, const char *fmt, va_list ap)
c = ' ';
begintabs = 0;
}
- ioputc(&bstderr, c);
+ ioputc(&out, c);
}
- efmt(color[kind]);
+ bfmt(&out, color[kind]);
do {
- ioputc(&bstderr, mark);
+ ioputc(&out, mark);
mark = '~';
} while (--nmark > 0 && ++j < end);
col = 1;
++line;
- efmt("%g.\n");
+ bfmt(&out, "%g.\n");
--nmark;
}
- ioputc(&bstderr, '\n');
+ ioputc(&out, '\n');
}
if (span && loc == &span->ex && span->sl.len)
if (span->ex.file != span->sl.file || !((uint) span->sl.off - span->ex.off < span->ex.len))
note(&(struct span){ span->sl }, "expanded from here");
+
+ if (--depth == 0) ioflush(&out);
}
void _Noreturn