From 374312cde4d44f8849d602cc5c9ea634798b9c50 Mon Sep 17 00:00:00 2001 From: "H. Peter Anvin (Intel)" Date: Fri, 14 Dec 2018 00:17:13 -0800 Subject: strlist, warnings: improve strlist, buffer warnings until error Make strlist_free() take a pointer to a pointer, so we can set it to NULL. Buffer warnings on a strlist until we either get an error or we are in pass 2. Hopefully this should let us get rid of a lot of the ERR_PASS* bullshit, which far too often causes messages to get lost. asm/labels.c contains one example of a warning that cannot be made correct with a specific pass number. Signed-off-by: H. Peter Anvin (Intel) --- asm/labels.c | 4 ++-- asm/listing.c | 3 +-- asm/nasm.c | 47 +++++++++++++++++++++++++++++++++++++++++------ include/strlist.h | 4 ++-- nasmlib/strlist.c | 37 +++++++++++++++++++++++++++---------- 5 files changed, 73 insertions(+), 22 deletions(-) diff --git a/asm/labels.c b/asm/labels.c index 7d87503d..c8901cbf 100644 --- a/asm/labels.c +++ b/asm/labels.c @@ -511,9 +511,9 @@ void define_label(const char *label, int32_t segment, *! value is identical. It is an unconditional error to *! define the same label more than once to \e{different} values. */ - nasm_warnf(WARN_LABEL_REDEF|ERR_PASS2, + nasm_warnf(WARN_LABEL_REDEF, "label `%s' redefined to an identical value", lptr->defn.label); - noteflags = ERR_NOTE|ERR_HERE|WARN_LABEL_REDEF|ERR_PASS2; + noteflags = ERR_NOTE|ERR_HERE|WARN_LABEL_REDEF; } src_get(&saved_line, &saved_fname); diff --git a/asm/listing.c b/asm/listing.c index 10ed7249..67c07fc9 100644 --- a/asm/listing.c +++ b/asm/listing.c @@ -126,8 +126,7 @@ static void list_emit(void) fprintf(listfp, " %s\n", e->str); } - strlist_free(list_errors); - list_errors = NULL; + strlist_free(&list_errors); } } diff --git a/asm/nasm.c b/asm/nasm.c index 3c8b877c..9fcbe200 100644 --- a/asm/nasm.c +++ b/asm/nasm.c @@ -90,6 +90,7 @@ struct error_format { static const struct error_format errfmt_gnu = { ":", "", ": " }; static const struct error_format errfmt_msvc = { "(", ")", " : " }; static const struct error_format *errfmt = &errfmt_gnu; +static struct strlist *warn_list; static bool using_debug_info, opt_verbose_info; static const char *debug_format; @@ -388,7 +389,7 @@ static void emit_dependencies(struct strlist *list) } } - strlist_free(list); + strlist_free(&list); if (deps != stdout) fclose(deps); @@ -635,7 +636,7 @@ int main(int argc, char **argv) eval_cleanup(); stdscan_cleanup(); src_free(); - strlist_free(include_path); + strlist_free(&include_path); return terminate_after_phase; } @@ -1117,6 +1118,7 @@ static bool process_arg(char *p, char *q, int pass) break; } + olen = 0; /* Placates gcc at lower optimization levels */ plen = strlen(p); for (tx = textopts; tx->label; tx++) { olen = strlen(tx->label); @@ -1426,6 +1428,18 @@ static void assemble_file(const char *fname, struct strlist *depend_list) pass2 = passn > 1 ? 2 : 1; /* 1, 2, 2, ..., 2, 2 */ /* pass0 0, 0, 0, ..., 1, 2 */ + /* + * Create a warning buffer list unless we are in pass 2 (everything will be + * emitted immediately in pass 2.) + */ + if (warn_list) { + if (warn_list->nstr || pass0 == 2) + strlist_free(&warn_list); + } + + if (pass0 < 2 && !warn_list) + warn_list = strlist_alloc(false); + globalbits = cmd_sb; /* set 'bits' to command line default */ cpu = cmd_cpu; if (pass0 == 2) { @@ -1691,8 +1705,10 @@ static void assemble_file(const char *fname, struct strlist *depend_list) } } + strlist_free(&warn_list); preproc->cleanup(0); lfmt->cleanup(); + if (!terminate_after_phase && opt_verbose_info) { /* -On and -Ov switches */ fprintf(stdout, "info: assembly required 1+%"PRId64"+1 passes\n", @@ -1844,10 +1860,29 @@ static void nasm_verror_asm(errflags severity, const char *fmt, va_list args) } if (!skip_this_pass(severity)) { - fprintf(error_file, "%s%s%s%s%s%s%s\n", - currentfile ? currentfile : "nasm", - linestr, errfmt->beforemsg, pfx, msg, - (severity & ERR_HERE) ? " here" : "", warnsuf); + const char *file = currentfile ? currentfile : "nasm"; + const char *here = (severity & ERR_HERE) ? " here" : ""; + + if (warn_list && true_type < ERR_NONFATAL) { + /* + * Buffer up warnings until we either get an error + * or we are on the code-generation pass. + */ + strlist_printf(warn_list, "%s%s%s%s%s%s%s", + file, linestr, errfmt->beforemsg, + pfx, msg, here, warnsuf); + } else { + /* If we have buffered warnings, output them now. */ + if (warn_list) { + strlist_write(warn_list, "\n", error_file); + strlist_free(&warn_list); + } + + fprintf(error_file, "%s%s%s%s%s%s%s\n", + file, linestr, errfmt->beforemsg, + pfx, msg, here, warnsuf); + + } } /* Are we recursing from error_list_macros? */ diff --git a/include/strlist.h b/include/strlist.h index b0e2919b..610aad4d 100644 --- a/include/strlist.h +++ b/include/strlist.h @@ -71,7 +71,6 @@ static inline size_t strlist_size(const struct strlist *list) } struct strlist safe_alloc *strlist_alloc(bool uniq); -void strlist_free(struct strlist *list); const struct strlist_entry * never_null strlist_add(struct strlist *list, const char *str); const struct strlist_entry * printf_func(2, 3) never_null strlist_printf(struct strlist *list, const char *fmt, ...); @@ -80,7 +79,8 @@ const struct strlist_entry * never_null const struct strlist_entry * strlist_find(const struct strlist *list, const char *str); void * safe_alloc strlist_linearize(const struct strlist *list, char sep); -void strlist_free(struct strlist *list); +void strlist_write(const struct strlist *list, const char *sep, FILE *f); +void strlist_free(struct strlist **listp); #define strlist_for_each(p,h) list_for_each((p), strlist_head(h)) #endif /* NASM_STRLIST_H */ diff --git a/nasmlib/strlist.c b/nasmlib/strlist.c index 93a6787f..506ad50e 100644 --- a/nasmlib/strlist.c +++ b/nasmlib/strlist.c @@ -136,21 +136,24 @@ strlist_printf(struct strlist *list, const char *fmt, ...) } /* - * Free a string list + * Free a string list. Sets the pointed to pointer to NULL. */ -void strlist_free(struct strlist *list) +void strlist_free(struct strlist **listp) { - if (list) { - struct strlist_entry *e, *tmp; + struct strlist *list = *listp; + struct strlist_entry *e, *tmp; - if (list->uniq) - hash_free(&list->hash); + if (!list) + return; - list_for_each_safe(e, tmp, list->head) - nasm_free(e); + if (list->uniq) + hash_free(&list->hash); - nasm_free(list); - } + list_for_each_safe(e, tmp, list->head) + nasm_free(e); + + nasm_free(list); + *listp = NULL; } /* @@ -187,3 +190,17 @@ void *strlist_linearize(const struct strlist *list, char sep) return buf; } + +/* + * Output a string list to a file. The separator can be any string. + */ +void strlist_write(const struct strlist *list, const char *sep, FILE *f) +{ + const struct strlist_entry *sl; + size_t seplen = strlen(sep); + + strlist_for_each(sl, list) { + fwrite(sl->str, 1, sl->size - 1, f); + fwrite(sep, 1, seplen, f); + } +} -- cgit v1.2.1