bison-patches
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH 3/3] warnings: factoring: complaints


From: Victor Santet
Subject: [PATCH 3/3] warnings: factoring: complaints
Date: Thu, 28 Jun 2012 16:44:21 +0200

* src/complain.c (error_message): Accept warning categories (an integer) as
argument.
Location is a 'const location *' instead of 'location *'.
(ERROR_MESSAGE): Delete it.
* src/complain.c, src/complain.h (complains): New function.
(complain, complain_at, complain_at_indent): Generic functions for
complaints. Call 'complains'.
(warn_at, warn_at_indent, warn, yacc_at, midrule_value_at)
(fatal_at, fatal): Delete them. Adjust dependencies.
* src/complain.h (enum warnings): New fields 'complaint' and 'fatal'.
* bootstrap.conf (XGETTEXT_OPTIONS): Adjust.
---
 bootstrap.conf   |    6 +-
 src/complain.c   |  164 +++++++++++++++++++-----------------------------------
 src/complain.h   |   62 +++++----------------
 src/conflicts.c  |   14 ++---
 src/files.c      |    6 +-
 src/getargs.c    |    5 +-
 src/gram.c       |    2 +-
 src/location.c   |    4 +-
 src/muscle-tab.c |   34 +++++------
 src/parse-gram.y |    7 ++-
 src/reader.c     |   62 +++++++++++----------
 src/reduce.c     |   28 +++++-----
 src/scan-code.l  |   64 +++++++++++----------
 src/scan-gram.l  |   44 ++++++++-------
 src/scan-skel.l  |   71 ++++++++++++-----------
 src/symlist.c    |    3 +-
 src/symtab.c     |   83 +++++++++++++--------------
 17 files changed, 301 insertions(+), 358 deletions(-)

diff --git a/bootstrap.conf b/bootstrap.conf
index cff387f..486268d 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -45,9 +45,9 @@ gnulib_modules='
 XGETTEXT_OPTIONS=$XGETTEXT_OPTIONS'\\\
  --from-code=UTF-8\\\
  --flag=asprintf:2:c-format\\\
- --flag=complain:1:c-format --flag=complain_at:2:c-format\\\
- --flag=fatal:1:c-format --flag=fatal_at:2:c-format\\\
- --flag=warn:1:c-format  --flag=warn_at:2:c-format\\\
+ --flag=complain:2:c-format\\\
+ --flag=complain_at:3:c-format\\\
+ --flag=complain_at_indent:4:c-format\\\
  --flag=unexpected_end:2:c-format\\\
 '
 XGETTEXT_OPTIONS_RUNTIME=$XGETTEXT_OPTIONS'\\\
diff --git a/src/complain.c b/src/complain.c
index fadef5a..3c6b569 100644
--- a/src/complain.c
+++ b/src/complain.c
@@ -29,7 +29,7 @@
 #include "files.h"
 #include "getargs.h"
 
-int warnings_flag = Wconflicts_sr | Wconflicts_rr | Wother;
+warnings warnings_flag = Wconflicts_sr | Wconflicts_rr | Wother;
 
 bool complaint_issued;
 static unsigned *indent_ptr = 0;
@@ -49,8 +49,7 @@ static unsigned *indent_ptr = 0;
  */
 static
 void
