From: Peter Johnson Date: Sat, 18 May 2002 09:55:42 +0000 (-0000) Subject: Revamp error/warning handling. X-Git-Tag: v0.2.0~217 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4fed536d3c090c72eaae6207579a5f9bc7fa7501;p=yasm Revamp error/warning handling. svn path=/trunk/yasm/; revision=622 --- diff --git a/frontends/yasm/yasm.c b/frontends/yasm/yasm.c index 37c86737..8a7c4c1b 100644 --- a/frontends/yasm/yasm.c +++ b/frontends/yasm/yasm.c @@ -204,7 +204,8 @@ main(int argc, char *argv[]) if (obj != stdout) fclose(obj); - if (OutputAllErrorWarning() > 0) { + if (GetNumErrors() > 0) { + OutputAllErrorWarning(); if (obj != stdout) remove(obj_filename); xfree(preproc_buf); @@ -263,7 +264,8 @@ main(int argc, char *argv[]) fclose(in); xfree(in_filename); - if (OutputAllErrorWarning() > 0) { + if (GetNumErrors() > 0) { + OutputAllErrorWarning(); cleanup(sections); return EXIT_FAILURE; } @@ -271,7 +273,8 @@ main(int argc, char *argv[]) symrec_parser_finalize(); basic_optimizer.optimize(sections); - if (OutputAllErrorWarning() > 0) { + if (GetNumErrors() > 0) { + OutputAllErrorWarning(); cleanup(sections); return EXIT_FAILURE; } @@ -295,13 +298,15 @@ main(int argc, char *argv[]) /* If we had an error at this point, we also need to delete the output * object file (to make sure it's not left newer than the source). */ - if (OutputAllErrorWarning() > 0) { + if (GetNumErrors() > 0) { + OutputAllErrorWarning(); cleanup(sections); if (obj != stdout) remove(obj_filename); return EXIT_FAILURE; } + OutputAllErrorWarning(); xfree(obj_filename); cleanup(sections); diff --git a/libyasm/errwarn.c b/libyasm/errwarn.c index 5f66d43b..b6cf7923 100644 --- a/libyasm/errwarn.c +++ b/libyasm/errwarn.c @@ -66,13 +66,14 @@ static const char *fatal_msgs[] = { }; /*@=observertrans@*/ -typedef /*@reldef@*/ STAILQ_HEAD(errwarnhead_s, errwarn_s) errwarnhead; -static /*@only@*/ /*@null@*/ errwarnhead *errwarns = (errwarnhead *)NULL; +typedef /*@reldef@*/ SLIST_HEAD(errwarnhead_s, errwarn_s) errwarnhead; +static /*@only@*/ /*@null@*/ errwarnhead errwarns = + SLIST_HEAD_INITIALIZER(errwarns); typedef struct errwarn_s { - /*@reldef@*/ STAILQ_ENTRY(errwarn_s) link; + /*@reldef@*/ SLIST_ENTRY(errwarn_s) link; - enum { WE_ERROR, WE_WARNING } type; + enum { WE_UNKNOWN, WE_ERROR, WE_WARNING, WE_PARSERERROR } type; unsigned long line; /* FIXME: This should not be a fixed size. But we don't have vasprintf() @@ -80,15 +81,8 @@ typedef struct errwarn_s { char msg[MSG_MAXSIZE]; } errwarn; -/* Line number of the previous error. Set and checked by Error(). */ -static unsigned long previous_error_line = 0; - -/* Is the last error a parser error? Error() lets other errors override parser - * errors. Set by yyerror(), read and reset by Error(). */ -static int previous_error_parser = 0; - -/* Line number of the previous warning. Set and checked by Warning(). */ -static unsigned long previous_warning_line = 0; +/* Last inserted error/warning. Used to speed up insertions. */ +static /*@null@*/ errwarn *previous_we = NULL; /* Static buffer for use by conv_unprint(). */ static char unprint[5]; @@ -115,14 +109,6 @@ conv_unprint(char ch) return unprint; } -/* Parser error handler. Moves error into our error handling system. */ -void -ParserError(const char *s) -{ - Error("%s %s", _("parser error:"), s); - previous_error_parser = 1; -} - /* Report an internal error. Essentially a fatal error with trace info. * Exit immediately because it's essentially an assert() trap. */ void @@ -150,201 +136,222 @@ Fatal(fatal_num num) #endif } -/* Register an error. Uses argtypes as described above to specify the - * argument types. Does not print the error, only stores it for - * OutputAllErrorWarning() to print. */ -void -Error(const char *fmt, ...) +/* Create an errwarn structure in the correct linked list location. + * If replace_parser_error is nonzero, overwrites the last error if its + * type is WE_PARSERERROR. + */ +errwarn * +errwarn_new(unsigned long lindex, int replace_parser_error) { - va_list ap; - errwarn *we; - - if ((previous_error_line == line_index) && !previous_error_parser) - return; + errwarn *first, *next, *ins_we, *we; + enum { INS_NONE, INS_HEAD, INS_AFTER } action = INS_NONE; - if (!errwarns) { - errwarns = xmalloc(sizeof(errwarnhead)); - STAILQ_INIT(errwarns); + /* Find the entry with either line=lindex or the last one with lineline) { + if (ins_we == first) + action = INS_HEAD; + else + ins_we = first; + } else if (!next) + action = INS_AFTER; + else if (lindex >= ins_we->line && lindex < next->line) + action = INS_AFTER; } - if (previous_error_parser) { - /* overwrite last (parser) error */ - we = STAILQ_LAST(errwarns, errwarn_s, link); + if (replace_parser_error && ins_we && ins_we->type == WE_PARSERERROR) { + /* overwrite last error */ + we = ins_we; } else { + /* add a new error */ we = xmalloc(sizeof(errwarn)); - we->type = WE_ERROR; - we->line = line_index; + we->type = WE_UNKNOWN; + we->line = lindex; + + if (action == INS_HEAD) + SLIST_INSERT_HEAD(&errwarns, we, link); + else if (action == INS_AFTER) { + assert(ins_we != NULL); + SLIST_INSERT_AFTER(ins_we, we, link); + } else + InternalError(_("Unexpected errwarn insert action")); } - assert(we != NULL); + /* Remember previous err/warn */ + previous_we = we; + + return we; +} + +/* Register an error. Does not print the error, only stores it for + * OutputAllErrorWarning() to print. + */ +void +error_common(unsigned long lindex, const char *fmt, va_list ap) +{ + errwarn *we = errwarn_new(lindex, 1); + + we->type = WE_ERROR; - va_start(ap, fmt); #ifdef HAVE_VSNPRINTF vsnprintf(we->msg, MSG_MAXSIZE, fmt, ap); #else vsprintf(we->msg, fmt, ap); #endif - va_end(ap); - - /*@-branchstate@*/ - if (!previous_error_parser) - STAILQ_INSERT_TAIL(errwarns, we, link); - /*@=branchstate@*/ - - previous_error_line = line_index; - previous_error_parser = 0; error_count++; } -/* Register a warning. Uses argtypes as described above to specify the - * argument types. Does not print the warning, only stores it for - * OutputAllErrorWarning() to print. */ +/* Register an warning. Does not print the warning, only stores it for + * OutputAllErrorWarning() to print. + */ void -Warning(const char *fmt, ...) +warning_common(unsigned long lindex, const char *fmt, va_list va) { - va_list ap; - errwarn *we; - - if (warnings_disabled) - return; - - if (previous_warning_line == line_index) - return; - - previous_warning_line = line_index; - - we = xmalloc(sizeof(errwarn)); + errwarn *we = errwarn_new(lindex, 0); we->type = WE_WARNING; - we->line = line_index; - va_start(ap, fmt); + #ifdef HAVE_VSNPRINTF - vsnprintf(we->msg, MSG_MAXSIZE, fmt, ap); + vsnprintf(we->msg, MSG_MAXSIZE, fmt, va); #else - vsprintf(we->msg, fmt, ap); + vsprintf(we->msg, fmt, va); #endif - va_end(ap); - if (!errwarns) { - errwarns = xmalloc(sizeof(errwarnhead)); - STAILQ_INIT(errwarns); - } - STAILQ_INSERT_TAIL(errwarns, we, link); warning_count++; } +/* Parser error handler. Moves YACC-style error into our error handling + * system. + */ void -ErrorNow(const char *fmt, ...) +ParserError(const char *s) { - va_list ap; + Error("%s %s", _("parser error:"), s); + previous_we->type = WE_PARSERERROR; +} - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - fprintf(stderr, "\n"); +/* Register an error during the parser stage (uses global line_index). Does + * not print the error, only stores it for OutputAllErrorWarning() to print. + */ +void +Error(const char *fmt, ...) +{ + va_list va; + va_start(va, fmt); + error_common(line_index, fmt, va); + va_end(va); } +/* Register an error at line lindex. Does not print the error, only stores it + * for OutputAllErrorWarning() to print. + */ void -WarningNow(const char *fmt, ...) +ErrorAt(unsigned long lindex, const char *fmt, ...) { - va_list ap; + va_list va; + va_start(va, fmt); + error_common(lindex, fmt, va); + va_end(va); +} - if (warnings_disabled) - return; +/* Register a warning during the parser stage (uses global line_index). Does + * not print the warning, only stores it for OutputAllErrorWarning() to print. + */ +void +Warning(const char *fmt, ...) +{ + va_list va; + va_start(va, fmt); + warning_common(line_index, fmt, va); + va_end(va); +} - fprintf(stderr, "%s ", _("warning:")); - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - fprintf(stderr, "\n"); +/* Register an warning at line lindex. Does not print the warning, only stores + * it for OutputAllErrorWarning() to print. + */ +void +WarningAt(unsigned long lindex, const char *fmt, ...) +{ + va_list va; + va_start(va, fmt); + warning_common(lindex, fmt, va); + va_end(va); } void -ErrorAt(unsigned long lindex, const char *fmt, ...) +ErrorNow(const char *fmt, ...) { - /* XXX: Should insert into list instead of printing immediately */ va_list ap; - const char *filename; - unsigned long line; - line_lookup(lindex, &filename, &line); - fprintf(stderr, "%s:%lu: ", filename?filename:"(NULL)", line); va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); fprintf(stderr, "\n"); - - error_count++; } void -WarningAt(unsigned long lindex, const char *fmt, ...) +WarningNow(const char *fmt, ...) { - /* XXX: Should insert into list instead of printing immediately */ va_list ap; - const char *filename; - unsigned long line; if (warnings_disabled) return; - line_lookup(lindex, &filename, &line); - fprintf(stderr, "%s:%lu: %s ", filename?filename:"NULL", line, - _("warning:")); + fprintf(stderr, "%s ", _("warning:")); va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); fprintf(stderr, "\n"); +} - warning_count++; +/* Get the number of errors (including warnings if warnings are being treated + * as errors). + */ +unsigned int +GetNumErrors(void) +{ + if (warning_error) + return error_count+warning_count; + else + return error_count; } /* Output all previously stored errors and warnings to stderr. */ -unsigned int +void OutputAllErrorWarning(void) { - errwarn *we, *we2; + errwarn *we; const char *filename; unsigned long line; - /* If errwarns hasn't been initialized, there are no messages. */ - if (!errwarns) { - if (warning_error) - return error_count+warning_count; - else - return error_count; - } - /* If we're treating warnings as errors, tell the user about it. */ if (warning_error && warning_error != 2) { fprintf(stderr, "%s\n", _("warnings being treated as errors")); warning_error = 2; } - /* Output error and warning messages. */ - STAILQ_FOREACH(we, errwarns, link) { + /* Output error/warning, then delete each message. */ + while (!SLIST_EMPTY(&errwarns)) { + we = SLIST_FIRST(&errwarns); + /* Output error/warning */ line_lookup(we->line, &filename, &line); if (we->type == WE_ERROR) fprintf(stderr, "%s:%lu: %s\n", filename, line, we->msg); else fprintf(stderr, "%s:%lu: %s %s\n", filename, line, _("warning:"), we->msg); - } - /* Delete messages. */ - we = STAILQ_FIRST(errwarns); - while (we) { - we2 = STAILQ_NEXT(we, link); + /* Delete */ + SLIST_REMOVE_HEAD(&errwarns, link); xfree(we); - we = we2; } - - /* Return the total error count up to this point. - * If we're treating warnings as errors, add that to the total as well. - */ - if (warning_error) - return error_count+warning_count; - return error_count; } diff --git a/libyasm/errwarn.h b/libyasm/errwarn.h index e55ac18a..bc95e328 100644 --- a/libyasm/errwarn.h +++ b/libyasm/errwarn.h @@ -71,8 +71,7 @@ void Error(const char *, ...) /*@printflike@*/; void Warning(const char *, ...) /*@printflike@*/; /* Use Error() and Warning() instead of ErrorAt() and WarningAt() when being - * called in line order from a parser. The *At() functions are much slower, - * at least in the current implementation. + * called in line order from a parser. */ void ErrorAt(unsigned long lindex, const char *, ...) /*@printflike@*/; void WarningAt(unsigned long lindex, const char *, ...) /*@printflike@*/; @@ -85,6 +84,9 @@ void ErrorNow(const char *, ...) /*@printflike@*/; void WarningNow(const char *, ...) /*@printflike@*/; /* Returns total number of errors to this point in assembly. */ -unsigned int OutputAllErrorWarning(void); +unsigned int GetNumErrors(void); + +/* Outputs all errors/warnings to standard error. */ +void OutputAllErrorWarning(void); #endif diff --git a/modules/objfmts/bin/tests/integer-warn.errwarn b/modules/objfmts/bin/tests/integer-warn.errwarn index 8be45269..973e8d39 100644 --- a/modules/objfmts/bin/tests/integer-warn.errwarn +++ b/modules/objfmts/bin/tests/integer-warn.errwarn @@ -1,6 +1,2 @@ ./src/objfmts/bin/tests/integer-warn.asm:5: warning: Numeric constant too large for internal format ./src/objfmts/bin/tests/integer-warn.asm:6: warning: Numeric constant too large for internal format -./src/objfmts/bin/tests/integer-warn.asm:5: warning: Numeric constant too large for internal format -./src/objfmts/bin/tests/integer-warn.asm:6: warning: Numeric constant too large for internal format -./src/objfmts/bin/tests/integer-warn.asm:5: warning: Numeric constant too large for internal format -./src/objfmts/bin/tests/integer-warn.asm:6: warning: Numeric constant too large for internal format diff --git a/src/errwarn.c b/src/errwarn.c index 5f66d43b..b6cf7923 100644 --- a/src/errwarn.c +++ b/src/errwarn.c @@ -66,13 +66,14 @@ static const char *fatal_msgs[] = { }; /*@=observertrans@*/ -typedef /*@reldef@*/ STAILQ_HEAD(errwarnhead_s, errwarn_s) errwarnhead; -static /*@only@*/ /*@null@*/ errwarnhead *errwarns = (errwarnhead *)NULL; +typedef /*@reldef@*/ SLIST_HEAD(errwarnhead_s, errwarn_s) errwarnhead; +static /*@only@*/ /*@null@*/ errwarnhead errwarns = + SLIST_HEAD_INITIALIZER(errwarns); typedef struct errwarn_s { - /*@reldef@*/ STAILQ_ENTRY(errwarn_s) link; + /*@reldef@*/ SLIST_ENTRY(errwarn_s) link; - enum { WE_ERROR, WE_WARNING } type; + enum { WE_UNKNOWN, WE_ERROR, WE_WARNING, WE_PARSERERROR } type; unsigned long line; /* FIXME: This should not be a fixed size. But we don't have vasprintf() @@ -80,15 +81,8 @@ typedef struct errwarn_s { char msg[MSG_MAXSIZE]; } errwarn; -/* Line number of the previous error. Set and checked by Error(). */ -static unsigned long previous_error_line = 0; - -/* Is the last error a parser error? Error() lets other errors override parser - * errors. Set by yyerror(), read and reset by Error(). */ -static int previous_error_parser = 0; - -/* Line number of the previous warning. Set and checked by Warning(). */ -static unsigned long previous_warning_line = 0; +/* Last inserted error/warning. Used to speed up insertions. */ +static /*@null@*/ errwarn *previous_we = NULL; /* Static buffer for use by conv_unprint(). */ static char unprint[5]; @@ -115,14 +109,6 @@ conv_unprint(char ch) return unprint; } -/* Parser error handler. Moves error into our error handling system. */ -void -ParserError(const char *s) -{ - Error("%s %s", _("parser error:"), s); - previous_error_parser = 1; -} - /* Report an internal error. Essentially a fatal error with trace info. * Exit immediately because it's essentially an assert() trap. */ void @@ -150,201 +136,222 @@ Fatal(fatal_num num) #endif } -/* Register an error. Uses argtypes as described above to specify the - * argument types. Does not print the error, only stores it for - * OutputAllErrorWarning() to print. */ -void -Error(const char *fmt, ...) +/* Create an errwarn structure in the correct linked list location. + * If replace_parser_error is nonzero, overwrites the last error if its + * type is WE_PARSERERROR. + */ +errwarn * +errwarn_new(unsigned long lindex, int replace_parser_error) { - va_list ap; - errwarn *we; - - if ((previous_error_line == line_index) && !previous_error_parser) - return; + errwarn *first, *next, *ins_we, *we; + enum { INS_NONE, INS_HEAD, INS_AFTER } action = INS_NONE; - if (!errwarns) { - errwarns = xmalloc(sizeof(errwarnhead)); - STAILQ_INIT(errwarns); + /* Find the entry with either line=lindex or the last one with lineline) { + if (ins_we == first) + action = INS_HEAD; + else + ins_we = first; + } else if (!next) + action = INS_AFTER; + else if (lindex >= ins_we->line && lindex < next->line) + action = INS_AFTER; } - if (previous_error_parser) { - /* overwrite last (parser) error */ - we = STAILQ_LAST(errwarns, errwarn_s, link); + if (replace_parser_error && ins_we && ins_we->type == WE_PARSERERROR) { + /* overwrite last error */ + we = ins_we; } else { + /* add a new error */ we = xmalloc(sizeof(errwarn)); - we->type = WE_ERROR; - we->line = line_index; + we->type = WE_UNKNOWN; + we->line = lindex; + + if (action == INS_HEAD) + SLIST_INSERT_HEAD(&errwarns, we, link); + else if (action == INS_AFTER) { + assert(ins_we != NULL); + SLIST_INSERT_AFTER(ins_we, we, link); + } else + InternalError(_("Unexpected errwarn insert action")); } - assert(we != NULL); + /* Remember previous err/warn */ + previous_we = we; + + return we; +} + +/* Register an error. Does not print the error, only stores it for + * OutputAllErrorWarning() to print. + */ +void +error_common(unsigned long lindex, const char *fmt, va_list ap) +{ + errwarn *we = errwarn_new(lindex, 1); + + we->type = WE_ERROR; - va_start(ap, fmt); #ifdef HAVE_VSNPRINTF vsnprintf(we->msg, MSG_MAXSIZE, fmt, ap); #else vsprintf(we->msg, fmt, ap); #endif - va_end(ap); - - /*@-branchstate@*/ - if (!previous_error_parser) - STAILQ_INSERT_TAIL(errwarns, we, link); - /*@=branchstate@*/ - - previous_error_line = line_index; - previous_error_parser = 0; error_count++; } -/* Register a warning. Uses argtypes as described above to specify the - * argument types. Does not print the warning, only stores it for - * OutputAllErrorWarning() to print. */ +/* Register an warning. Does not print the warning, only stores it for + * OutputAllErrorWarning() to print. + */ void -Warning(const char *fmt, ...) +warning_common(unsigned long lindex, const char *fmt, va_list va) { - va_list ap; - errwarn *we; - - if (warnings_disabled) - return; - - if (previous_warning_line == line_index) - return; - - previous_warning_line = line_index; - - we = xmalloc(sizeof(errwarn)); + errwarn *we = errwarn_new(lindex, 0); we->type = WE_WARNING; - we->line = line_index; - va_start(ap, fmt); + #ifdef HAVE_VSNPRINTF - vsnprintf(we->msg, MSG_MAXSIZE, fmt, ap); + vsnprintf(we->msg, MSG_MAXSIZE, fmt, va); #else - vsprintf(we->msg, fmt, ap); + vsprintf(we->msg, fmt, va); #endif - va_end(ap); - if (!errwarns) { - errwarns = xmalloc(sizeof(errwarnhead)); - STAILQ_INIT(errwarns); - } - STAILQ_INSERT_TAIL(errwarns, we, link); warning_count++; } +/* Parser error handler. Moves YACC-style error into our error handling + * system. + */ void -ErrorNow(const char *fmt, ...) +ParserError(const char *s) { - va_list ap; + Error("%s %s", _("parser error:"), s); + previous_we->type = WE_PARSERERROR; +} - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - fprintf(stderr, "\n"); +/* Register an error during the parser stage (uses global line_index). Does + * not print the error, only stores it for OutputAllErrorWarning() to print. + */ +void +Error(const char *fmt, ...) +{ + va_list va; + va_start(va, fmt); + error_common(line_index, fmt, va); + va_end(va); } +/* Register an error at line lindex. Does not print the error, only stores it + * for OutputAllErrorWarning() to print. + */ void -WarningNow(const char *fmt, ...) +ErrorAt(unsigned long lindex, const char *fmt, ...) { - va_list ap; + va_list va; + va_start(va, fmt); + error_common(lindex, fmt, va); + va_end(va); +} - if (warnings_disabled) - return; +/* Register a warning during the parser stage (uses global line_index). Does + * not print the warning, only stores it for OutputAllErrorWarning() to print. + */ +void +Warning(const char *fmt, ...) +{ + va_list va; + va_start(va, fmt); + warning_common(line_index, fmt, va); + va_end(va); +} - fprintf(stderr, "%s ", _("warning:")); - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - fprintf(stderr, "\n"); +/* Register an warning at line lindex. Does not print the warning, only stores + * it for OutputAllErrorWarning() to print. + */ +void +WarningAt(unsigned long lindex, const char *fmt, ...) +{ + va_list va; + va_start(va, fmt); + warning_common(lindex, fmt, va); + va_end(va); } void -ErrorAt(unsigned long lindex, const char *fmt, ...) +ErrorNow(const char *fmt, ...) { - /* XXX: Should insert into list instead of printing immediately */ va_list ap; - const char *filename; - unsigned long line; - line_lookup(lindex, &filename, &line); - fprintf(stderr, "%s:%lu: ", filename?filename:"(NULL)", line); va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); fprintf(stderr, "\n"); - - error_count++; } void -WarningAt(unsigned long lindex, const char *fmt, ...) +WarningNow(const char *fmt, ...) { - /* XXX: Should insert into list instead of printing immediately */ va_list ap; - const char *filename; - unsigned long line; if (warnings_disabled) return; - line_lookup(lindex, &filename, &line); - fprintf(stderr, "%s:%lu: %s ", filename?filename:"NULL", line, - _("warning:")); + fprintf(stderr, "%s ", _("warning:")); va_start(ap, fmt); vfprintf(stderr, fmt, ap); va_end(ap); fprintf(stderr, "\n"); +} - warning_count++; +/* Get the number of errors (including warnings if warnings are being treated + * as errors). + */ +unsigned int +GetNumErrors(void) +{ + if (warning_error) + return error_count+warning_count; + else + return error_count; } /* Output all previously stored errors and warnings to stderr. */ -unsigned int +void OutputAllErrorWarning(void) { - errwarn *we, *we2; + errwarn *we; const char *filename; unsigned long line; - /* If errwarns hasn't been initialized, there are no messages. */ - if (!errwarns) { - if (warning_error) - return error_count+warning_count; - else - return error_count; - } - /* If we're treating warnings as errors, tell the user about it. */ if (warning_error && warning_error != 2) { fprintf(stderr, "%s\n", _("warnings being treated as errors")); warning_error = 2; } - /* Output error and warning messages. */ - STAILQ_FOREACH(we, errwarns, link) { + /* Output error/warning, then delete each message. */ + while (!SLIST_EMPTY(&errwarns)) { + we = SLIST_FIRST(&errwarns); + /* Output error/warning */ line_lookup(we->line, &filename, &line); if (we->type == WE_ERROR) fprintf(stderr, "%s:%lu: %s\n", filename, line, we->msg); else fprintf(stderr, "%s:%lu: %s %s\n", filename, line, _("warning:"), we->msg); - } - /* Delete messages. */ - we = STAILQ_FIRST(errwarns); - while (we) { - we2 = STAILQ_NEXT(we, link); + /* Delete */ + SLIST_REMOVE_HEAD(&errwarns, link); xfree(we); - we = we2; } - - /* Return the total error count up to this point. - * If we're treating warnings as errors, add that to the total as well. - */ - if (warning_error) - return error_count+warning_count; - return error_count; } diff --git a/src/errwarn.h b/src/errwarn.h index e55ac18a..bc95e328 100644 --- a/src/errwarn.h +++ b/src/errwarn.h @@ -71,8 +71,7 @@ void Error(const char *, ...) /*@printflike@*/; void Warning(const char *, ...) /*@printflike@*/; /* Use Error() and Warning() instead of ErrorAt() and WarningAt() when being - * called in line order from a parser. The *At() functions are much slower, - * at least in the current implementation. + * called in line order from a parser. */ void ErrorAt(unsigned long lindex, const char *, ...) /*@printflike@*/; void WarningAt(unsigned long lindex, const char *, ...) /*@printflike@*/; @@ -85,6 +84,9 @@ void ErrorNow(const char *, ...) /*@printflike@*/; void WarningNow(const char *, ...) /*@printflike@*/; /* Returns total number of errors to this point in assembly. */ -unsigned int OutputAllErrorWarning(void); +unsigned int GetNumErrors(void); + +/* Outputs all errors/warnings to standard error. */ +void OutputAllErrorWarning(void); #endif diff --git a/src/main.c b/src/main.c index 37c86737..8a7c4c1b 100644 --- a/src/main.c +++ b/src/main.c @@ -204,7 +204,8 @@ main(int argc, char *argv[]) if (obj != stdout) fclose(obj); - if (OutputAllErrorWarning() > 0) { + if (GetNumErrors() > 0) { + OutputAllErrorWarning(); if (obj != stdout) remove(obj_filename); xfree(preproc_buf); @@ -263,7 +264,8 @@ main(int argc, char *argv[]) fclose(in); xfree(in_filename); - if (OutputAllErrorWarning() > 0) { + if (GetNumErrors() > 0) { + OutputAllErrorWarning(); cleanup(sections); return EXIT_FAILURE; } @@ -271,7 +273,8 @@ main(int argc, char *argv[]) symrec_parser_finalize(); basic_optimizer.optimize(sections); - if (OutputAllErrorWarning() > 0) { + if (GetNumErrors() > 0) { + OutputAllErrorWarning(); cleanup(sections); return EXIT_FAILURE; } @@ -295,13 +298,15 @@ main(int argc, char *argv[]) /* If we had an error at this point, we also need to delete the output * object file (to make sure it's not left newer than the source). */ - if (OutputAllErrorWarning() > 0) { + if (GetNumErrors() > 0) { + OutputAllErrorWarning(); cleanup(sections); if (obj != stdout) remove(obj_filename); return EXIT_FAILURE; } + OutputAllErrorWarning(); xfree(obj_filename); cleanup(sections); diff --git a/src/objfmts/bin/tests/integer-warn.errwarn b/src/objfmts/bin/tests/integer-warn.errwarn index 8be45269..973e8d39 100644 --- a/src/objfmts/bin/tests/integer-warn.errwarn +++ b/src/objfmts/bin/tests/integer-warn.errwarn @@ -1,6 +1,2 @@ ./src/objfmts/bin/tests/integer-warn.asm:5: warning: Numeric constant too large for internal format ./src/objfmts/bin/tests/integer-warn.asm:6: warning: Numeric constant too large for internal format -./src/objfmts/bin/tests/integer-warn.asm:5: warning: Numeric constant too large for internal format -./src/objfmts/bin/tests/integer-warn.asm:6: warning: Numeric constant too large for internal format -./src/objfmts/bin/tests/integer-warn.asm:5: warning: Numeric constant too large for internal format -./src/objfmts/bin/tests/integer-warn.asm:6: warning: Numeric constant too large for internal format