From b4a3f6828478f1d831ae11ee4d3dcd82b93407c8 Mon Sep 17 00:00:00 2001 From: Jo-Philipp Wich Date: Fri, 5 Aug 2022 12:01:39 +0200 Subject: compiler: improve formatting of nested syntax error messages Indent inner messages and prepend them with a vertical bar to increase visual separation of messages. Also include file name in source context output when the compiled program contains more than one source file. Adjust affected testcase outputs accordingly. Signed-off-by: Jo-Philipp Wich --- compiler.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 46 insertions(+), 7 deletions(-) (limited to 'compiler.c') diff --git a/compiler.c b/compiler.c index dc6afea..0042c15 100644 --- a/compiler.c +++ b/compiler.c @@ -169,10 +169,11 @@ uc_compiler_current_source(uc_compiler_t *compiler) __attribute__((format(printf, 3, 0))) static void uc_compiler_syntax_error(uc_compiler_t *compiler, size_t off, const char *fmt, ...) { + uc_source_t *source = uc_compiler_current_source(compiler); uc_stringbuf_t *buf = compiler->parser->error; size_t line = 0, byte = 0, len = 0; + char *s, *p, *nl; va_list ap; - char *s; if (compiler->parser->synchronizing) return; @@ -188,7 +189,7 @@ uc_compiler_syntax_error(uc_compiler_t *compiler, size_t off, const char *fmt, . if (off) { byte = off; - line = uc_source_get_line(uc_compiler_current_source(compiler), &byte); + line = uc_source_get_line(source, &byte); } va_start(ap, fmt); @@ -196,15 +197,53 @@ uc_compiler_syntax_error(uc_compiler_t *compiler, size_t off, const char *fmt, . va_end(ap); ucv_stringbuf_append(buf, "Syntax error: "); - ucv_stringbuf_addstr(buf, s, len); - ucv_stringbuf_append(buf, "\n"); + + p = strstr(s, "\nSyntax error: "); + + if (!p) { + ucv_stringbuf_addstr(buf, s, len); + ucv_stringbuf_append(buf, "\n"); + } + else { + ucv_stringbuf_printf(buf, "%.*s\n\n", (int)(p - s), s); + + while (len > 0 && s[len-1] == '\n') + s[--len] = 0; + + for (p++, nl = strchr(p, '\n'); p != NULL; + p = nl ? nl + 1 : NULL, nl = p ? strchr(p, '\n') : NULL) + { + if (!nl) + ucv_stringbuf_printf(buf, " | %s", p); + else if (nl != p) + ucv_stringbuf_printf(buf, " | %.*s\n", (int)(nl - p), p); + else + ucv_stringbuf_append(buf, " |\n"); + } + + ucv_stringbuf_append(buf, "\n\n"); + } free(s); - if (line) - ucv_stringbuf_printf(buf, "In line %zu, byte %zu:\n", line, byte); + if (line) { + ucv_stringbuf_append(buf, "In "); + + if (compiler->program->sources.count > 1) { + len = strlen(source->filename); + + if (len > 48) + ucv_stringbuf_printf(buf, "...%s", source->filename + len - 45); + else + ucv_stringbuf_addstr(buf, source->filename, len); + + ucv_stringbuf_append(buf, ", "); + } + + ucv_stringbuf_printf(buf, "line %zu, byte %zu:\n", line, byte); + } - if (uc_error_context_format(buf, uc_compiler_current_source(compiler), NULL, off)) + if (uc_error_context_format(buf, source, NULL, off)) ucv_stringbuf_append(buf, "\n\n"); } -- cgit v1.2.3