-error_message (location *loc,
-               const char *prefix,
+error_message (const location *loc, warnings flags, const char *prefix,
                const char *message, va_list args)
 {
   unsigned pos = 0;
@@ -84,133 +83,86 @@ error_message (location *loc,
   }
 }
 
-/** Wrap error_message() with varargs handling. */
-#define ERROR_MESSAGE(Loc, Prefix, Message)     \
-{                                               \
-  va_list args;                                 \
-  va_start (args, Message);                     \
-  error_message (Loc, Prefix, Message, args);   \
-  va_end (args);                                \
-}
-
-
-/*--------------------------------.
-| Report a warning, and proceed.  |
-`--------------------------------*/
+/** Raise a complaint. That can be a fatal error, a complaint or just a
+    warning.  */
 
-void
-set_warning_issued (void)
+static inline void
+complains (const location *loc, warnings flags, const char *message,
+           va_list args)
 {
-  static bool warning_issued = false;
-  if (!warning_issued && (warnings_flag & Werror))
+  if (flags & complaint)
     {
-      fprintf (stderr, "%s: warnings being treated as errors\n", program_name);
+      error_message (loc, complaint, NULL, message, args);
       complaint_issued = true;
     }
-  warning_issued = true;
-}
-
-void
-warn_at (location loc, const char *message, ...)
-{
-  if (!(warnings_flag & Wother))
-    return;
-  set_warning_issued ();
-  ERROR_MESSAGE (&loc, _("warning"), message);
-}
-
-void
-warn_at_indent (location loc, unsigned *indent,
-                const char *message, ...)
-{
-  if (!(warnings_flag & Wother))
-    return;
-  set_warning_issued ();
-  indent_ptr = indent;
-  ERROR_MESSAGE (&loc, _("warning"), message);
+  else if (flags & fatal)
+    {
+      error_message (loc, fatal, _("fatal error"), message, args);
+      exit (EXIT_FAILURE);
+    }
+  else if (flags & Wyacc)
+    {
+      if (yacc_flag)
+        {
+          error_message (loc, flags, NULL, message, args);
+          complaint_issued = true;
+        }
+      else if (warnings_flag & Wyacc)
+        {
+          set_warning_issued ();
+          error_message (loc, flags, _("warning"), message, args);
+        }
+    }
+  else
+    {
+      if (! (warnings_flag & flags))
+        return;
+      set_warning_issued ();
+      error_message (loc, flags, _("warning"), message, args);
+    }
 }
 
 void
-warn (const char *message, ...)
+complain (warnings flags, const char *message, ...)
 {
-  if (!(warnings_flag & Wother))
-    return;
-  set_warning_issued ();
-  ERROR_MESSAGE (NULL, _("warning"), message);
+  va_list args;
+  va_start (args, message);
+  complains (NULL, flags, message, args);
+  va_end (args);
 }
 
-
-/*-----------------------------------------------------------.
-| An error has occurred, but we can proceed, and die later.  |
-`-----------------------------------------------------------*/
-
 void
-complain_at (location loc, const char *message, ...)
+complain_at (location loc, warnings flags, const char *message, ...)
 {
-  ERROR_MESSAGE (&loc, NULL, message);
-  complaint_issued = true;
+  va_list args;
+  va_start (args, message);
+  complains (&loc, flags, message, args);
+  va_end (args);
 }
 
-void
-complain_at_indent (location loc, unsigned *indent,
-                    const char *message, ...)
+void complain_at_indent (location loc, warnings flags, unsigned *indent,
+                         const char *message, ...)
 {
   indent_ptr = indent;
-  ERROR_MESSAGE (&loc, NULL, message);
-  complaint_issued = true;
-}
 
-void
-complain (const char *message, ...)
-{
-  ERROR_MESSAGE (NULL, NULL, message);
-  complaint_issued = true;
+  va_list args;
+  va_start (args, message);
+  complains (&loc, flags, message, args);
+  va_end (args);
 }
 
-
-/*--------------------------------------------------------------.
-| An incompatibility with POSIX Yacc: mapped either to warn* or |
-| complain* depending on yacc_flag.                             |
-`--------------------------------------------------------------*/
+/*--------------------------------.
+| Report a warning, and proceed.  |
+`--------------------------------*/
 
 void
-yacc_at (location loc, const char *message, ...)
+set_warning_issued (void)
 {
-  if (yacc_flag)
+  static bool warning_issued = false;
+  if (!warning_issued && (warnings_flag & Werror))
     {
-      ERROR_MESSAGE (&loc, NULL, message);
+      fprintf (stderr, "%s: warnings being treated as errors\n", program_name);
       complaint_issued = true;
     }
-  else if (warnings_flag & Wyacc)
-    {
-      set_warning_issued ();
-      ERROR_MESSAGE (&loc, _("warning"), message);
-    }
-}
-
-void
-midrule_value_at (location loc, const char *message, ...)
-{
-  if (!(warnings_flag & Wmidrule_values))
-    return;
-  set_warning_issued ();
-  ERROR_MESSAGE (&loc, _("warning"), message);
-}
-
-/*-------------------------------------------------.
-| A severe error has occurred, we cannot proceed.  |
-`-------------------------------------------------*/
-
-void
-fatal_at (location loc, const char *message, ...)
-{
-  ERROR_MESSAGE (&loc, _("fatal error"), message);
-  exit (EXIT_FAILURE);
-}
-
-void
-fatal (const char *message, ...)
-{
-  ERROR_MESSAGE (NULL, _("fatal error"), message);
-  exit (EXIT_FAILURE);
+  warning_issued = true;
 }
diff --git a/src/complain.h b/src/complain.h
index 30e7c86..79f2017 100644
--- a/src/complain.h
+++ b/src/complain.h
@@ -29,7 +29,7 @@ extern "C" {
 | --warnings.  |
 `-------------*/
 
-enum warnings
+typedef enum
   {
     Wnone             = 0,      /**< Issue no warnings.  */
     Werror            = 1 << 0, /**< Warnings are treated as errors.  */
@@ -38,11 +38,13 @@ enum warnings
     Wconflicts_sr     = 1 << 3, /**< S/R conflicts.  */
     Wconflicts_rr     = 1 << 4, /**< R/R conflicts.  */
     Wother            = 1 << 5, /**< All other warnings.  */
+    complaint         = 1 << 6, /**< All complaints.  */
+    fatal             = 1 << 7, /**< All fatal errors.  */
     Wall              = ~Werror /**< All above warnings.  */
-  };
+  } warnings;
 
 /** What warnings are issued.  */
-extern int warnings_flag;
+extern warnings warnings_flag;
 
 /** Record that a warning is about to be issued, and treat it as an
     error if <tt>warnings_flag & Werror</tt>.  This is exported
@@ -51,56 +53,18 @@ extern int warnings_flag;
     the normal warning format.  */
 void set_warning_issued (void);
 
-/** Informative messages, but we proceed.  Report iff
-    <tt>warnings_flag & Wother</tt>.  */
-
-void warn (char const *format, ...)
-  __attribute__ ((__format__ (__printf__, 1, 2)));
-
-void warn_at (location loc, char const *format, ...)
-  __attribute__ ((__format__ (__printf__, 2, 3)));
-
-/* Generate a message aligned by an indent.
-   When *indent == 0, assign message's indent to *indent,
-   When *indent > 0, align the message by *indent value. */
-void warn_at_indent (location loc, unsigned *indent,
-                     char const *format, ...)
-  __attribute__ ((__format__ (__printf__, 3, 4)));
-
-/** An error, but we continue and die later.  */
-
-void complain (char const *format, ...)
-  __attribute__ ((__format__ (__printf__, 1, 2)));
-
-void complain_at (location loc, char const *format, ...)
+/** Make a complaint, but don't specify any location.  */
+void complain (warnings flags, char const *message, ...)
   __attribute__ ((__format__ (__printf__, 2, 3)));
 
-/* Generate a message aligned by an indent.
-   When *indent == 0, assign message's indent to *indent,
-   When *indent > 0, align the message by *indent value. */
-void complain_at_indent (location loc, unsigned *indent,
-                         char const *format, ...)
+/** Make a complaint with location.  */
+void complain_at (location loc, warnings flags, char const *message, ...)
   __attribute__ ((__format__ (__printf__, 3, 4)));
 
-/** An incompatibility with POSIX Yacc: mapped either to warn* or
-    complain* depending on yacc_flag. */
-
-void yacc_at (location loc, char const *format, ...)
-  __attribute__ ((__format__ (__printf__, 2, 3)));
-
-/** A midrule-value warning.  Report iff
-    <tt>warnings_flag & Wmidrule_values</tt>.  */
-
-void midrule_value_at (location loc, char const *format, ...)
-  __attribute__ ((__format__ (__printf__, 2, 3)));
-
-/** A fatal error, causing immediate exit.  */
-
-void fatal (char const *format, ...)
-  __attribute__ ((__noreturn__, __format__ (__printf__, 1, 2)));
-
-void fatal_at (location loc, char const *format, ...)
-  __attribute__ ((__noreturn__, __format__ (__printf__, 2, 3)));
+/** Make a complaint with location and some indentation.  */
+void complain_at_indent (location loc, warnings flags, unsigned *indent,
+                         char const *message, ...)
+  __attribute__ ((__format__ (__printf__, 4, 5)));
 
 /** Whether an error was reported.  */
 extern bool complaint_issued;
diff --git a/src/conflicts.c b/src/conflicts.c
index 4b05e61..ccd50eb 100644
--- a/src/conflicts.c
+++ b/src/conflicts.c
@@ -584,7 +584,7 @@ conflicts_print (void)
 
   if (! glr_parser && rrc_total > 0 && expected_rr_conflicts != -1)
     {
-      warn (_("%%expect-rr applies only to GLR parsers"));
+      complain (Wother, _("%%expect-rr applies only to GLR parsers"));
       expected_rr_conflicts = -1;
     }
 
@@ -618,14 +618,14 @@ conflicts_print (void)
   if (expected_sr_conflicts != -1 || expected_rr_conflicts != -1)
     {
       if (! src_ok)
-        complain (ngettext ("expected %d shift/reduce conflict",
-                            "expected %d shift/reduce conflicts",
-                            src_expected),
+        complain (complaint, ngettext ("expected %d shift/reduce conflict",
+                                       "expected %d shift/reduce conflicts",
+                                       src_expected),
                   src_expected);
       if (! rrc_ok)
-        complain (ngettext ("expected %d reduce/reduce conflict",
-                            "expected %d reduce/reduce conflicts",
-                            rrc_expected),
+        complain (complaint, ngettext ("expected %d reduce/reduce conflict",
+                                       "expected %d reduce/reduce conflicts",
+                                       rrc_expected),
                   rrc_expected);
     }
 }
diff --git a/src/files.c b/src/files.c
index 88234bf..ae9fc7f 100644
--- a/src/files.c
+++ b/src/files.c
@@ -360,7 +360,7 @@ output_file_name_check (char **file_name)
   bool conflict = false;
   if (STREQ (*file_name, grammar_file))
     {
-      complain (_("refusing to overwrite the input file %s"),
+      complain (complaint, _("refusing to overwrite the input file %s"),
                 quote (*file_name));
       conflict = true;
     }
@@ -370,8 +370,8 @@ output_file_name_check (char **file_name)
       for (i = 0; i < file_names_count; i++)
         if (STREQ (file_names[i], *file_name))
           {
-            warn (_("conflicting outputs to file %s"),
-                  quote (*file_name));
+            complain (Wother, _("conflicting outputs to file %s"),
+                      quote (*file_name));
             conflict = true;
           }
     }
diff --git a/src/getargs.c b/src/getargs.c
index d0b1e94..f5d3767 100644
--- a/src/getargs.c
+++ b/src/getargs.c
@@ -401,7 +401,8 @@ skeleton_arg (char const *arg, int prio, location loc)
       skeleton = arg;
     }
   else if (prio == skeleton_prio)
-    complain_at (loc, _("multiple skeleton declarations are invalid"));
+    complain_at (loc, complaint,
+                 _("multiple skeleton declarations are invalid"));
 }
 
 void
@@ -426,7 +427,7 @@ language_argmatch (char const *arg, int prio, location loc)
   else
     return;
 
-  complain_at (loc, msg, quotearg_colon (arg));
+  complain_at (loc, complaint, msg, quotearg_colon (arg));
 }
 
 /*----------------------.
diff --git a/src/gram.c b/src/gram.c
index ac41a32..810311f 100644
--- a/src/gram.c
+++ b/src/gram.c
@@ -308,7 +308,7 @@ grammar_rules_useless_report (const char *message)
   for (r = 0; r < nrules ; ++r)
     if (!rules[r].useful)
       {
-        warn_at (rules[r].location, "%s: ", message);
+        complain_at (rules[r].location, Wother, "%s: ", message);
         if (warnings_flag & Wother)
           {
             rule_print (&rules[r], stderr);
diff --git a/src/location.c b/src/location.c
index 88887e9..9960d62 100644
--- a/src/location.c
+++ b/src/location.c
@@ -90,9 +90,9 @@ location_compute (location *loc, boundary *cur, char const 
*token, size_t size)
   loc->end = *cur;
 
   if (line == INT_MAX && loc->start.line != INT_MAX)
-    warn_at (*loc, _("line number overflow"));
+    complain_at (*loc, Wother, _("line number overflow"));
   if (column == INT_MAX && loc->start.column != INT_MAX)
-    warn_at (*loc, _("column number overflow"));
+    complain_at (*loc, Wother, _("column number overflow"));
 }
 
 
diff --git a/src/muscle-tab.c b/src/muscle-tab.c
index 57050d0..47d9fb6 100644
--- a/src/muscle-tab.c
+++ b/src/muscle-tab.c
@@ -439,10 +439,10 @@ muscle_percent_define_insert (char const *variable, 
location variable_loc,
         atoi (muscle_find_const (how_name));
       if (how_old == MUSCLE_PERCENT_DEFINE_F)
         return;
-      complain_at (variable_loc, _("%%define variable %s redefined"),
+      complain_at (variable_loc, complaint, _("%%define variable %s 
redefined"),
                    quote (variable));
-      complain_at (muscle_percent_define_get_loc (variable),
-                   _("previous definition"));
+      location loc = muscle_percent_define_get_loc (variable);
+      complain_at (loc, complaint, _("previous definition"));
     }
 
   MUSCLE_INSERT_STRING (name, value);
@@ -503,7 +503,7 @@ muscle_percent_define_get_loc (char const *variable)
   char const *loc_name;
   loc_name = UNIQSTR_CONCAT ("percent_define_loc(", variable, ")");
   if (!muscle_find_const (loc_name))
-    fatal(_("%s: undefined %%define variable %s"),
+    complain (fatal, _("%s: undefined %%define variable %s"),
           "muscle_percent_define_get_loc", quote (variable));
   return muscle_location_decode (loc_name);
 }
@@ -517,7 +517,7 @@ muscle_percent_define_get_syncline (char const *variable)
     UNIQSTR_CONCAT ("percent_define_syncline(", variable, ")");
   syncline = muscle_find_const (syncline_name);
   if (!syncline)
-    fatal(_("%s: undefined %%define variable %s"),
+    complain (fatal, _("%s: undefined %%define variable %s"),
           "muscle_percent_define_get_syncline", quote (variable));
   return syncline;
 }
@@ -562,15 +562,16 @@ muscle_percent_define_flag_if (char const *variable)
       else if (!muscle_find_const (invalid_boolean_name))
         {
           muscle_insert (invalid_boolean_name, "");
-          complain_at(muscle_percent_define_get_loc (variable),
-                      _("invalid value for %%define Boolean variable %s"),
-                      quote (variable));
+          location loc = muscle_percent_define_get_loc (variable);
+          complain_at (loc, complaint,
+                       _("invalid value for %%define Boolean variable %s"),
+                       quote (variable));
         }
       free (value);
     }
   else
-    fatal(_("%s: undefined %%define variable %s"),
-          "muscle_percent_define_flag", quote (variable));
+    complain (fatal, _("%s: undefined %%define variable %s"),
+              "muscle_percent_define_flag", quote (variable));
 
   return result;
 }
@@ -620,11 +621,12 @@ muscle_percent_define_check_values (char const * const 
*values)
           if (!*values)
             {
               location loc = muscle_percent_define_get_loc (*variablep);
-              complain_at(loc,
-                          _("invalid value for %%define variable %s: %s"),
-                          quote (*variablep), quote_n (1, value));
+              complain_at (loc, complaint,
+                           _("invalid value for %%define variable %s: %s"),
+                           quote (*variablep), quote_n (1, value));
               for (values = variablep + 1; *values; ++values)
-                complain_at (loc, _("accepted value: %s"), quote (*values));
+                complain_at (loc, complaint, _("accepted value: %s"),
+                             quote (*values));
             }
           else
             {
@@ -634,8 +636,8 @@ muscle_percent_define_check_values (char const * const 
*values)
           free (value);
         }
       else
-        fatal (_("%s: undefined %%define variable %s"),
-               "muscle_percent_define_check_values", quote (*variablep));
+        complain (fatal, _("%s: undefined %%define variable %s"),
+                  "muscle_percent_define_check_values", quote (*variablep));
     }
 }
 
diff --git a/src/parse-gram.y b/src/parse-gram.y
index c932ba5..ee1c324 100644
--- a/src/parse-gram.y
+++ b/src/parse-gram.y
@@ -773,7 +773,8 @@ add_param (param_type type, char *decl, location loc)
   }
 
   if (! name_start)
-    complain_at (loc, _("missing identifier in parameter declaration"));
+    complain_at (loc, complaint,
+                 _("missing identifier in parameter declaration"));
   else
     {
       char *name = xmemdup0 (name_start, strspn (name_start, alphanum));
@@ -793,7 +794,7 @@ version_check (location const *loc, char const *version)
 {
   if (strverscmp (version, PACKAGE_VERSION) > 0)
     {
-      complain_at (*loc, "require bison %s, but have %s",
+      complain_at (*loc, complaint, "require bison %s, but have %s",
                    version, PACKAGE_VERSION);
       exit (EX_MISMATCH);
     }
@@ -802,7 +803,7 @@ version_check (location const *loc, char const *version)
 static void
 gram_error (location const *loc, char const *msg)
 {
-  complain_at (*loc, "%s", msg);
+  complain_at (*loc, complaint, "%s", msg);
 }
 
 char const *
diff --git a/src/reader.c b/src/reader.c
index c456cbf..53b21ef 100644
--- a/src/reader.c
+++ b/src/reader.c
@@ -59,7 +59,7 @@ void
 grammar_start_symbol_set (symbol *sym, location loc)
 {
   if (start_flag)
-    complain_at (loc, _("multiple %s declarations"), "%start");
+    complain_at (loc, complaint, _("multiple %s declarations"), "%start");
   else
     {
       start_flag = true;
@@ -128,11 +128,11 @@ record_merge_function_type (int merger, uniqstr type, 
location declaration_loc)
   aver (merge_function != NULL && merger_find == merger);
   if (merge_function->type != NULL && !UNIQSTR_EQ (merge_function->type, type))
     {
-      complain_at (declaration_loc,
-                   _("result type clash on merge function %s: <%s> != <%s>"),
-                   quote (merge_function->name), type, merge_function->type);
-      complain_at (merge_function->type_declaration_location,
-                   _("previous declaration"));
+      complain_at (declaration_loc, complaint,
+                _("result type clash on merge function %s: <%s> != <%s>"),
+                quote (merge_function->name), type, merge_function->type);
+      complain_at (merge_function->type_declaration_location, complaint,
+                _("previous declaration"));
     }
   merge_function->type = uniqstr_new (type);
   merge_function->type_declaration_location = declaration_loc;
@@ -197,9 +197,9 @@ assign_named_ref (symbol_list *p, named_ref *name)
 
   if (name->id == sym->tag)
     {
-      warn_at (name->loc,
-               _("duplicated symbol name for %s ignored"),
-               quote (sym->tag));
+      complain_at (name->loc, Wother,
+                   _("duplicated symbol name for %s ignored"),
+                   quote (sym->tag));
       named_ref_free (name);
     }
   else
@@ -242,7 +242,8 @@ grammar_current_rule_begin (symbol *lhs, location loc,
       ++nvars;
     }
   else if (lhs->class == token_sym)
-    complain_at (loc, _("rule given for %s, which is a token"), lhs->tag);
+    complain_at (loc, complaint, _("rule given for %s, which is a token"),
+                 lhs->tag);
 }
 
 
@@ -296,14 +297,14 @@ grammar_rule_check (const symbol_list *r)
           const char *rhs_type =
             first_rhs->type_name ? first_rhs->type_name : "";
           if (!UNIQSTR_EQ (lhs_type, rhs_type))
-            warn_at (r->location,
-                     _("type clash on default action: <%s> != <%s>"),
-                     lhs_type, rhs_type);
+            complain_at (r->location, Wother,
+                         _("type clash on default action: <%s> != <%s>"),
+                         lhs_type, rhs_type);
         }
       /* Warn if there is no default for $$ but we need one.  */
       else
-        warn_at (r->location,
-                 _("empty rule for typed nonterminal, and no action"));
+        complain_at (r->location, Wother,
+                     _("empty rule for typed nonterminal, and no action"));
     }
 
   /* Check that symbol values that should be used are in fact used.  */
@@ -318,12 +319,12 @@ grammar_rule_check (const symbol_list *r)
             /* The default action, $$ = $1, `uses' both.  */
             && (r->action_props.code || (n != 0 && n != 1)))
           {
-            void (*warn_at_ptr)(location, char const*, ...) =
-              midrule_warning ? midrule_value_at : warn_at;
+            int warn_flag =
+              midrule_warning ? Wmidrule_values : Wother;
             if (n)
-              warn_at_ptr (r->location, _("unused value: $%d"), n);
+              complain_at (r->location, warn_flag, _("unused value: $%d"), n);
             else
-              warn_at_ptr (r->location, _("unset value: $$"));
+              complain_at (r->location, warn_flag, _("unset value: $$"));
           }
       }
   }
