]> granicus.if.org Git - yasm/commitdiff
Revamp error/warning handling.
authorPeter Johnson <peter@tortall.net>
Sat, 18 May 2002 09:55:42 +0000 (09:55 -0000)
committerPeter Johnson <peter@tortall.net>
Sat, 18 May 2002 09:55:42 +0000 (09:55 -0000)
svn path=/trunk/yasm/; revision=622

frontends/yasm/yasm.c
libyasm/errwarn.c
libyasm/errwarn.h
modules/objfmts/bin/tests/integer-warn.errwarn
src/errwarn.c
src/errwarn.h
src/main.c
src/objfmts/bin/tests/integer-warn.errwarn

index 37c867378f123dfb1c8c2e4b98835e999dffa308..8a7c4c1bf92422044e7d205613d72ff9b8f8224a 100644 (file)
@@ -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);
index 5f66d43b139feb6985b289a92a59bcd5bac463c6..b6cf79231d48a91366d831d899d1ac60c2e0c739 100644 (file)
@@ -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 line<lindex.
+     * Start with the last entry added to speed the search.
+     */
+    ins_we = previous_we;
+    first = SLIST_FIRST(&errwarns);
+    if (!ins_we || !first)
+       action = INS_HEAD;
+    while (action == INS_NONE) {
+       next = SLIST_NEXT(ins_we, link);
+       if (lindex < ins_we->line) {
+           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;
 }
index e55ac18abda1e120104da43221495a54cb00f7d0..bc95e328bacc22a1f8d08c456fc48e26bf66ec3a 100644 (file)
@@ -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
index 8be45269d170f851f82a6481fcb7b98adc6e3c57..973e8d3979369b9076b1fba709674ddaa58400f1 100644 (file)
@@ -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
index 5f66d43b139feb6985b289a92a59bcd5bac463c6..b6cf79231d48a91366d831d899d1ac60c2e0c739 100644 (file)
@@ -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 line<lindex.
+     * Start with the last entry added to speed the search.
+     */
+    ins_we = previous_we;
+    first = SLIST_FIRST(&errwarns);
+    if (!ins_we || !first)
+       action = INS_HEAD;
+    while (action == INS_NONE) {
+       next = SLIST_NEXT(ins_we, link);
+       if (lindex < ins_we->line) {
+           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;
 }
index e55ac18abda1e120104da43221495a54cb00f7d0..bc95e328bacc22a1f8d08c456fc48e26bf66ec3a 100644 (file)
@@ -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
index 37c867378f123dfb1c8c2e4b98835e999dffa308..8a7c4c1bf92422044e7d205613d72ff9b8f8224a 100644 (file)
@@ -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);
index 8be45269d170f851f82a6481fcb7b98adc6e3c57..973e8d3979369b9076b1fba709674ddaa58400f1 100644 (file)
@@ -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