diff --git a/libyasm/errwarn.c b/libyasm/errwarn.c index f62e182d..af07f2d0 100644 --- a/libyasm/errwarn.c +++ b/libyasm/errwarn.c @@ -74,6 +74,8 @@ typedef struct errwarn_data { enum { WE_UNKNOWN, WE_ERROR, WE_WARNING, WE_PARSERERROR } type; unsigned long line; + unsigned long displine; + /* FIXME: This should not be a fixed size. But we don't have vasprintf() * right now. */ char msg[MSG_MAXSIZE]; @@ -179,7 +181,8 @@ def_fatal(const char *fmt, ...) * type is WE_PARSERERROR. */ static errwarn_data * -errwarn_data_new(unsigned long line, int replace_parser_error) +errwarn_data_new(unsigned long line, unsigned long displine, + int replace_parser_error) { errwarn_data *first, *next, *ins_we, *we; enum { INS_NONE, INS_HEAD, INS_AFTER } action = INS_NONE; @@ -215,6 +218,7 @@ errwarn_data_new(unsigned long line, int replace_parser_error) we->type = WE_UNKNOWN; we->line = line; + we->displine = displine; if (action == INS_HEAD) SLIST_INSERT_HEAD(&errwarns, we, link); @@ -231,13 +235,14 @@ errwarn_data_new(unsigned long line, int replace_parser_error) return we; } -/* Register an error at line line. Does not print the error, only stores it - * for output_all() to print. +/* Register an error at line line, displaying line displine. Does not print + * the error, only stores it for output_all() to print. */ void -yasm__error_va(unsigned long line, const char *fmt, va_list va) +yasm__error_va_at(unsigned long line, unsigned long displine, const char *fmt, + va_list va) { - errwarn_data *we = errwarn_data_new(line, 1); + errwarn_data *we = errwarn_data_new(line, displine, 1); we->type = WE_ERROR; @@ -250,19 +255,19 @@ yasm__error_va(unsigned long line, const char *fmt, va_list va) error_count++; } -/* Register an warning at line line. Does not print the warning, only stores - * it for output_all() to print. +/* Register an warning at line line, displaying line displine. Does not print + * the warning, only stores it for output_all() to print. */ void -yasm__warning_va(yasm_warn_class num, unsigned long line, const char *fmt, - va_list va) +yasm__warning_va_at(yasm_warn_class num, unsigned long line, + unsigned long displine, const char *fmt, va_list va) { errwarn_data *we; if (!(warn_class_enabled & (1UL<type = WE_WARNING; @@ -283,7 +288,20 @@ yasm__error(unsigned long line, const char *fmt, ...) { va_list va; va_start(va, fmt); - yasm__error_va(line, fmt, va); + yasm__error_va_at(line, line, fmt, va); + va_end(va); +} + +/* Register an error at line line, displaying line displine. Does not print + * the error, only stores it for output_all() to print. + */ +void +yasm__error_at(unsigned long line, unsigned long displine, const char *fmt, + ...) +{ + va_list va; + va_start(va, fmt); + yasm__error_va_at(line, displine, fmt, va); va_end(va); } @@ -295,7 +313,20 @@ yasm__warning(yasm_warn_class num, unsigned long line, const char *fmt, ...) { va_list va; va_start(va, fmt); - yasm__warning_va(num, line, fmt, va); + yasm__warning_va_at(num, line, line, fmt, va); + va_end(va); +} + +/* Register an warning at line line, displaying line displine. Does not print + * the warning, only stores it for output_all() to print. + */ +void +yasm__warning_at(yasm_warn_class num, unsigned long line, + unsigned long displine, const char *fmt, ...) +{ + va_list va; + va_start(va, fmt); + yasm__warning_va_at(num, line, line, fmt, va); va_end(va); } @@ -354,7 +385,7 @@ yasm_errwarn_output_all(yasm_linemap *lm, int warning_as_error, /* Output error/warnings. */ SLIST_FOREACH(we, &errwarns, link) { /* Output error/warning */ - yasm_linemap_lookup(lm, we->line, &filename, &line); + yasm_linemap_lookup(lm, we->displine, &filename, &line); if (we->type == WE_ERROR) print_error(filename, line, we->msg); else diff --git a/libyasm/errwarn.h b/libyasm/errwarn.h index 620fc81a..8d33c253 100644 --- a/libyasm/errwarn.h +++ b/libyasm/errwarn.h @@ -75,13 +75,38 @@ extern /*@exits@*/ void (*yasm_internal_error_) */ extern /*@exits@*/ void (*yasm_fatal) (const char *message, ...); +/** Log an error at a given line, displaying a different line. va_list version + * of yasm__error_at(). + * \internal + * \param line virtual line + * \param displine displayed virtual line + * \param message printf-like-format message + * \param va argument list for message + */ +void yasm__error_va_at(unsigned long line, unsigned long displine, + const char *message, va_list va); + /** Log an error. va_list version of yasm__error(). * \internal * \param line virtual line * \param message printf-like-format message * \param va argument list for message */ -void yasm__error_va(unsigned long line, const char *message, va_list va); +#define yasm__error_va(line, message, va) \ + yasm__error_va_at(line, line, message, va) + +/** Log a warning at a given line, displaying a different line. va_list + * version of yasm__warning_at(). + * \internal + * \param wclass warning class + * \param line virtual line + * \param displine displayed virtual line + * \param message printf-like-format message + * \param va argument list for message + */ +void yasm__warning_va_at(yasm_warn_class wclass, unsigned long line, + unsigned long displine, const char *message, + va_list va); /** Log a warning. va_list version of yasm__warning(). * \internal @@ -90,8 +115,8 @@ void yasm__error_va(unsigned long line, const char *message, va_list va); * \param message printf-like-format message * \param va argument list for message */ -void yasm__warning_va(yasm_warn_class wclass, unsigned long line, - const char *message, va_list va); +#define yasm__warning_va(wclass, line, message, va) \ + yasm__warning_va_at(wclass, line, line, message, va) /** Log an error. Does not print it out immediately; yasm_errwarn_output_all() * outputs errors and warnings. @@ -103,6 +128,17 @@ void yasm__warning_va(yasm_warn_class wclass, unsigned long line, void yasm__error(unsigned long line, const char *message, ...) /*@printflike@*/; +/** Log an error at a given line, displaying a different line. Does not print + * it out immediately; yasm_errwarn_output_all() outputs errors and warnings. + * \internal + * \param line virtual line + * \param displine displayed virtual line + * \param message printf-like-format message + * \param ... argument list for message + */ +void yasm__error_at(unsigned long line, unsigned long displine, + const char *message, ...) /*@printflike@*/; + /** Log a warning. Does not print it out immediately; * yasm_errwarn_output_all() outputs errors and warnings. * \internal @@ -114,6 +150,19 @@ void yasm__error(unsigned long line, const char *message, ...) void yasm__warning(yasm_warn_class wclass, unsigned long line, const char *message, ...) /*@printflike@*/; +/** Log a warning at a given line, displaying a different line. Does not print + * it out immediately; yasm_errwarn_output_all() outputs errors and warnings. + * \internal + * \param wclass warning class + * \param line virtual line + * \param displine displayed virtual line + * \param message printf-like-format message + * \param ... argument list for message + */ +void yasm__warning_at(yasm_warn_class wclass, unsigned long line, + unsigned long displine, const char *message, ...) + /*@printflike@*/; + /** Log a parser error. Parser errors can be overwritten by non-parser errors * on the same line. * \internal diff --git a/libyasm/symrec.c b/libyasm/symrec.c index 8cc5f607..280c2233 100644 --- a/libyasm/symrec.c +++ b/libyasm/symrec.c @@ -191,9 +191,9 @@ symtab_define(yasm_symtab *symtab, const char *name, sym_type type, /* Has it been defined before (either by DEFINED or COMMON/EXTERN)? */ if ((rec->status & SYM_DEFINED) || (rec->visibility & (YASM_SYM_COMMON | YASM_SYM_EXTERN))) { - yasm__error(line, - N_("duplicate definition of `%s'; first defined on line %lu"), - name, rec->line); + yasm__error(line, N_("redefinition of `%s'"), name); + yasm__error_at(line, rec->line, N_("`%s' previously defined here"), + name); } else { rec->line = line; /* set line number of definition */ rec->type = type; diff --git a/libyasm/tests/Makefile.inc b/libyasm/tests/Makefile.inc index 79207247..61c7be0f 100644 --- a/libyasm/tests/Makefile.inc +++ b/libyasm/tests/Makefile.inc @@ -2,6 +2,11 @@ TESTS += bitvect_test TESTS += floatnum_test +TESTS += libyasm/tests/libyasm_test.sh + +EXTRA_DIST += libyasm/tests/libyasm_test.sh +EXTRA_DIST += libyasm/tests/duplabel-err.asm +EXTRA_DIST += libyasm/tests/duplabel-err.errwarn noinst_PROGRAMS += bitvect_test noinst_PROGRAMS += floatnum_test diff --git a/libyasm/tests/duplabel-err.asm b/libyasm/tests/duplabel-err.asm new file mode 100644 index 00000000..3d666b35 --- /dev/null +++ b/libyasm/tests/duplabel-err.asm @@ -0,0 +1,18 @@ +%macro TESTMAC 0 +label: + mov ax, 5 + mov dx, 4 + mov cx, 3 +%endmacro + +db 6 + +db 7 + +TESTMAC + +db 8 +db 9 +TESTMAC +db 10 +TESTMAC diff --git a/libyasm/tests/duplabel-err.errwarn b/libyasm/tests/duplabel-err.errwarn new file mode 100644 index 00000000..69014ad8 --- /dev/null +++ b/libyasm/tests/duplabel-err.errwarn @@ -0,0 +1,4 @@ +-:16: redefinition of `label' +-:12: `label' previously defined here +-:18: redefinition of `label' +-:12: `label' previously defined here diff --git a/libyasm/tests/libyasm_test.sh b/libyasm/tests/libyasm_test.sh new file mode 100755 index 00000000..de980947 --- /dev/null +++ b/libyasm/tests/libyasm_test.sh @@ -0,0 +1,4 @@ +#! /bin/sh +# $IdPath$ +${srcdir}/out_test.sh libyasm_test libyasm/tests "libyasm" "-f bin" "" +exit $?