@@ -334,8 +335,8 @@ grammar_rule_check (const symbol_list *r)
   if (r->ruleprec
       && r->ruleprec->tag[0] != '\'' && r->ruleprec->tag[0] != '"'
       && r->ruleprec->status != declared && !r->ruleprec->prec)
-    warn_at (r->location, _("token for %%prec is not defined: %s"),
-             r->ruleprec->tag);
+    complain_at (r->location, Wother,
+                 _("token for %%prec is not defined: %s"), r->ruleprec->tag);
 }
 
 
@@ -425,7 +426,7 @@ grammar_current_rule_prec_set (symbol *precsym, location 
loc)
      token.  */
   symbol_class_set (precsym, token_sym, loc, false);
   if (current_rule->ruleprec)
-    complain_at (loc, _("only one %s allowed per rule"), "%prec");
+    complain_at (loc, complaint, _("only one %s allowed per rule"), "%prec");
   current_rule->ruleprec = precsym;
 }
 
@@ -435,11 +436,13 @@ void
 grammar_current_rule_dprec_set (int dprec, location loc)
 {
   if (! glr_parser)
-    warn_at (loc, _("%s affects only GLR parsers"), "%dprec");
+    complain_at (loc, Wother, _("%s affects only GLR parsers"),
+                 "%dprec");
   if (dprec <= 0)
-    complain_at (loc, _("%s must be followed by positive number"), "%dprec");
+    complain_at (loc, complaint, _("%s must be followed by positive number"),
+                 "%dprec");
   else if (current_rule->dprec != 0)
-    complain_at (loc, _("only one %s allowed per rule"), "%dprec");
+    complain_at (loc, complaint, _("only one %s allowed per rule"), "%dprec");
   current_rule->dprec = dprec;
 }
 
