diff options
author | somov <somov@yandex-team.ru> | 2022-02-10 16:45:47 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:45:47 +0300 |
commit | a5950576e397b1909261050b8c7da16db58f10b1 (patch) | |
tree | 7ba7677f6a4c3e19e2cefab34d16df2c8963b4d4 /contrib/tools/yasm/libyasm/errwarn.c | |
parent | 81eddc8c0b55990194e112b02d127b87d54164a9 (diff) | |
download | ydb-a5950576e397b1909261050b8c7da16db58f10b1.tar.gz |
Restoring authorship annotation for <somov@yandex-team.ru>. Commit 1 of 2.
Diffstat (limited to 'contrib/tools/yasm/libyasm/errwarn.c')
-rw-r--r-- | contrib/tools/yasm/libyasm/errwarn.c | 1058 |
1 files changed, 529 insertions, 529 deletions
diff --git a/contrib/tools/yasm/libyasm/errwarn.c b/contrib/tools/yasm/libyasm/errwarn.c index f759cf8f71..4266253bbc 100644 --- a/contrib/tools/yasm/libyasm/errwarn.c +++ b/contrib/tools/yasm/libyasm/errwarn.c @@ -1,533 +1,533 @@ -/* - * Error and warning reporting and related functions. - * - * Copyright (C) 2001-2007 Peter Johnson - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ -#include "util.h" - -#include <ctype.h> +/* + * Error and warning reporting and related functions. + * + * Copyright (C) 2001-2007 Peter Johnson + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS'' + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +#include "util.h" + +#include <ctype.h> #include <errno.h> -#include <stdarg.h> - -#include "coretype.h" - -#include "linemap.h" -#include "errwarn.h" - - -#define MSG_MAXSIZE 1024 - -#if !defined(HAVE_TOASCII) || defined(lint) -# define toascii(c) ((c) & 0x7F) -#endif - -/* Default handlers for replacable functions */ -static /*@exits@*/ void def_internal_error_ - (const char *file, unsigned int line, const char *message); -static /*@exits@*/ void def_fatal(const char *message, va_list va); -static const char *def_gettext_hook(const char *msgid); - -/* Storage for errwarn's "extern" functions */ -/*@exits@*/ void (*yasm_internal_error_) - (const char *file, unsigned int line, const char *message) - = def_internal_error_; -/*@exits@*/ void (*yasm_fatal) (const char *message, va_list va) = def_fatal; -const char * (*yasm_gettext_hook) (const char *msgid) = def_gettext_hook; - -/* Error indicator */ -/* yasm_eclass is not static so that yasm_error_occurred macro can access it */ -yasm_error_class yasm_eclass; -static /*@only@*/ /*@null@*/ char *yasm_estr; -static unsigned long yasm_exrefline; -static /*@only@*/ /*@null@*/ char *yasm_exrefstr; - -/* Warning indicator */ -typedef struct warn { - /*@reldef@*/ STAILQ_ENTRY(warn) link; - - yasm_warn_class wclass; - /*@owned@*/ /*@null@*/ char *wstr; -} warn; -static STAILQ_HEAD(warn_head, warn) yasm_warns; - -/* Enabled warnings. See errwarn.h for a list. */ -static unsigned long warn_class_enabled; - -typedef struct errwarn_data { - /*@reldef@*/ SLIST_ENTRY(errwarn_data) link; - - enum { WE_UNKNOWN, WE_ERROR, WE_WARNING, WE_PARSERERROR } type; - - unsigned long line; - unsigned long xrefline; - /*@owned@*/ char *msg; - /*@owned@*/ char *xrefmsg; -} errwarn_data; - -struct yasm_errwarns { - /*@reldef@*/ SLIST_HEAD(errwarn_head, errwarn_data) errwarns; - - /* Total error count */ - unsigned int ecount; - - /* Total warning count */ - unsigned int wcount; - - /* Last inserted error/warning. Used to speed up insertions. */ - /*@null@*/ errwarn_data *previous_we; -}; - -/* Static buffer for use by conv_unprint(). */ -static char unprint[5]; - - -static const char * -def_gettext_hook(const char *msgid) -{ - return msgid; -} - -void -yasm_errwarn_initialize(void) -{ - /* Default enabled warnings. See errwarn.h for a list. */ - warn_class_enabled = - (1UL<<YASM_WARN_GENERAL) | (1UL<<YASM_WARN_UNREC_CHAR) | - (1UL<<YASM_WARN_PREPROC) | (0UL<<YASM_WARN_ORPHAN_LABEL) | - (1UL<<YASM_WARN_UNINIT_CONTENTS) | (0UL<<YASM_WARN_SIZE_OVERRIDE) | - (1UL<<YASM_WARN_IMPLICIT_SIZE_OVERRIDE); - - yasm_eclass = YASM_ERROR_NONE; - yasm_estr = NULL; - yasm_exrefline = 0; - yasm_exrefstr = NULL; - - STAILQ_INIT(&yasm_warns); -} - -void -yasm_errwarn_cleanup(void) -{ - yasm_error_clear(); - yasm_warn_clear(); -} - -/* Convert a possibly unprintable character into a printable string, using - * standard cat(1) convention for unprintable characters. - */ -char * -yasm__conv_unprint(int ch) -{ - int pos = 0; - - if (((ch & ~0x7F) != 0) /*!isascii(ch)*/ && !isprint(ch)) { - unprint[pos++] = 'M'; - unprint[pos++] = '-'; - ch &= toascii(ch); - } - if (iscntrl(ch)) { - unprint[pos++] = '^'; - unprint[pos++] = (ch == '\177') ? '?' : ch | 0100; - } else - unprint[pos++] = ch; - unprint[pos] = '\0'; - - return unprint; -} - -/* Report an internal error. Essentially a fatal error with trace info. - * Exit immediately because it's essentially an assert() trap. - */ -static void -def_internal_error_(const char *file, unsigned int line, const char *message) -{ - fprintf(stderr, - yasm_gettext_hook(N_("INTERNAL ERROR at %s, line %u: %s\n")), - file, line, yasm_gettext_hook(message)); -#ifdef HAVE_ABORT - abort(); -#else - exit(EXIT_FAILURE); -#endif -} - -/* Report a fatal error. These are unrecoverable (such as running out of - * memory), so just exit immediately. - */ -static void -def_fatal(const char *fmt, va_list va) -{ - fprintf(stderr, "%s: ", yasm_gettext_hook(N_("FATAL"))); - vfprintf(stderr, yasm_gettext_hook(fmt), va); - fputc('\n', stderr); - exit(EXIT_FAILURE); -} - -/* 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. - */ -static errwarn_data * -errwarn_data_new(yasm_errwarns *errwarns, unsigned long line, - int replace_parser_error) -{ - errwarn_data *first, *next, *ins_we, *we; - enum { INS_NONE, INS_HEAD, INS_AFTER } action = INS_NONE; - - /* Find the entry with either line=line or the last one with line<line. - * Start with the last entry added to speed the search. - */ - ins_we = errwarns->previous_we; - first = SLIST_FIRST(&errwarns->errwarns); - if (!ins_we || !first) - action = INS_HEAD; - while (action == INS_NONE) { - next = SLIST_NEXT(ins_we, link); - if (line < ins_we->line) { - if (ins_we == first) - action = INS_HEAD; - else - ins_we = first; - } else if (!next) - action = INS_AFTER; - else if (line >= ins_we->line && line < next->line) - action = INS_AFTER; - else - ins_we = next; - } - - if (replace_parser_error && ins_we && ins_we->type == WE_PARSERERROR) { - /* overwrite last error */ - we = ins_we; - } else { - /* add a new error */ - we = yasm_xmalloc(sizeof(errwarn_data)); - - we->type = WE_UNKNOWN; - we->line = line; - we->xrefline = 0; - we->msg = NULL; - we->xrefmsg = NULL; - - if (action == INS_HEAD) - SLIST_INSERT_HEAD(&errwarns->errwarns, we, link); - else if (action == INS_AFTER) { - assert(ins_we != NULL); - SLIST_INSERT_AFTER(ins_we, we, link); - } else - yasm_internal_error(N_("Unexpected errwarn insert action")); - } - - /* Remember previous err/warn */ - errwarns->previous_we = we; - - return we; -} - -void -yasm_error_clear(void) -{ - if (yasm_estr) - yasm_xfree(yasm_estr); - if (yasm_exrefstr) - yasm_xfree(yasm_exrefstr); - yasm_eclass = YASM_ERROR_NONE; - yasm_estr = NULL; - yasm_exrefline = 0; - yasm_exrefstr = NULL; -} - -int -yasm_error_matches(yasm_error_class eclass) -{ - if (yasm_eclass == YASM_ERROR_NONE) - return eclass == YASM_ERROR_NONE; - if (yasm_eclass == YASM_ERROR_GENERAL) - return eclass == YASM_ERROR_GENERAL; - return (yasm_eclass & eclass) == eclass; -} - -void -yasm_error_set_va(yasm_error_class eclass, const char *format, va_list va) -{ - if (yasm_eclass != YASM_ERROR_NONE) - return; - - yasm_eclass = eclass; - yasm_estr = yasm_xmalloc(MSG_MAXSIZE+1); -#ifdef HAVE_VSNPRINTF - vsnprintf(yasm_estr, MSG_MAXSIZE, yasm_gettext_hook(format), va); -#else - vsprintf(yasm_estr, yasm_gettext_hook(format), va); -#endif -} - -void -yasm_error_set(yasm_error_class eclass, const char *format, ...) -{ - va_list va; - va_start(va, format); - yasm_error_set_va(eclass, format, va); - va_end(va); -} - -void -yasm_error_set_xref_va(unsigned long xrefline, const char *format, va_list va) -{ - if (yasm_eclass != YASM_ERROR_NONE) - return; - - yasm_exrefline = xrefline; - - yasm_exrefstr = yasm_xmalloc(MSG_MAXSIZE+1); -#ifdef HAVE_VSNPRINTF - vsnprintf(yasm_exrefstr, MSG_MAXSIZE, yasm_gettext_hook(format), va); -#else - vsprintf(yasm_exrefstr, yasm_gettext_hook(format), va); -#endif -} - -void -yasm_error_set_xref(unsigned long xrefline, const char *format, ...) -{ - va_list va; - va_start(va, format); - yasm_error_set_xref_va(xrefline, format, va); - va_end(va); -} - -void -yasm_error_fetch(yasm_error_class *eclass, char **str, unsigned long *xrefline, - char **xrefstr) -{ - *eclass = yasm_eclass; - *str = yasm_estr; - *xrefline = yasm_exrefline; - *xrefstr = yasm_exrefstr; - yasm_eclass = YASM_ERROR_NONE; - yasm_estr = NULL; - yasm_exrefline = 0; - yasm_exrefstr = NULL; -} - -void yasm_warn_clear(void) -{ - /* Delete all error/warnings */ - while (!STAILQ_EMPTY(&yasm_warns)) { - warn *w = STAILQ_FIRST(&yasm_warns); - - if (w->wstr) - yasm_xfree(w->wstr); - - STAILQ_REMOVE_HEAD(&yasm_warns, link); - yasm_xfree(w); - } -} - -yasm_warn_class -yasm_warn_occurred(void) -{ - if (STAILQ_EMPTY(&yasm_warns)) - return YASM_WARN_NONE; - return STAILQ_FIRST(&yasm_warns)->wclass; -} - -void -yasm_warn_set_va(yasm_warn_class wclass, const char *format, va_list va) -{ - warn *w; - - if (!(warn_class_enabled & (1UL<<wclass))) - return; /* warning is part of disabled class */ - - w = yasm_xmalloc(sizeof(warn)); - w->wclass = wclass; - w->wstr = yasm_xmalloc(MSG_MAXSIZE+1); -#ifdef HAVE_VSNPRINTF - vsnprintf(w->wstr, MSG_MAXSIZE, yasm_gettext_hook(format), va); -#else - vsprintf(w->wstr, yasm_gettext_hook(format), va); -#endif - STAILQ_INSERT_TAIL(&yasm_warns, w, link); -} - -void -yasm_warn_set(yasm_warn_class wclass, const char *format, ...) -{ - va_list va; - va_start(va, format); - yasm_warn_set_va(wclass, format, va); - va_end(va); -} - -void -yasm_warn_fetch(yasm_warn_class *wclass, char **str) -{ - warn *w = STAILQ_FIRST(&yasm_warns); - - if (!w) { - *wclass = YASM_WARN_NONE; - *str = NULL; - return; - } - - *wclass = w->wclass; - *str = w->wstr; - - STAILQ_REMOVE_HEAD(&yasm_warns, link); - yasm_xfree(w); -} - -void -yasm_warn_enable(yasm_warn_class num) -{ - warn_class_enabled |= (1UL<<num); -} - -void -yasm_warn_disable(yasm_warn_class num) -{ - warn_class_enabled &= ~(1UL<<num); -} - -void -yasm_warn_disable_all(void) -{ - warn_class_enabled = 0; -} - -yasm_errwarns * -yasm_errwarns_create(void) -{ - yasm_errwarns *errwarns = yasm_xmalloc(sizeof(yasm_errwarns)); - SLIST_INIT(&errwarns->errwarns); - errwarns->ecount = 0; - errwarns->wcount = 0; - errwarns->previous_we = NULL; - return errwarns; -} - -void -yasm_errwarns_destroy(yasm_errwarns *errwarns) -{ - errwarn_data *we; - - /* Delete all error/warnings */ - while (!SLIST_EMPTY(&errwarns->errwarns)) { - we = SLIST_FIRST(&errwarns->errwarns); - if (we->msg) - yasm_xfree(we->msg); - if (we->xrefmsg) - yasm_xfree(we->xrefmsg); - - SLIST_REMOVE_HEAD(&errwarns->errwarns, link); - yasm_xfree(we); - } - - yasm_xfree(errwarns); -} - -void -yasm_errwarn_propagate(yasm_errwarns *errwarns, unsigned long line) -{ - if (yasm_eclass != YASM_ERROR_NONE) { - errwarn_data *we = errwarn_data_new(errwarns, line, 1); - yasm_error_class eclass; - - yasm_error_fetch(&eclass, &we->msg, &we->xrefline, &we->xrefmsg); - if (eclass != YASM_ERROR_GENERAL - && (eclass & YASM_ERROR_PARSE) == YASM_ERROR_PARSE) - we->type = WE_PARSERERROR; - else - we->type = WE_ERROR; - errwarns->ecount++; - } - - while (!STAILQ_EMPTY(&yasm_warns)) { - errwarn_data *we = errwarn_data_new(errwarns, line, 0); - yasm_warn_class wclass; - - yasm_warn_fetch(&wclass, &we->msg); - we->type = WE_WARNING; - errwarns->wcount++; - } -} - -unsigned int -yasm_errwarns_num_errors(yasm_errwarns *errwarns, int warning_as_error) -{ - if (warning_as_error) - return errwarns->ecount+errwarns->wcount; - else - return errwarns->ecount; -} - -void -yasm_errwarns_output_all(yasm_errwarns *errwarns, yasm_linemap *lm, - int warning_as_error, - yasm_print_error_func print_error, - yasm_print_warning_func print_warning) -{ - errwarn_data *we; - const char *filename, *xref_filename; - unsigned long line, xref_line; - - /* If we're treating warnings as errors, tell the user about it. */ - if (warning_as_error && warning_as_error != 2) { - print_error("", 0, - yasm_gettext_hook(N_("warnings being treated as errors")), - NULL, 0, NULL); - warning_as_error = 2; - } - - /* Output error/warnings. */ - SLIST_FOREACH(we, &errwarns->errwarns, link) { - /* Output error/warning */ - yasm_linemap_lookup(lm, we->line, &filename, &line); - if (we->xrefline) - yasm_linemap_lookup(lm, we->xrefline, &xref_filename, &xref_line); - else { - xref_filename = NULL; - xref_line = 0; - } - if (we->type == WE_ERROR || we->type == WE_PARSERERROR) - print_error(filename, line, we->msg, xref_filename, xref_line, - we->xrefmsg); - else - print_warning(filename, line, we->msg); - } -} - -void -yasm__fatal(const char *message, ...) -{ - va_list va; - va_start(va, message); - yasm_fatal(message, va); - /*@notreached@*/ - va_end(va); -} +#include <stdarg.h> + +#include "coretype.h" + +#include "linemap.h" +#include "errwarn.h" + + +#define MSG_MAXSIZE 1024 + +#if !defined(HAVE_TOASCII) || defined(lint) +# define toascii(c) ((c) & 0x7F) +#endif + +/* Default handlers for replacable functions */ +static /*@exits@*/ void def_internal_error_ + (const char *file, unsigned int line, const char *message); +static /*@exits@*/ void def_fatal(const char *message, va_list va); +static const char *def_gettext_hook(const char *msgid); + +/* Storage for errwarn's "extern" functions */ +/*@exits@*/ void (*yasm_internal_error_) + (const char *file, unsigned int line, const char *message) + = def_internal_error_; +/*@exits@*/ void (*yasm_fatal) (const char *message, va_list va) = def_fatal; +const char * (*yasm_gettext_hook) (const char *msgid) = def_gettext_hook; + +/* Error indicator */ +/* yasm_eclass is not static so that yasm_error_occurred macro can access it */ +yasm_error_class yasm_eclass; +static /*@only@*/ /*@null@*/ char *yasm_estr; +static unsigned long yasm_exrefline; +static /*@only@*/ /*@null@*/ char *yasm_exrefstr; + +/* Warning indicator */ +typedef struct warn { + /*@reldef@*/ STAILQ_ENTRY(warn) link; + + yasm_warn_class wclass; + /*@owned@*/ /*@null@*/ char *wstr; +} warn; +static STAILQ_HEAD(warn_head, warn) yasm_warns; + +/* Enabled warnings. See errwarn.h for a list. */ +static unsigned long warn_class_enabled; + +typedef struct errwarn_data { + /*@reldef@*/ SLIST_ENTRY(errwarn_data) link; + + enum { WE_UNKNOWN, WE_ERROR, WE_WARNING, WE_PARSERERROR } type; + + unsigned long line; + unsigned long xrefline; + /*@owned@*/ char *msg; + /*@owned@*/ char *xrefmsg; +} errwarn_data; + +struct yasm_errwarns { + /*@reldef@*/ SLIST_HEAD(errwarn_head, errwarn_data) errwarns; + + /* Total error count */ + unsigned int ecount; + + /* Total warning count */ + unsigned int wcount; + + /* Last inserted error/warning. Used to speed up insertions. */ + /*@null@*/ errwarn_data *previous_we; +}; + +/* Static buffer for use by conv_unprint(). */ +static char unprint[5]; + + +static const char * +def_gettext_hook(const char *msgid) +{ + return msgid; +} + +void +yasm_errwarn_initialize(void) +{ + /* Default enabled warnings. See errwarn.h for a list. */ + warn_class_enabled = + (1UL<<YASM_WARN_GENERAL) | (1UL<<YASM_WARN_UNREC_CHAR) | + (1UL<<YASM_WARN_PREPROC) | (0UL<<YASM_WARN_ORPHAN_LABEL) | + (1UL<<YASM_WARN_UNINIT_CONTENTS) | (0UL<<YASM_WARN_SIZE_OVERRIDE) | + (1UL<<YASM_WARN_IMPLICIT_SIZE_OVERRIDE); + + yasm_eclass = YASM_ERROR_NONE; + yasm_estr = NULL; + yasm_exrefline = 0; + yasm_exrefstr = NULL; + + STAILQ_INIT(&yasm_warns); +} + +void +yasm_errwarn_cleanup(void) +{ + yasm_error_clear(); + yasm_warn_clear(); +} + +/* Convert a possibly unprintable character into a printable string, using + * standard cat(1) convention for unprintable characters. + */ +char * +yasm__conv_unprint(int ch) +{ + int pos = 0; + + if (((ch & ~0x7F) != 0) /*!isascii(ch)*/ && !isprint(ch)) { + unprint[pos++] = 'M'; + unprint[pos++] = '-'; + ch &= toascii(ch); + } + if (iscntrl(ch)) { + unprint[pos++] = '^'; + unprint[pos++] = (ch == '\177') ? '?' : ch | 0100; + } else + unprint[pos++] = ch; + unprint[pos] = '\0'; + + return unprint; +} + +/* Report an internal error. Essentially a fatal error with trace info. + * Exit immediately because it's essentially an assert() trap. + */ +static void +def_internal_error_(const char *file, unsigned int line, const char *message) +{ + fprintf(stderr, + yasm_gettext_hook(N_("INTERNAL ERROR at %s, line %u: %s\n")), + file, line, yasm_gettext_hook(message)); +#ifdef HAVE_ABORT + abort(); +#else + exit(EXIT_FAILURE); +#endif +} + +/* Report a fatal error. These are unrecoverable (such as running out of + * memory), so just exit immediately. + */ +static void +def_fatal(const char *fmt, va_list va) +{ + fprintf(stderr, "%s: ", yasm_gettext_hook(N_("FATAL"))); + vfprintf(stderr, yasm_gettext_hook(fmt), va); + fputc('\n', stderr); + exit(EXIT_FAILURE); +} + +/* 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. + */ +static errwarn_data * +errwarn_data_new(yasm_errwarns *errwarns, unsigned long line, + int replace_parser_error) +{ + errwarn_data *first, *next, *ins_we, *we; + enum { INS_NONE, INS_HEAD, INS_AFTER } action = INS_NONE; + + /* Find the entry with either line=line or the last one with line<line. + * Start with the last entry added to speed the search. + */ + ins_we = errwarns->previous_we; + first = SLIST_FIRST(&errwarns->errwarns); + if (!ins_we || !first) + action = INS_HEAD; + while (action == INS_NONE) { + next = SLIST_NEXT(ins_we, link); + if (line < ins_we->line) { + if (ins_we == first) + action = INS_HEAD; + else + ins_we = first; + } else if (!next) + action = INS_AFTER; + else if (line >= ins_we->line && line < next->line) + action = INS_AFTER; + else + ins_we = next; + } + + if (replace_parser_error && ins_we && ins_we->type == WE_PARSERERROR) { + /* overwrite last error */ + we = ins_we; + } else { + /* add a new error */ + we = yasm_xmalloc(sizeof(errwarn_data)); + + we->type = WE_UNKNOWN; + we->line = line; + we->xrefline = 0; + we->msg = NULL; + we->xrefmsg = NULL; + + if (action == INS_HEAD) + SLIST_INSERT_HEAD(&errwarns->errwarns, we, link); + else if (action == INS_AFTER) { + assert(ins_we != NULL); + SLIST_INSERT_AFTER(ins_we, we, link); + } else + yasm_internal_error(N_("Unexpected errwarn insert action")); + } + + /* Remember previous err/warn */ + errwarns->previous_we = we; + + return we; +} + +void +yasm_error_clear(void) +{ + if (yasm_estr) + yasm_xfree(yasm_estr); + if (yasm_exrefstr) + yasm_xfree(yasm_exrefstr); + yasm_eclass = YASM_ERROR_NONE; + yasm_estr = NULL; + yasm_exrefline = 0; + yasm_exrefstr = NULL; +} + +int +yasm_error_matches(yasm_error_class eclass) +{ + if (yasm_eclass == YASM_ERROR_NONE) + return eclass == YASM_ERROR_NONE; + if (yasm_eclass == YASM_ERROR_GENERAL) + return eclass == YASM_ERROR_GENERAL; + return (yasm_eclass & eclass) == eclass; +} + +void +yasm_error_set_va(yasm_error_class eclass, const char *format, va_list va) +{ + if (yasm_eclass != YASM_ERROR_NONE) + return; + + yasm_eclass = eclass; + yasm_estr = yasm_xmalloc(MSG_MAXSIZE+1); +#ifdef HAVE_VSNPRINTF + vsnprintf(yasm_estr, MSG_MAXSIZE, yasm_gettext_hook(format), va); +#else + vsprintf(yasm_estr, yasm_gettext_hook(format), va); +#endif +} + +void +yasm_error_set(yasm_error_class eclass, const char *format, ...) +{ + va_list va; + va_start(va, format); + yasm_error_set_va(eclass, format, va); + va_end(va); +} + +void +yasm_error_set_xref_va(unsigned long xrefline, const char *format, va_list va) +{ + if (yasm_eclass != YASM_ERROR_NONE) + return; + + yasm_exrefline = xrefline; + + yasm_exrefstr = yasm_xmalloc(MSG_MAXSIZE+1); +#ifdef HAVE_VSNPRINTF + vsnprintf(yasm_exrefstr, MSG_MAXSIZE, yasm_gettext_hook(format), va); +#else + vsprintf(yasm_exrefstr, yasm_gettext_hook(format), va); +#endif +} + +void +yasm_error_set_xref(unsigned long xrefline, const char *format, ...) +{ + va_list va; + va_start(va, format); + yasm_error_set_xref_va(xrefline, format, va); + va_end(va); +} + +void +yasm_error_fetch(yasm_error_class *eclass, char **str, unsigned long *xrefline, + char **xrefstr) +{ + *eclass = yasm_eclass; + *str = yasm_estr; + *xrefline = yasm_exrefline; + *xrefstr = yasm_exrefstr; + yasm_eclass = YASM_ERROR_NONE; + yasm_estr = NULL; + yasm_exrefline = 0; + yasm_exrefstr = NULL; +} + +void yasm_warn_clear(void) +{ + /* Delete all error/warnings */ + while (!STAILQ_EMPTY(&yasm_warns)) { + warn *w = STAILQ_FIRST(&yasm_warns); + + if (w->wstr) + yasm_xfree(w->wstr); + + STAILQ_REMOVE_HEAD(&yasm_warns, link); + yasm_xfree(w); + } +} + +yasm_warn_class +yasm_warn_occurred(void) +{ + if (STAILQ_EMPTY(&yasm_warns)) + return YASM_WARN_NONE; + return STAILQ_FIRST(&yasm_warns)->wclass; +} + +void +yasm_warn_set_va(yasm_warn_class wclass, const char *format, va_list va) +{ + warn *w; + + if (!(warn_class_enabled & (1UL<<wclass))) + return; /* warning is part of disabled class */ + + w = yasm_xmalloc(sizeof(warn)); + w->wclass = wclass; + w->wstr = yasm_xmalloc(MSG_MAXSIZE+1); +#ifdef HAVE_VSNPRINTF + vsnprintf(w->wstr, MSG_MAXSIZE, yasm_gettext_hook(format), va); +#else + vsprintf(w->wstr, yasm_gettext_hook(format), va); +#endif + STAILQ_INSERT_TAIL(&yasm_warns, w, link); +} + +void +yasm_warn_set(yasm_warn_class wclass, const char *format, ...) +{ + va_list va; + va_start(va, format); + yasm_warn_set_va(wclass, format, va); + va_end(va); +} + +void +yasm_warn_fetch(yasm_warn_class *wclass, char **str) +{ + warn *w = STAILQ_FIRST(&yasm_warns); + + if (!w) { + *wclass = YASM_WARN_NONE; + *str = NULL; + return; + } + + *wclass = w->wclass; + *str = w->wstr; + + STAILQ_REMOVE_HEAD(&yasm_warns, link); + yasm_xfree(w); +} + +void +yasm_warn_enable(yasm_warn_class num) +{ + warn_class_enabled |= (1UL<<num); +} + +void +yasm_warn_disable(yasm_warn_class num) +{ + warn_class_enabled &= ~(1UL<<num); +} + +void +yasm_warn_disable_all(void) +{ + warn_class_enabled = 0; +} + +yasm_errwarns * +yasm_errwarns_create(void) +{ + yasm_errwarns *errwarns = yasm_xmalloc(sizeof(yasm_errwarns)); + SLIST_INIT(&errwarns->errwarns); + errwarns->ecount = 0; + errwarns->wcount = 0; + errwarns->previous_we = NULL; + return errwarns; +} + +void +yasm_errwarns_destroy(yasm_errwarns *errwarns) +{ + errwarn_data *we; + + /* Delete all error/warnings */ + while (!SLIST_EMPTY(&errwarns->errwarns)) { + we = SLIST_FIRST(&errwarns->errwarns); + if (we->msg) + yasm_xfree(we->msg); + if (we->xrefmsg) + yasm_xfree(we->xrefmsg); + + SLIST_REMOVE_HEAD(&errwarns->errwarns, link); + yasm_xfree(we); + } + + yasm_xfree(errwarns); +} + +void +yasm_errwarn_propagate(yasm_errwarns *errwarns, unsigned long line) +{ + if (yasm_eclass != YASM_ERROR_NONE) { + errwarn_data *we = errwarn_data_new(errwarns, line, 1); + yasm_error_class eclass; + + yasm_error_fetch(&eclass, &we->msg, &we->xrefline, &we->xrefmsg); + if (eclass != YASM_ERROR_GENERAL + && (eclass & YASM_ERROR_PARSE) == YASM_ERROR_PARSE) + we->type = WE_PARSERERROR; + else + we->type = WE_ERROR; + errwarns->ecount++; + } + + while (!STAILQ_EMPTY(&yasm_warns)) { + errwarn_data *we = errwarn_data_new(errwarns, line, 0); + yasm_warn_class wclass; + + yasm_warn_fetch(&wclass, &we->msg); + we->type = WE_WARNING; + errwarns->wcount++; + } +} + +unsigned int +yasm_errwarns_num_errors(yasm_errwarns *errwarns, int warning_as_error) +{ + if (warning_as_error) + return errwarns->ecount+errwarns->wcount; + else + return errwarns->ecount; +} + +void +yasm_errwarns_output_all(yasm_errwarns *errwarns, yasm_linemap *lm, + int warning_as_error, + yasm_print_error_func print_error, + yasm_print_warning_func print_warning) +{ + errwarn_data *we; + const char *filename, *xref_filename; + unsigned long line, xref_line; + + /* If we're treating warnings as errors, tell the user about it. */ + if (warning_as_error && warning_as_error != 2) { + print_error("", 0, + yasm_gettext_hook(N_("warnings being treated as errors")), + NULL, 0, NULL); + warning_as_error = 2; + } + + /* Output error/warnings. */ + SLIST_FOREACH(we, &errwarns->errwarns, link) { + /* Output error/warning */ + yasm_linemap_lookup(lm, we->line, &filename, &line); + if (we->xrefline) + yasm_linemap_lookup(lm, we->xrefline, &xref_filename, &xref_line); + else { + xref_filename = NULL; + xref_line = 0; + } + if (we->type == WE_ERROR || we->type == WE_PARSERERROR) + print_error(filename, line, we->msg, xref_filename, xref_line, + we->xrefmsg); + else + print_warning(filename, line, we->msg); + } +} + +void +yasm__fatal(const char *message, ...) +{ + va_list va; + va_start(va, message); + yasm_fatal(message, va); + /*@notreached@*/ + va_end(va); +} void yasm__fatal_missing_input_file(const char *message, const char *filename) |