@@ -450,9 +453,10 @@ void
 grammar_current_rule_merge_set (uniqstr name, location loc)
 {
   if (! glr_parser)
-    warn_at (loc, _("%s affects only GLR parsers"), "%merge");
+    complain_at (loc, Wother, _("%s affects only GLR parsers"),
+                 "%merge");
   if (current_rule->merger != 0)
-    complain_at (loc, _("only one %s allowed per rule"), "%merge");
+    complain_at (loc, complaint, _("only one %s allowed per rule"), "%merge");
   current_rule->merger = get_merge_function (name);
   current_rule->merger_declaration_location = loc;
 }
@@ -551,7 +555,7 @@ packgram (void)
           /* Don't allow rule_length == INT_MAX, since that might
              cause confusion with strtol if INT_MAX == LONG_MAX.  */
           if (rule_length == INT_MAX)
-              fatal_at (rules[ruleno].location, _("rule is too long"));
+            complain_at (rules[ruleno].location, fatal, _("rule is too long"));
 
           /* item_number = symbol_number.
              But the former needs to contain more: negative rule numbers. */
@@ -669,7 +673,7 @@ check_and_convert_grammar (void)
 {
   /* Grammar has been read.  Do some checking.  */
   if (nrules == 0)
-    fatal (_("no rules in the input grammar"));
+    complain (fatal, _("no rules in the input grammar"));
 
   /* If the user did not define her ENDTOKEN, do it now. */
   if (!endtoken)
diff --git a/src/reduce.c b/src/reduce.c
index 736cbb6..5a60e0a 100644
--- a/src/reduce.c
+++ b/src/reduce.c
@@ -299,9 +299,9 @@ nonterminals_reduce (void)
       {
         nontermmap[i - ntokens] = n++;
         if (symbols[i]->status != used)
-          warn_at (symbols[i]->location,
-                   _("nonterminal useless in grammar: %s"),
-                   symbols[i]->tag);
+          complain_at (symbols[i]->location, Wother,
+                       _("nonterminal useless in grammar: %s"),
+                       symbols[i]->tag);
       }
 
 
@@ -383,15 +383,15 @@ static void
 reduce_print (void)
 {
   if (nuseless_nonterminals > 0)
-    warn (ngettext ("%d nonterminal useless in grammar",
-                    "%d nonterminals useless in grammar",
-                    nuseless_nonterminals),
-          nuseless_nonterminals);
+    complain (Wother, ngettext ("%d nonterminal useless in grammar",
+                                        "%d nonterminals useless in grammar",
+                                        nuseless_nonterminals),
+              nuseless_nonterminals);
   if (nuseless_productions > 0)
-    warn (ngettext ("%d rule useless in grammar",
-                    "%d rules useless in grammar",
-                    nuseless_productions),
-          nuseless_productions);
+    complain (Wother, ngettext ("%d rule useless in grammar",
+                                        "%d rules useless in grammar",
+                                        nuseless_productions),
+              nuseless_productions);
 }
 
 void
@@ -416,9 +416,9 @@ reduce_grammar (void)
   reduce_print ();
 
   if (!bitset_test (N, accept->number - ntokens))
-    fatal_at (startsymbol_location,
-              _("start symbol %s does not derive any sentence"),
-              startsymbol->tag);
+    complain_at (startsymbol_location, fatal,
+                 _("start symbol %s does not derive any sentence"),
+                 startsymbol->tag);
 
   /* First reduce the nonterminals, as they renumber themselves in the
      whole grammar.  If you change the order, nonterms would be
diff --git a/src/scan-code.l b/src/scan-code.l
index eed0c9b..24ef5d9 100644
--- a/src/scan-code.l
+++ b/src/scan-code.l
@@ -198,12 +198,12 @@ ref      -?[0-9]+|{id}|"["{id}"]"|"$"
     need_semicolon = true;
   }
   "$"  {
-    warn_at (*loc, _("stray '$'"));
+    complain_at (*loc, Wother, _("stray '$'"));
     obstack_sgrow (&obstack_for_string, "$][");
     need_semicolon = true;
   }
   "@"  {
-    warn_at (*loc, _("stray '@'"));
+    complain_at (*loc, Wother, _("stray '@'"));
     obstack_sgrow (&obstack_for_string, "@@");
     need_semicolon = true;
   }
@@ -228,8 +228,10 @@ ref      -?[0-9]+|{id}|"["{id}"]"|"$"
     if (outer_brace && !yacc_flag && language_prio == default_prio
         && skeleton_prio == default_prio && need_semicolon && ! in_cpp)
       {
-        warn_at (*loc, _("a ';' might be needed at the end of action code"));
-        warn_at (*loc, _("future versions of Bison will not add the ';'"));
+        complain_at (*loc, Wother,
+                     _("a ';' might be needed at the end of action code"));
+        complain_at (*loc, Wother,
+                     _("future versions of Bison will not add the ';'"));
         obstack_1grow (&obstack_for_string, ';');
       }
 
@@ -251,8 +253,8 @@ ref      -?[0-9]+|{id}|"["{id}"]"|"$"
      2.4.2.  */
   YYFAIL {
     STRING_GROW; need_semicolon = true;
-    warn_at (*loc, _("use of YYFAIL, which is deprecated and will be"
-                     " removed"));
+    complain_at (*loc, Wother,
+                 _("use of YYFAIL, which is deprecated and will be removed"));
   }
 
   /* The sole purpose of this is to make sure identifiers that merely
@@ -436,11 +438,13 @@ show_sub_messages (const char* cp, bool 
explicit_bracketing,
       if (var->err == 0)
         {
           if (is_warning)
-            warn_at_indent (var->loc, &indent, _("refers to: %c%s at %s"),
-                            dollar_or_at, var->id, at_spec);
+            complain_at_indent (var->loc, Wother, &indent,
+                                _("refers to: %c%s at %s"), dollar_or_at,
+                                var->id, at_spec);
           else
-            complain_at_indent (var->loc, &indent, _("refers to: %c%s at %s"),
-                                dollar_or_at, var->id, at_spec);
+            complain_at_indent (var->loc, complaint, &indent,
+                                _("refers to: %c%s at %s"), dollar_or_at,
+                                var->id, at_spec);
         }
       else
         {
@@ -483,10 +487,10 @@ show_sub_messages (const char* cp, bool 
explicit_bracketing,
 
           obstack_1grow (&msg_buf, '\0');
           if (is_warning)
-            warn_at_indent (id_loc, &indent, "%s",
-                            (char *) obstack_finish (&msg_buf));
+            complain_at_indent (id_loc, Wother, &indent, "%s",
+                                (char *) obstack_finish (&msg_buf));
           else
-            complain_at_indent (id_loc, &indent, "%s",
+            complain_at_indent (id_loc, complaint, &indent, "%s",
                                 (char *) obstack_finish (&msg_buf));
           obstack_free (&msg_buf, 0);
         }
@@ -529,7 +533,7 @@ parse_ref (char *cp, symbol_list *rule, int rule_length,
         return num;
       else
         {
-          complain_at (text_loc, _("integer out of range: %s"),
+          complain_at (text_loc, complaint, _("integer out of range: %s"),
                        quote (text));
           return INVALID_REF;
         }
@@ -618,8 +622,8 @@ parse_ref (char *cp, symbol_list *rule, int rule_length,
           cp_end - cp : ref_tail_fields - cp;
         unsigned indent = 0;
 
-        complain_at_indent (text_loc, &indent, _("invalid reference: %s"),
-                            quote (text));
+        complain_at_indent (text_loc, complaint, &indent,
+                            _("invalid reference: %s"), quote (text));
         indent += SUB_INDENT;
         if (len == 0)
           {
@@ -629,20 +633,21 @@ parse_ref (char *cp, symbol_list *rule, int rule_length,
             const char *format =
               _("syntax error after '%c', expecting integer, letter,"
                 " '_', '[', or '$'");
-            complain_at_indent (sym_loc, &indent, format, dollar_or_at);
+            complain_at_indent (sym_loc, complaint, &indent, format,
+                                dollar_or_at);
           }
         else if (midrule_rhs_index)
           {
             const char *format =
               _("symbol not found in production before $%d: %.*s");
-            complain_at_indent (rule->location, &indent, format,
+            complain_at_indent (rule->location, complaint, &indent, format,
                                 midrule_rhs_index, len, cp);
           }
         else
           {
             const char *format =
               _("symbol not found in production: %.*s");
-            complain_at_indent (rule->location, &indent, format,
+            complain_at_indent (rule->location, complaint, &indent, format,
                                 len, cp);
           }
 
@@ -656,8 +661,8 @@ parse_ref (char *cp, symbol_list *rule, int rule_length,
         unsigned indent = 0;
         if (variant_count > 1)
           {
-            warn_at_indent (text_loc, &indent, _("misleading reference: %s"),
-                            quote (text));
+            complain_at_indent (text_loc, Wother, &indent,
+                                _("misleading reference: %s"), quote (text));
             show_sub_messages (cp, explicit_bracketing, midrule_rhs_index,
                                dollar_or_at, true, indent + SUB_INDENT);
           }
@@ -671,8 +676,8 @@ parse_ref (char *cp, symbol_list *rule, int rule_length,
     default:
       {
         unsigned indent = 0;
-        complain_at_indent (text_loc, &indent, _("ambiguous reference: %s"),
-                            quote (text));
+        complain_at_indent (text_loc, complaint, &indent,
+                            _("ambiguous reference: %s"), quote (text));
         show_sub_messages (cp, explicit_bracketing, midrule_rhs_index,
                            dollar_or_at, false, indent + SUB_INDENT);
         return INVALID_REF;
@@ -730,7 +735,8 @@ handle_action_dollar (symbol_list *rule, char *text, 
location dollar_loc)
       gt_ptr = cp;
       ++cp;
       if (untyped_var_seen)
-        complain_at (dollar_loc, _("explicit type given in untyped grammar"));
+        complain_at (dollar_loc, complaint,
+                  _("explicit type given in untyped grammar"));
       tag_seen = true;
     }
 
@@ -754,13 +760,14 @@ handle_action_dollar (symbol_list *rule, char *text, 
location dollar_loc)
           if (union_seen | tag_seen)
             {
               if (rule->midrule_parent_rule)
-                complain_at (dollar_loc,
+                complain_at (dollar_loc, complaint,
                              _("$$ for the midrule at $%d of %s"
                                " has no declared type"),
                              rule->midrule_parent_rhs_index,
                              quote (effective_rule->content.sym->tag));
               else
-                complain_at (dollar_loc, _("$$ of %s has no declared type"),
+                complain_at (dollar_loc, complaint,
+                             _("$$ of %s has no declared type"),
                              quote (rule->content.sym->tag));
             }
           else
@@ -782,8 +789,9 @@ handle_action_dollar (symbol_list *rule, char *text, 
location dollar_loc)
       if (!type_name)
         {
           if (union_seen | tag_seen)
-            complain_at (dollar_loc, _("$%s of %s has no declared type"),
-                         cp, quote (effective_rule->content.sym->tag));
+            complain_at (dollar_loc, complaint,
+                         _("$%s of %s has no declared type"), cp,
+                         quote (effective_rule->content.sym->tag));
           else
             untyped_var_seen = true;
           type_name = "";
diff --git a/src/scan-gram.l b/src/scan-gram.l
index d375fc1..de55e75 100644
--- a/src/scan-gram.l
+++ b/src/scan-gram.l
@@ -164,7 +164,8 @@ splice   (\\[ \f\t\v]*\n)*
 <INITIAL,SC_AFTER_IDENTIFIER,SC_BRACKETED_ID,SC_RETURN_BRACKETED_ID>
 {
   /* Comments and white space.  */
-  ","          warn_at (*loc, _("stray ',' treated as white space"));
+  ","
+    complain_at (loc, Wother, _("stray ',' treated as white space"));
   [ \f\n\t\v]  |
   "//".*       ;
   "/*" {
@@ -239,7 +240,7 @@ splice   (\\[ \f\t\v]*\n)*
   "%yacc"                           return PERCENT_YACC;
 
   {directive} {
-    complain_at (*loc, _("invalid directive: %s"), quote (yytext));
+    complain_at (*loc, complaint, _("invalid directive: %s"), quote (yytext));
   }
 
   "="                     return EQUAL;
@@ -265,7 +266,7 @@ splice   (\\[ \f\t\v]*\n)*
   /* Identifiers may not start with a digit.  Yet, don't silently
      accept "1FOO" as "1 FOO".  */
   {int}{id} {
-    complain_at (*loc, _("invalid identifier: %s"), quote (yytext));
+    complain_at (*loc, complaint, _("invalid identifier: %s"), quote (yytext));
   }
 
   /* Characters.  */
@@ -323,7 +324,7 @@ splice   (\\[ \f\t\v]*\n)*
   }
 
   . {
-    complain_at (*loc, _("invalid character: %s"), quote (yytext));
+    complain_at (*loc, complaint, _("invalid character: %s"), quote (yytext));
   }
 
   <<EOF>> {
@@ -340,7 +341,7 @@ splice   (\\[ \f\t\v]*\n)*
 
 <SC_ESCAPED_CHARACTER,SC_ESCAPED_STRING,SC_TAG>
 {
-  \0        complain_at (*loc, _("invalid null character"));
+  \0        complain_at (*loc, complaint, _("invalid null character"));
 }
 
 
@@ -392,7 +393,8 @@ splice   (\\[ \f\t\v]*\n)*
   {id} {
     if (bracketed_id_str)
       {
-        complain_at (*loc, _("unexpected identifier in bracketed name: %s"),
+        complain_at (*loc, complaint,
+                     _("unexpected identifier in bracketed name: %s"),
                      quote (yytext));
       }
     else
@@ -414,10 +416,10 @@ splice   (\\[ \f\t\v]*\n)*
           }
       }
     else
-      complain_at (*loc, _("an identifier expected"));
+      complain_at (*loc, complaint, _("an identifier expected"));
   }
   . {
-    complain_at (*loc, _("invalid character in bracketed name: %s"),
+    complain_at (*loc, complaint, _("invalid character in bracketed name: %s"),
                  quote (yytext));
   }
   <<EOF>> {
@@ -515,12 +517,13 @@ splice   (\\[ \f\t\v]*\n)*
       /* FIXME: Eventually, make these errors.  */
       if (last_string[0] == '\0')
         {
-          warn_at (*loc, _("empty character literal"));
+          complain_at (*loc, Wother, _("empty character literal"));
           /* '\0' seems dangerous even if we are about to complain.  */
           val->character = '\'';
         }
       else if (last_string[1] != '\0')
-        warn_at (*loc, _("extra characters in character literal"));
+        complain_at (*loc, Wother,
+                  _("extra characters in character literal"));
     }
     if (yytext[0] == '\n')
       unexpected_newline (token_start, "'");
@@ -536,12 +539,13 @@ splice   (\\[ \f\t\v]*\n)*
       /* FIXME: Eventually, make these errors.  */
       if (last_string[0] == '\0')
         {
-          warn_at (*loc, _("empty character literal"));
+          complain_at (*loc, Wother, _("empty character literal"));
           /* '\0' seems dangerous even if we are about to complain.  */
           val->character = '\'';
         }
       else if (last_string[1] != '\0')
-        warn_at (*loc, _("extra characters in character literal"));
+        complain_at (*loc, Wother,
+                  _("extra characters in character literal"));
     }
     unexpected_eof (token_start, "'");
     STRING_FREE;
@@ -594,7 +598,7 @@ splice   (\\[ \f\t\v]*\n)*
   \\[0-7]{1,3} {
     unsigned long int c = strtoul (yytext + 1, NULL, 8);
     if (!c || UCHAR_MAX < c)
-      complain_at (*loc, _("invalid number after \\-escape: %s"),
+      complain_at (*loc, complaint, _("invalid number after \\-escape: %s"),
                    yytext+1);
     else
       obstack_1grow (&obstack_for_string, c);
@@ -604,7 +608,7 @@ splice   (\\[ \f\t\v]*\n)*
     verify (UCHAR_MAX < ULONG_MAX);
     unsigned long int c = strtoul (yytext + 2, NULL, 16);
     if (!c || UCHAR_MAX < c)
-      complain_at (*loc, _("invalid number after \\-escape: %s"),
+      complain_at (*loc, complaint, _("invalid number after \\-escape: %s"),
                    yytext+1);
     else
       obstack_1grow (&obstack_for_string, c);
@@ -624,7 +628,7 @@ splice   (\\[ \f\t\v]*\n)*
   \\(u|U[0-9abcdefABCDEF]{4})[0-9abcdefABCDEF]{4} {
     int c = convert_ucn_to_byte (yytext);
     if (c <= 0)
-      complain_at (*loc, _("invalid number after \\-escape: %s"),
+      complain_at (*loc, complaint, _("invalid number after \\-escape: %s"),
                    yytext+1);
     else
       obstack_1grow (&obstack_for_string, c);
@@ -636,7 +640,8 @@ splice   (\\[ \f\t\v]*\n)*
       p = quote (p);
     else
       p = quotearg_style_mem (escape_quoting_style, p, 1);
-    complain_at (*loc, _("invalid character after \\-escape: %s"), p);
+    complain_at (*loc, complaint, _("invalid character after \\-escape: %s"),
+                 p);
   }
 }
 
@@ -867,7 +872,8 @@ scan_integer (char const *number, int base, location loc)
 
   if (INT_MAX < num)
     {
-      complain_at (loc, _("integer out of range: %s"), quote (number));
+      complain_at (loc, complaint, _("integer out of range: %s"),
+                   quote (number));
       num = INT_MAX;
     }
 
@@ -945,7 +951,7 @@ handle_syncline (char *args, location loc)
   *strchr (file, '"') = '\0';
   if (INT_MAX <= lineno)
     {
-      warn_at (loc, _("line number overflow"));
+      complain_at (loc, Wother, _("line number overflow"));
       lineno = INT_MAX;
     }
   current_file = uniqstr_new (file);
@@ -969,7 +975,7 @@ unexpected_end (boundary start, char const *msgid, char 
const *token_end)
   // Instead of '\'', display "'".
   if (STREQ (token_end, "'\\''"))
     token_end = "\"'\"";
-  complain_at (loc, _(msgid), token_end);
+  complain_at (loc, complaint, _(msgid), token_end);
 }
 
 
diff --git a/src/scan-skel.l b/src/scan-skel.l
index 284a120..17382a7 100644
--- a/src/scan-skel.l
+++ b/src/scan-skel.l
@@ -141,7 +141,8 @@ static void fail_for_invalid_at (char const *at);
 
 <SC_AT_DIRECTIVE_ARGS,SC_AT_DIRECTIVE_SKIP_WS>{
   <<EOF>> {
-    fatal (_("unclosed %s directive in skeleton"), at_directive_argv[0]);
+    complain (fatal, _("unclosed %s directive in skeleton"),
+              at_directive_argv[0]);
   }
 }
 
@@ -188,34 +189,36 @@ at_directive_perform (int at_directive_argc,
            || STREQ (at_directive_argv[0], "@complain")
            || STREQ (at_directive_argv[0], "@fatal"))
     {
-      void (*func)(char const *, ...);
+      warnings complaint_flag;
       switch (at_directive_argv[0][1])
         {
-          case 'w': func = warn; break;
-          case 'c': func = complain; break;
-          case 'f': func = fatal; break;
-          default: aver (false); break;
+        case 'w': complaint_flag = Wother; break;
+        case 'c': complaint_flag = complaint; break;
+        case 'f': complaint_flag = fatal; break;
+        default: aver (false); break;
         }
       switch (at_directive_argc)
         {
           case 2:
-            func (_(at_directive_argv[1]));
+            complain (complaint_flag, "%s", _(at_directive_argv[1]));
             break;
           case 3:
-            func (_(at_directive_argv[1]), at_directive_argv[2]);
+            complain (complaint_flag, _(at_directive_argv[1]),
+                      at_directive_argv[2]);
             break;
           case 4:
-            func (_(at_directive_argv[1]), at_directive_argv[2],
-                  at_directive_argv[3]);
+            complain (complaint_flag, _(at_directive_argv[1]),
+                      at_directive_argv[2], at_directive_argv[3]);
             break;
           case 5:
-            func (_(at_directive_argv[1]), at_directive_argv[2],
-                  at_directive_argv[3], at_directive_argv[4]);
+            complain (complaint_flag, _(at_directive_argv[1]),
+                      at_directive_argv[2], at_directive_argv[3],
+                      at_directive_argv[4]);
             break;
           case 6:
-            func (_(at_directive_argv[1]), at_directive_argv[2],
-                  at_directive_argv[3], at_directive_argv[4],
-                  at_directive_argv[5]);
+            complain (complaint_flag, _(at_directive_argv[1]),
+                      at_directive_argv[2], at_directive_argv[3],
+                      at_directive_argv[4], at_directive_argv[5]);
             break;
           default:
             fail_for_at_directive_too_many_args (at_directive_argv[0]);
@@ -226,39 +229,41 @@ at_directive_perform (int at_directive_argc,
            || STREQ (at_directive_argv[0], "@complain_at")
            || STREQ (at_directive_argv[0], "@fatal_at"))
     {
-      void (*func)(location, char const *, ...);
+      warnings complaint_flag;
       location loc;
       if (at_directive_argc < 4)
         fail_for_at_directive_too_few_args (at_directive_argv[0]);
       switch (at_directive_argv[0][1])
         {
-          case 'w': func = warn_at; break;
-          case 'c': func = complain_at; break;
-          case 'f': func = fatal_at; break;
-          default: aver (false); break;
+        case 'w': complaint_flag = Wother; break;
+        case 'c': complaint_flag = complaint; break;
+        case 'f': complaint_flag = fatal; break;
+        default: aver (false); break;
         }
       boundary_set_from_string (&loc.start, at_directive_argv[1]);
       boundary_set_from_string (&loc.end, at_directive_argv[2]);
       switch (at_directive_argc)
         {
           case 4:
-            func (loc, _(at_directive_argv[3]));
+            complain_at (loc, complaint_flag, "%s", _(at_directive_argv[3]));
             break;
           case 5:
-            func (loc, _(at_directive_argv[3]), at_directive_argv[4]);
+            complain_at (loc, complaint_flag, _(at_directive_argv[3]),
+                      at_directive_argv[4]);
             break;
           case 6:
-            func (loc, _(at_directive_argv[3]), at_directive_argv[4],
-                  at_directive_argv[5]);
+            complain_at (loc, complaint_flag, _(at_directive_argv[3]),
+                      at_directive_argv[4], at_directive_argv[5]);
             break;
           case 7:
-            func (loc, _(at_directive_argv[3]), at_directive_argv[4],
-                  at_directive_argv[5], at_directive_argv[6]);
+            complain_at (loc, complaint_flag, _(at_directive_argv[3]),
+                      at_directive_argv[4], at_directive_argv[5],
+                      at_directive_argv[6]);
             break;
           case 8:
-            func (loc, _(at_directive_argv[3]), at_directive_argv[4],
-                  at_directive_argv[5], at_directive_argv[6],
-                  at_directive_argv[7]);
+            complain_at (loc, complaint_flag, _(at_directive_argv[3]),
+                      at_directive_argv[4], at_directive_argv[5],
+                      at_directive_argv[6], at_directive_argv[7]);
             break;
           default:
             fail_for_at_directive_too_many_args (at_directive_argv[0]);
@@ -286,19 +291,19 @@ at_directive_perform (int at_directive_argc,
 static void
 fail_for_at_directive_too_few_args (char const *at_directive_name)
 {
-  fatal (_("too few arguments for %s directive in skeleton"),
+  complain (fatal, _("too few arguments for %s directive in skeleton"),
          at_directive_name);
 }
 
 static void
 fail_for_at_directive_too_many_args (char const *at_directive_name)
 {
-  fatal (_("too many arguments for %s directive in skeleton"),
-         at_directive_name);
+  complain (fatal, _("too many arguments for %s directive in skeleton"),
+            at_directive_name);
 }
 
 static void
 fail_for_invalid_at (char const *at)
 {
-  fatal ("invalid @ in skeleton: %s", at);
+  complain (fatal, "invalid @ in skeleton: %s", at);
 }
diff --git a/src/symlist.c b/src/symlist.c
index 4882831..1fbc5cb 100644
--- a/src/symlist.c
+++ b/src/symlist.c
@@ -24,7 +24,6 @@
 #include "complain.h"
 #include "symlist.h"
 
-
 /*--------------------------------------.
 | Create a list containing SYM at LOC.  |
 `--------------------------------------*/
@@ -212,7 +211,7 @@ symbol_list_n_type_name_get (symbol_list *l, location loc, 
int n)
   l = symbol_list_n_get (l, n);
   if (!l)
     {
-      complain_at (loc, _("invalid $ value: $%d"), n);
+      complain_at (loc, complaint, _("invalid $ value: $%d"), n);
       return NULL;
     }
   aver (l->content_type == SYMLIST_SYMBOL);
diff --git a/src/symtab.c b/src/symtab.c
index 124da37..998a0e8 100644
--- a/src/symtab.c
+++ b/src/symtab.c
@@ -75,8 +75,8 @@ symbol_new (uniqstr tag, location loc)
   /* If the tag is not a string (starts with a double quote), check
      that it is valid for Yacc. */
   if (tag[0] != '\"' && tag[0] != '\'' && strchr (tag, '-'))
-    yacc_at (loc, _("POSIX Yacc forbids dashes in symbol names: %s"),
-             tag);
+    complain_at (loc, Wyacc,
+                 _("POSIX Yacc forbids dashes in symbol names: %s"), tag);
 
   res->tag = tag;
   res->location = loc;
@@ -95,8 +95,8 @@ symbol_new (uniqstr tag, location loc)
   res->status = undeclared;
 
   if (nsyms == SYMBOL_NUMBER_MAXIMUM)
-    fatal (_("too many symbols in input grammar (limit is %d)"),
-           SYMBOL_NUMBER_MAXIMUM);
+    complain (fatal, _("too many symbols in input grammar (limit is %d)"),
+              SYMBOL_NUMBER_MAXIMUM);
   nsyms++;
   return res;
 }
@@ -207,16 +207,16 @@ static void
 symbol_redeclaration (symbol *s, const char *what, location first,
                       location second)
 {
-  complain_at (second, _("%s redeclaration for %s"), what, s->tag);
-  complain_at (first, _("previous declaration"));
+  complain_at (second, complaint, _("%s redeclaration for %s"), what, s->tag);
+  complain_at (first, complaint, _("previous declaration"));
 }
 
 static void
 semantic_type_redeclaration (semantic_type *s, const char *what, location 
first,
                              location second)
 {
-  complain_at (second, _("%s redeclaration for <%s>"), what, s->tag);
-  complain_at (first, _("previous declaration"));
+  complain_at (second, complaint, _("%s redeclaration for <%s>"), what, 
s->tag);
+  complain_at (first, complaint, _("previous declaration"));
 }
 
 
@@ -333,7 +333,7 @@ symbol_class_set (symbol *sym, symbol_class class, location 
loc, bool declaring)
   bool warned = false;
   if (sym->class != unknown_sym && sym->class != class)
     {
-      complain_at (loc, _("symbol %s redefined"), sym->tag);
+      complain_at (loc, complaint, _("symbol %s redefined"), sym->tag);
       // Don't report both "redefined" and "redeclared".
       warned = true;
     }
@@ -348,7 +348,7 @@ symbol_class_set (symbol *sym, symbol_class class, location 
loc, bool declaring)
   if (declaring)
     {
       if (sym->status == declared && !warned)
-        warn_at (loc, _("symbol %s redeclared"), sym->tag);
+        complain_at (loc, Wother, _("symbol %s redeclared"), sym->tag);
       sym->status = declared;
     }
 }
@@ -369,7 +369,8 @@ symbol_user_token_number_set (symbol *sym, int 
user_token_number, location loc)
     user_token_numberp = &sym->alias->user_token_number;
   if (*user_token_numberp != USER_NUMBER_UNDEFINED
       && *user_token_numberp != user_token_number)
-    complain_at (loc, _("redefining user token number of %s"), sym->tag);
+    complain_at (loc, complaint, _("redefining user token number of %s"),
+                 sym->tag);
 
   *user_token_numberp = user_token_number;
   /* User defined $end token? */
@@ -398,17 +399,17 @@ symbol_check_defined (symbol *sym)
       switch (sym->status)
         {
         case used:
-          warn_at (sym->location,
+          complain_at (sym->location, Wother,
                    _("symbol %s is used, but is not defined as a token"
                      " and has no rules"),
                    sym->tag);
           break;
         case undeclared:
         case needed:
-          complain_at (sym->location,
-                       _("symbol %s is used, but is not defined as a token"
-                         " and has no rules"),
-                       sym->tag);
+          complain_at (sym->location, complaint,
+                    _("symbol %s is used, but is not defined as a token"
+                      " and has no rules"),
+                    sym->tag);
           break;
         case declared:
           /* If declared, then sym->class != unknown_sym. */
@@ -448,14 +449,14 @@ semantic_type_check_defined (semantic_type *sem_type)
       for (int i = 0; i < 2; ++i)
         if (sem_type->props[i].kind != CODE_PROPS_NONE
             && ! sem_type->props[i].is_used)
-          warn_at (sem_type->location,
+          complain_at (sem_type->location, Wother,
                    _("useless %s for type <%s>"),
                    code_props_type_string (i), sem_type->tag);
     }
   else
-    warn_at (sem_type->location,
-             _("type <%s> is used, but is not associated to any symbol"),
-             sem_type->tag);
+    complain_at (sem_type->location, Wother,
+                 _("type <%s> is used, but is not associated to any symbol"),
+                 sem_type->tag);
 
   return true;
 }
@@ -478,11 +479,11 @@ void
 symbol_make_alias (symbol *sym, symbol *str, location loc)
 {
   if (str->alias)
-    warn_at (loc, _("symbol %s used more than once as a literal string"),
-             str->tag);
+    complain_at (loc, Wother,
+              _("symbol %s used more than once as a literal string"), 
str->tag);
   else if (sym->alias)
-    warn_at (loc, _("symbol %s given more than one literal string"),
-             sym->tag);
+    complain_at (loc, Wother,
+              _("symbol %s given more than one literal string"), sym->tag);
   else
     {
       str->class = token_sym;
@@ -586,10 +587,10 @@ user_token_number_redeclaration (int num, symbol *first, 
symbol *second)
       first = second;
       second = tmp;
     }
-  complain_at (second->location,
-               _("user token number %d redeclaration for %s"),
-               num, second->tag);
-  complain_at (first->location, _("previous declaration for %s"),
+  complain_at (second->location, complaint,
+            _("user token number %d redeclaration for %s"),
+            num, second->tag);
+  complain_at (first->location, complaint, _("previous declaration for %s"),
                first->tag);
 }
 
@@ -968,13 +969,13 @@ symbols_pack (void)
   symbols_token_translations_init ();
 
   if (startsymbol->class == unknown_sym)
-    fatal_at (startsymbol_location,
-              _("the start symbol %s is undefined"),
-              startsymbol->tag);
+    complain_at (startsymbol_location, fatal,
+                 _("the start symbol %s is undefined"),
+                 startsymbol->tag);
   else if (startsymbol->class == token_sym)
-    fatal_at (startsymbol_location,
-              _("the start symbol %s is a token"),
-              startsymbol->tag);
+    complain_at (startsymbol_location, fatal,
+                 _("the start symbol %s is a token"),
+                 startsymbol->tag);
 }
 
 
@@ -987,10 +988,10 @@ default_tagged_code_props_set (code_props_type kind, 
code_props const *code)
 {
   if (default_tagged_code_props[kind].code)
     {
-      complain_at (code->location,
+      complain_at (code->location, complaint,
                    _("redeclaration for default tagged %s"),
                    code_props_type_string (kind));
-      complain_at (default_tagged_code_props[kind].location,
+      complain_at (default_tagged_code_props[kind].location, complaint,
                    _("previous declaration"));
     }
   default_tagged_code_props[kind] = *code;
@@ -1001,11 +1002,11 @@ default_tagless_code_props_set (code_props_type kind, 
code_props const *code)
 {
   if (default_tagless_code_props[kind].code)
     {
-      complain_at (code->location,
-                   _("redeclaration for default tagless %s"),
-                   code_props_type_string (kind));
-      complain_at (default_tagless_code_props[kind].location,
-                   _("previous declaration"));
+      complain_at (code->location, complaint,
+                _("redeclaration for default tagless %s"),
+                code_props_type_string (kind));
+      complain_at (default_tagless_code_props[kind].location, complaint,
+                _("previous declaration"));
     }
   default_tagless_code_props[kind] = *code;
 }
-- 
1.7.9.5




reply via email to

[Prev in Thread] Current Thread [Next in Thread]