m4-commit
[Top][All Lists]
Advanced

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

[SCM] GNU M4 source repository branch, branch-1_4, updated. branch-cvs-r


From: Eric Blake
Subject: [SCM] GNU M4 source repository branch, branch-1_4, updated. branch-cvs-readonly-20-g9de0b89
Date: Fri, 23 Nov 2007 03:43:25 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU M4 source repository".

http://git.sv.gnu.org/gitweb/?p=m4.git;a=commitdiff;h=9de0b8950ca83762363605805c40f8f8614acbc8

The branch, branch-1_4 has been updated
       via  9de0b8950ca83762363605805c40f8f8614acbc8 (commit)
       via  910837ec453663d0423f73eb79c17740486450a0 (commit)
      from  031a71a80442ed2ad3c2ee14d5811c786a12c51b (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 9de0b8950ca83762363605805c40f8f8614acbc8
Author: Eric Blake <address@hidden>
Date:   Thu Nov 22 19:54:32 2007 -0700

    More error messages tied to macro names.
    
    * src/input.c (set_word_regexp): Take additional parameter.
    (input_init): Adjust caller.
    * src/debug.c (debug_set_file, debug_set_output): Take additional
    parameter.
    (debug_init): Adjust caller.
    (expansion_level): Move declaration...
    * src/m4.h (expansion_level): ...here.
    (debug_set_output, set_word_regexp): Adjust prototypes.
    * src/builtin.c (m4_changeword, m4_m4exit, m4_debugfile): Adjust
    callers.
    * src/m4.c (main): Likewise.
    
    Signed-off-by: Eric Blake <address@hidden>

commit 910837ec453663d0423f73eb79c17740486450a0
Author: Eric Blake <address@hidden>
Date:   Thu Nov 22 14:13:49 2007 -0700

    Refactor error messages to avoid macros.
    
    * src/m4.h (_): Define, as a placeholder for now.
    (M4ERROR, M4ERROR_AT_LINE): Delete.
    (m4_error, m4_error_at_line): Change prototype.
    (m4_warn, m4_warn_at_line): New prototypes.
    * src/m4.c (m4_verror_at_line): New helper function.
    (m4_error, m4_error_at_line): Use new function, and properly call
    va_end.
    (m4_warn, m4_warn_at_line): New functions.
    (stackovf_handler, main): All callers changed.
    * src/builtin.c: Likewise.
    * src/debug.c: Likewise.
    * src/eval.c: Likewise.
    * src/format.c: Likewise.
    * src/freeze.c: Likewise.
    * src/input.c: Likewise.
    * src/macro.c: Likewise.
    * doc/m4.texinfo (Indir, Builtin, Dumpdef, Incr, Eval, Substr)
    (Improved forloop): Adjust tests accordingly.
    
    Signed-off-by: Eric Blake <address@hidden>

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog      |   33 ++++++++++++
 doc/m4.texinfo |   40 ++++++++--------
 src/builtin.c  |  150 +++++++++++++++++++++-----------------------------------
 src/debug.c    |   41 ++++++---------
 src/eval.c     |   30 ++++--------
 src/format.c   |    6 +--
 src/freeze.c   |   35 +++++++------
 src/input.c    |   30 +++++-------
 src/m4.c       |  136 ++++++++++++++++++++++++++++++++++++++++----------
 src/m4.h       |   22 +++++---
 src/macro.c    |   13 ++---
 src/output.c   |   54 ++++++++++----------
 src/path.c     |    6 +--
 13 files changed, 327 insertions(+), 269 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 4d8ec23..9bbf726 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,38 @@
 2007-11-22  Eric Blake  <address@hidden>
 
+       More error messages tied to macro names.
+       * src/input.c (set_word_regexp): Take additional parameter.
+       (input_init): Adjust caller.
+       * src/debug.c (debug_set_file, debug_set_output): Take additional
+       parameter.
+       (debug_init): Adjust caller.
+       (expansion_level): Move declaration...
+       * src/m4.h (expansion_level): ...here.
+       (debug_set_output, set_word_regexp): Adjust prototypes.
+       * src/builtin.c (m4_changeword, m4_m4exit, m4_debugfile): Adjust
+       callers.
+       * src/m4.c (main): Likewise.
+
+       Refactor error messages to avoid macros.
+       * src/m4.h (_): Define, as a placeholder for now.
+       (M4ERROR, M4ERROR_AT_LINE): Delete.
+       (m4_error, m4_error_at_line): Change prototype.
+       (m4_warn, m4_warn_at_line): New prototypes.
+       * src/m4.c (m4_verror_at_line): New helper function.
+       (m4_error, m4_error_at_line): Use new function, and properly call
+       va_end.
+       (m4_warn, m4_warn_at_line): New functions.
+       (stackovf_handler, main): All callers changed.
+       * src/builtin.c: Likewise.
+       * src/debug.c: Likewise.
+       * src/eval.c: Likewise.
+       * src/format.c: Likewise.
+       * src/freeze.c: Likewise.
+       * src/input.c: Likewise.
+       * src/macro.c: Likewise.
+       * doc/m4.texinfo (Indir, Builtin, Dumpdef, Incr, Eval, Substr)
+       (Improved forloop): Adjust tests accordingly.
+
        Security fix: avoid arbitrary code execution with 'm4 -F'.
        * src/freeze.c (produce_frozen_state): Never pass raw file name as
        printf format.
diff --git a/doc/m4.texinfo b/doc/m4.texinfo
index 6ae09f7..3cc3539 100644
--- a/doc/m4.texinfo
+++ b/doc/m4.texinfo
@@ -2367,7 +2367,7 @@ f(define(`f', `2'))
 indir(`f', define(`f', `3'))
 @result{}3
 indir(`f', undefine(`f'))
address@hidden:stdin:4: indir: undefined macro `f'
address@hidden:stdin:4: Warning: indir: undefined macro `f'
 @result{}
 @end example
 
@@ -2389,7 +2389,7 @@ indir(`define', `foo', defn(`divnum'))
 foo
 @result{}0
 indir(`divert', defn(`foo'))
address@hidden:stdin:5: divert: empty string treated as 0
address@hidden:stdin:5: Warning: divert: empty string treated as 0
 @result{}
 @end example
 
@@ -2452,10 +2452,10 @@ $ @kbd{m4 -P}
 m4_builtin(`divnum')
 @result{}0
 m4_builtin(`m4_divnum')
address@hidden:stdin:2: m4_builtin: undefined builtin `m4_divnum'
address@hidden:stdin:2: Warning: m4_builtin: undefined builtin `m4_divnum'
 @result{}
 m4_indir(`divnum')
address@hidden:stdin:3: m4_indir: undefined macro `divnum'
address@hidden:stdin:3: Warning: m4_indir: undefined macro `divnum'
 @result{}
 m4_indir(`m4_divnum')
 @result{}0
@@ -2469,13 +2469,13 @@ recognized; but it will provoke a warning, and result 
in a void expansion.
 builtin
 @result{}builtin
 builtin()
address@hidden:stdin:2: builtin: undefined builtin `'
address@hidden:stdin:2: Warning: builtin: undefined builtin `'
 @result{}
 builtin(`builtin')
 @error{}m4:stdin:3: Warning: builtin: too few arguments: 0 < 1
 @result{}
 builtin(`builtin',)
address@hidden:stdin:4: builtin: undefined builtin `'
address@hidden:stdin:4: Warning: builtin: undefined builtin `'
 @result{}
 @end example
 
@@ -3133,7 +3133,7 @@ f(popdef(`f')dumpdef(`f'))
 @error{}f:@tabchar{}``$0'1'
 @result{}f2
 f(popdef(`f')dumpdef(`f'))
address@hidden:stdin:3: dumpdef: undefined macro `f'
address@hidden:stdin:3: Warning: dumpdef: undefined macro `f'
 @result{}f1
 @end example
 
@@ -3231,7 +3231,7 @@ undefine(`foo')
 ifdef(`foo', `yes', `no')
 @result{}no
 indir(`foo')
address@hidden:stdin:8: indir: undefined macro `foo'
address@hidden:stdin:8: Warning: indir: undefined macro `foo'
 @result{}
 define(`foo', `blah')
 @result{}
@@ -4920,7 +4920,7 @@ substr(`abc')
 @error{}m4:stdin:1: Warning: substr: too few arguments: 1 < 2
 @result{}abc
 substr(`abc',)
address@hidden:stdin:2: substr: empty string treated as 0
address@hidden:stdin:2: Warning: substr: empty string treated as 0
 @result{}abc
 @end example
 
@@ -5266,10 +5266,10 @@ incr(`4')
 decr(`7')
 @result{}6
 incr()
address@hidden:stdin:3: incr: empty string treated as 0
address@hidden:stdin:3: Warning: incr: empty string treated as 0
 @result{}1
 decr()
address@hidden:stdin:4: decr: empty string treated as 0
address@hidden:stdin:4: Warning: decr: empty string treated as 0
 @result{}-1
 @end example
 
@@ -5388,12 +5388,12 @@ eval(`+ + - ~ ! ~ 0')
 eval(`2 || 1 / 0')
 @result{}1
 eval(`0 || 1 / 0')
address@hidden:stdin:9: eval: divide by zero: 0 || 1 / 0
address@hidden:stdin:9: Warning: eval: divide by zero: 0 || 1 / 0
 @result{}
 eval(`0 && 1 % 0')
 @result{}0
 eval(`2 && 1 % 0')
address@hidden:stdin:11: eval: modulo by zero: 2 && 1 % 0
address@hidden:stdin:11: Warning: eval: modulo by zero: 2 && 1 % 0
 @result{}
 @end example
 
@@ -5414,9 +5414,9 @@ eval(`2 ** 0')
 @result{}1
 eval(`0 ** 0')
 @result{}
address@hidden:stdin:5: eval: divide by zero: 0 ** 0
address@hidden:stdin:5: Warning: eval: divide by zero: 0 ** 0
 eval(`4 ** -2')
address@hidden:stdin:6: eval: negative exponent: 4 ** -2
address@hidden:stdin:6: Warning: eval: negative exponent: 4 ** -2
 @result{}
 @end example
 
@@ -5461,7 +5461,7 @@ square(square(`5')` + 1')
 define(`foo', `666')
 @result{}
 eval(`foo / 6')
address@hidden:stdin:11: eval: bad expression: foo / 6
address@hidden:stdin:11: Warning: eval: bad expression: foo / 6
 @result{}
 eval(foo / 6)
 @result{}111
@@ -5529,13 +5529,13 @@ eval(`10', `', `0')
 eval(`10', `16')
 @result{}a
 eval(`1', `37')
address@hidden:stdin:9: eval: radix 37 out of range
address@hidden:stdin:9: Warning: eval: radix 37 out of range
 @result{}
 eval(`1', , `-1')
address@hidden:stdin:10: eval: negative width
address@hidden:stdin:10: Warning: eval: negative width
 @result{}
 eval()
address@hidden:stdin:11: eval: empty string treated as 0
address@hidden:stdin:11: Warning: eval: empty string treated as 0
 @result{}0
 @end example
 
@@ -6769,7 +6769,7 @@ forloop(`', `1', `2', ` odd iterator name')
 forloop(`i', `5 + 5', `0xc', ` 0x`'eval(i, `16')')
 @result{} 0xa 0xb 0xc
 forloop(`i', `a', `b', `non-numeric bounds')
address@hidden:stdin:6: eval: bad expression (bad input): (b) >= (a)
address@hidden:stdin:6: Warning: eval: bad expression (bad input): (b) >= (a)
 @result{}
 @end example
 
diff --git a/src/builtin.c b/src/builtin.c
index 48df3d6..cc4e469 100644
--- a/src/builtin.c
+++ b/src/builtin.c
@@ -24,8 +24,6 @@
 
 #include "m4.h"
 
-extern FILE *popen ();
-
 #include "regex.h"
 
 #if HAVE_SYS_WAIT_H
@@ -374,11 +372,9 @@ set_macro_sequence (const char *regexp)
 
   msg = re_compile_pattern (regexp, strlen (regexp), &macro_sequence_buf);
   if (msg != NULL)
-    {
-      M4ERROR ((EXIT_FAILURE, 0,
-               "--warn-macro-sequence: bad regular expression `%s': %s",
-               regexp, msg));
-    }
+    m4_error (EXIT_FAILURE, 0, NULL,
+             _("--warn-macro-sequence: bad regular expression `%s': %s"),
+             regexp, msg);
   re_set_registers (&macro_sequence_buf, &macro_sequence_regs,
                    macro_sequence_regs.num_regs,
                    macro_sequence_regs.start, macro_sequence_regs.end);
@@ -439,16 +435,15 @@ define_user_macro (const char *name, const char *text, 
symbol_lookup mode)
              offset = macro_sequence_regs.end[0];
              tmp = defn[offset];
              defn[offset] = '\0';
-             M4ERROR ((warning_status, 0,
-                       "Warning: definition of `%s' contains sequence `%s'",
-                       name, defn + macro_sequence_regs.start[0]));
+             m4_warn (0, NULL, _("definition of `%s' contains sequence `%s'"),
+                      name, defn + macro_sequence_regs.start[0]);
              defn[offset] = tmp;
            }
        }
       if (offset == -2)
-       M4ERROR ((warning_status, 0,
-                 "error checking --warn-macro-sequence for macro `%s'",
-                 name));
+       m4_warn (0, NULL,
+                _("problem checking --warn-macro-sequence for macro `%s'"),
+                name);
     }
 }
 
@@ -505,16 +500,11 @@ bad_argc (const char *name, int argc, unsigned int min, 
unsigned int max)
 {
   if (argc - 1 < min)
     {
-      if (!suppress_warnings)
-       M4ERROR ((warning_status, 0,
-                 "Warning: %s: too few arguments: %d < %d",
-                 name, argc - 1, min));
+      m4_warn (0, name, _("too few arguments: %d < %d"), argc - 1, min);
       return true;
     }
-  if (argc - 1 > max && !suppress_warnings)
-    M4ERROR ((warning_status, 0,
-             "Warning: %s: extra arguments ignored: %d > %d",
-             name, argc - 1, max));
+  if (argc - 1 > max)
+    m4_warn (0, name, _("extra arguments ignored: %d > %d"), argc - 1, max);
   return false;
 }
 
@@ -532,7 +522,7 @@ numeric_arg (const char *name, const char *arg, int *valuep)
   if (*arg == '\0')
     {
       *valuep = 0;
-      M4ERROR ((warning_status, 0, "%s: empty string treated as 0", name));
+      m4_warn (0, name, _("empty string treated as 0"));
     }
   else
     {
@@ -540,16 +530,13 @@ numeric_arg (const char *name, const char *arg, int 
*valuep)
       *valuep = strtol (arg, &endp, 10);
       if (*endp != '\0')
        {
-         M4ERROR ((warning_status, 0,
-                   "%s: non-numeric argument `%s'", name, arg));
+         m4_warn (0, name, _("non-numeric argument `%s'"), arg);
          return false;
        }
       if (isspace (to_uchar (*arg)))
-       M4ERROR ((warning_status, 0,
-                 "%s: leading whitespace ignored", name));
+       m4_warn (0, name, _("leading whitespace ignored"));
       else if (errno == ERANGE)
-       M4ERROR ((warning_status, 0,
-                 "%s: numeric overflow detected", name));
+       m4_warn (0, name, _("numeric overflow detected"));
     }
   return true;
 }
@@ -664,8 +651,7 @@ define_macro (int argc, token_data **argv, symbol_lookup 
mode)
 
   if (TOKEN_DATA_TYPE (argv[1]) != TOKEN_TEXT)
     {
-      M4ERROR ((warning_status, 0,
-               "Warning: %s: invalid macro name ignored", me));
+      m4_warn (0, me, _("invalid macro name ignored"));
       return;
     }
 
@@ -864,8 +850,7 @@ m4_dumpdef (struct obstack *obs, int argc, token_data 
**argv)
          if (s != NULL && SYMBOL_TYPE (s) != TOKEN_VOID)
            dump_symbol (s, &data);
          else
-           M4ERROR ((warning_status, 0,
-                     "%s: undefined macro `%s'", me, ARG (i)));
+           m4_warn (0, me, _("undefined macro `%s'"), ARG (i));
        }
     }
 
@@ -925,16 +910,14 @@ m4_builtin (struct obstack *obs, int argc, token_data 
**argv)
     return;
   if (TOKEN_DATA_TYPE (argv[1]) != TOKEN_TEXT)
     {
-      M4ERROR ((warning_status, 0,
-               "Warning: %s: invalid macro name ignored", me));
+      m4_warn (0, me, _("invalid macro name ignored"));
       return;
     }
 
   name = ARG (1);
   bp = find_builtin_by_name (name);
   if (bp->func == m4_placeholder)
-    M4ERROR ((warning_status, 0,
-             "%s: undefined builtin `%s'", me, name));
+    m4_warn (0, me, _("undefined builtin `%s'"), name);
   else
     {
       int i;
@@ -967,16 +950,14 @@ m4_indir (struct obstack *obs, int argc, token_data 
**argv)
     return;
   if (TOKEN_DATA_TYPE (argv[1]) != TOKEN_TEXT)
     {
-      M4ERROR ((warning_status, 0,
-               "Warning: %s: invalid macro name ignored", me));
+      m4_warn (0, me, _("invalid macro name ignored"));
       return;
     }
 
   name = ARG (1);
   s = lookup_symbol (name, SYMBOL_LOOKUP);
   if (s == NULL || SYMBOL_TYPE (s) == TOKEN_VOID)
-    M4ERROR ((warning_status, 0,
-             "%s: undefined macro `%s'", me, name));
+    m4_warn (0, me, _("undefined macro `%s'"), name);
   else
     {
       int i;
@@ -1025,12 +1006,11 @@ m4_defn (struct obstack *obs, int argc, token_data 
**argv)
        case TOKEN_FUNC:
          b = SYMBOL_FUNC (s);
          if (b == m4_placeholder)
-           M4ERROR ((warning_status, 0, "\
-Warning: %s: builtin `%s' requested by frozen file not found", me, ARG (i)));
+           m4_warn (0, me,
+                    _("builtin `%s' requested by frozen file not found"),
+                    ARG (i));
          else if (argc != 2)
-           M4ERROR ((warning_status, 0,
-                     "Warning: %s: cannot concatenate builtin `%s'",
-                     me, ARG (i)));
+           m4_warn (0, me, _("cannot concatenate builtin `%s'"), ARG (i));
          else
            push_macro (b);
          break;
@@ -1122,8 +1102,7 @@ m4_esyscmd (struct obstack *obs, int argc, token_data 
**argv)
   pin = popen (ARG (1), "r");
   if (pin == NULL)
     {
-      M4ERROR ((warning_status, errno,
-               "%s: cannot open pipe to command `%s'", me, ARG (1)));
+      m4_warn (errno, me, _("cannot open pipe to command `%s'"), ARG (1));
       sysval = -1;
     }
   else
@@ -1164,8 +1143,7 @@ m4_eval (struct obstack *obs, int argc, token_data **argv)
 
   if (radix < 1 || radix > (int) strlen (digits))
     {
-      M4ERROR ((warning_status, 0,
-               "%s: radix %d out of range", me, radix));
+      m4_warn (0, me, _("radix %d out of range"), radix);
       return;
     }
 
@@ -1173,13 +1151,12 @@ m4_eval (struct obstack *obs, int argc, token_data 
**argv)
     return;
   if (min < 0)
     {
-      M4ERROR ((warning_status, 0, "%s: negative width", me));
+      m4_warn (0, me, _("negative width"));
       return;
     }
 
   if (!*ARG (1))
-    M4ERROR ((warning_status, 0,
-             "%s: empty string treated as 0", me));
+    m4_warn (0, me, _("empty string treated as 0"));
   else if (evaluate (me, ARG (1), &value))
     return;
 
@@ -1300,8 +1277,7 @@ m4_undivert (struct obstack *obs, int argc, token_data 
**argv)
        if (*endp == '\0' && !isspace (to_uchar (*str)))
          insert_diversion (file);
        else if (no_gnu_extensions)
-         M4ERROR ((warning_status, 0,
-                   "%s: non-numeric argument `%s'", me, str));
+         m4_warn (0, me, _("non-numeric argument `%s'"), str);
        else
          {
            fp = m4_path_search (str, NULL);
@@ -1309,12 +1285,10 @@ m4_undivert (struct obstack *obs, int argc, token_data 
**argv)
              {
                insert_file (fp);
                if (fclose (fp) == EOF)
-                 M4ERROR ((warning_status, errno,
-                           "%s: error undiverting `%s'", me, str));
+                 m4_warn (errno, me, _("error undiverting `%s'"), str);
              }
            else
-             M4ERROR ((warning_status, errno,
-                       "%s: cannot undivert `%s'", me, str));
+             m4_warn (errno, me, _("cannot undivert `%s'"), str);
          }
       }
 }
@@ -1389,10 +1363,11 @@ m4_changecom (struct obstack *obs, int argc, token_data 
**argv)
 static void
 m4_changeword (struct obstack *obs, int argc, token_data **argv)
 {
-  if (bad_argc (ARG (0), argc, 1, 1))
-    return;
+  const char *me = ARG (0);
 
-  set_word_regexp (ARG (1));
+  if (bad_argc (me, argc, 1, 1))
+    return;
+  set_word_regexp (me, ARG (1));
 }
 
 #endif /* ENABLE_CHANGEWORD */
@@ -1420,11 +1395,7 @@ include (int argc, token_data **argv, bool silent)
   if (fp == NULL)
     {
       if (!silent)
-       {
-         M4ERROR ((warning_status, errno, "%s: cannot open `%s'",
-                   me, ARG (1)));
-         retcode = EXIT_FAILURE;
-       }
+       m4_error (0, errno, me, _("cannot open `%s'"), ARG (1));
       return;
     }
 
@@ -1483,7 +1454,7 @@ mkstemp_helper (struct obstack *obs, const char *me, 
const char *name)
   fd = mkstemp ((char *) obstack_base (obs));
   if (fd < 0)
     {
-      M4ERROR ((0, errno, "%s: cannot create tempfile `%s'", me, name));
+      m4_warn (errno, me, _("cannot create tempfile `%s'"), name);
       obstack_free (obs, obstack_finish (obs));
     }
   else
@@ -1515,7 +1486,7 @@ m4_maketemp (struct obstack *obs, int argc, token_data 
**argv)
       int i;
       int len2;
 
-      M4ERROR ((warning_status, 0, "%s: recommend using mkstemp instead", me));
+      m4_warn (0, me, _("recommend using mkstemp instead"));
       for (i = len; i > 1; i--)
        if (str[i - 1] != 'X')
          break;
@@ -1607,13 +1578,12 @@ m4_m4exit (struct obstack *obs, int argc, token_data 
**argv)
     exit_code = EXIT_FAILURE;
   if (exit_code < 0 || exit_code > 255)
     {
-      M4ERROR ((warning_status, 0,
-               "%s: exit status out of range: `%d'", me, exit_code));
+      m4_warn (0, me, _("exit status out of range: %d"), exit_code);
       exit_code = EXIT_FAILURE;
     }
   /* Change debug stream back to stderr, to force flushing debug stream and
      detect any errors it might have encountered.  */
-  debug_set_output (NULL);
+  debug_set_output (me, NULL);
   debug_flush_files ();
   if (exit_code == EXIT_SUCCESS && retcode != EXIT_SUCCESS)
     exit_code = retcode;
@@ -1730,8 +1700,7 @@ m4_debugmode (struct obstack *obs, int argc, token_data 
**argv)
        }
 
       if (new_debug_level < 0)
-       M4ERROR ((warning_status, 0,
-                 "%s: bad debug flags: `%s'", me, str));
+       m4_warn (0, me, _("bad debug flags: `%s'"), str);
       else
        {
          switch (change_flag)
@@ -1765,10 +1734,9 @@ m4_debugfile (struct obstack *obs, int argc, token_data 
**argv)
   bad_argc (me, argc, 0, 1);
 
   if (argc == 1)
-    debug_set_output (NULL);
-  else if (!debug_set_output (ARG (1)))
-    M4ERROR ((warning_status, errno,
-             "%s: cannot set error file: `%s'", me, ARG (1)));
+    debug_set_output (me, NULL);
+  else if (!debug_set_output (me, ARG (1)))
+    m4_warn (errno, me, _("cannot set error file: `%s'"), ARG (1));
 }
 
 /* This section contains text processing macros: "len", "index",
@@ -2020,8 +1988,8 @@ substitute (struct obstack *obs, const char *me, const 
char *victim,
        case '0':
          if (!substitute_warned)
            {
-             M4ERROR ((warning_status, 0, "\
-Warning: %s: \\0 will disappear, use \\& instead in replacements", me));
+             m4_warn (0, me, _("\
+\\0 will disappear, use \\& instead in replacements"));
              substitute_warned = 1;
            }
          /* Fall through.  */
@@ -2036,16 +2004,14 @@ Warning: %s: \\0 will disappear, use \\& instead in 
replacements", me));
        case '7': case '8': case '9':
          ch -= '0';
          if (!regs || regs->num_regs - 1 <= ch)
-           M4ERROR ((warning_status, 0,
-                     "Warning: %s: sub-expression %d not present", me, ch));
+           m4_warn (0, me, _("sub-expression %d not present"), ch);
          else if (regs->end[ch] > 0)
            obstack_grow (obs, victim + regs->start[ch],
                          regs->end[ch] - regs->start[ch]);
          break;
 
        case '\0':
-         M4ERROR ((warning_status, 0,
-                   "Warning: %s: trailing \\ ignored in replacement", me));
+         m4_warn (0, me, _("trailing \\ ignored in replacement"));
          return;
 
        default:
@@ -2125,8 +2091,7 @@ m4_regexp (struct obstack *obs, int argc, token_data 
**argv)
   msg = compile_pattern (regexp, strlen (regexp), &buf, &regs);
   if (msg != NULL)
     {
-      M4ERROR ((warning_status, 0,
-               "%s: bad regular expression: `%s': %s", me, regexp, msg));
+      m4_warn (0, me, _("bad regular expression: `%s': %s"), regexp, msg);
       return;
     }
 
@@ -2136,8 +2101,7 @@ m4_regexp (struct obstack *obs, int argc, token_data 
**argv)
                        argc == 3 ? NULL : regs);
 
   if (startpos == -2)
-    M4ERROR ((warning_status, 0,
-             "%s: error matching regular expression `%s'", me, regexp));
+    m4_warn (0, me, _("problem matching regular expression `%s'"), regexp);
   else if (argc == 3)
     shipout_int (obs, startpos);
   else if (startpos >= 0)
@@ -2195,8 +2159,7 @@ m4_patsubst (struct obstack *obs, int argc, token_data 
**argv)
   msg = compile_pattern (regexp, strlen (regexp), &buf, &regs);
   if (msg != NULL)
     {
-      M4ERROR ((warning_status, 0,
-               "%s: bad regular expression `%s': %s", me, regexp, msg));
+      m4_warn (0, me, _("bad regular expression `%s': %s"), regexp, msg);
       return;
     }
 
@@ -2216,9 +2179,8 @@ m4_patsubst (struct obstack *obs, int argc, token_data 
**argv)
             copied verbatim.  */
 
          if (matchpos == -2)
-           M4ERROR ((warning_status, 0,
-                     "%s: error matching regular expression `%s'",
-                     me, regexp));
+           m4_warn (0, me, _("problem matching regular expression `%s'"),
+                    regexp);
          else if (offset < length)
            obstack_grow (obs, victim + offset, length - offset);
          break;
@@ -2262,8 +2224,8 @@ m4_patsubst (struct obstack *obs, int argc, token_data 
**argv)
 void
 m4_placeholder (struct obstack *obs, int argc, token_data **argv)
 {
-  M4ERROR ((warning_status, 0, "\
-builtin `%s' requested by frozen file not found", ARG (0)));
+  m4_warn (0, NULL, _("builtin `%s' requested by frozen file not found"),
+          ARG (0));
 }
 
 /*-------------------------------------------------------------------------.
diff --git a/src/debug.c b/src/debug.c
index 998ccb9..c22a482 100644
--- a/src/debug.c
+++ b/src/debug.c
@@ -30,9 +30,7 @@ FILE *debug = NULL;
 /* Obstack for trace messages.  */
 static struct obstack trace;
 
-extern int expansion_level;
-
-static void debug_set_file (FILE *);
+static void debug_set_file (const char *, FILE *);
 
 /*----------------------------------.
 | Initialise the debugging module.  |
@@ -41,7 +39,7 @@ static void debug_set_file (FILE *);
 void
 debug_init (void)
 {
-  debug_set_file (stderr);
+  debug_set_file (NULL, stderr);
   obstack_init (&trace);
 }
 
@@ -128,16 +126,13 @@ debug_decode (const char *opts)
 `------------------------------------------------------------------------*/
 
 static void
-debug_set_file (FILE *fp)
+debug_set_file (const char *caller, FILE *fp)
 {
   struct stat stdout_stat, debug_stat;
 
   if (debug != NULL && debug != stderr && debug != stdout
       && close_stream (debug) != 0)
-    {
-      M4ERROR ((warning_status, errno, "error writing to debug stream"));
-      retcode = EXIT_FAILURE;
-    }
+    m4_error (0, errno, caller, _("error writing to debug stream"));
   debug = fp;
 
   if (debug != NULL && debug != stdout)
@@ -154,11 +149,7 @@ debug_set_file (FILE *fp)
          && stdout_stat.st_ino != 0)
        {
          if (debug != stderr && close_stream (debug) != 0)
-           {
-             M4ERROR ((warning_status, errno,
-                       "error writing to debug stream"));
-             retcode = EXIT_FAILURE;
-           }
+           m4_error (0, errno, caller, _("error writing to debug stream"));
          debug = stdout;
        }
     }
@@ -195,21 +186,22 @@ debug_flush_files (void)
     }
 }
 
-/*-------------------------------------------------------------------------.
-| Change the debug output to file NAME.  If NAME is NULL, debug output is  |
-| reverted to stderr, and if empty debug output is discarded.  Return true |
-| iff the output stream was changed.                                      |
-`-------------------------------------------------------------------------*/
+/*-------------------------------------------------------------------.
+| Change the debug output to file NAME.  If NAME is NULL, debug             |
+| output is reverted to stderr, and if empty, debug output is       |
+| discarded.  Return true iff the output stream was changed.  Report |
+| errors on behalf of CALLER.                                       |
+`-------------------------------------------------------------------*/
 
 bool
-debug_set_output (const char *name)
+debug_set_output (const char *caller, const char *name)
 {
   FILE *fp;
 
   if (name == NULL)
-    debug_set_file (stderr);
+    debug_set_file (caller, stderr);
   else if (*name == '\0')
-    debug_set_file (NULL);
+    debug_set_file (caller, NULL);
   else
     {
       fp = fopen (name, "a");
@@ -217,9 +209,8 @@ debug_set_output (const char *name)
        return false;
 
       if (set_cloexec_flag (fileno (fp), true) != 0)
-       M4ERROR ((warning_status, errno,
-                 "Warning: cannot protect debug file across forks"));
-      debug_set_file (fp);
+       m4_warn (errno, caller, _("cannot protect debug file across forks"));
+      debug_set_file (caller, fp);
     }
   return true;
 }
diff --git a/src/eval.c b/src/eval.c
index 1af596e..fdb50b7 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -310,45 +310,36 @@ evaluate (const char *me, const char *expr, int32_t *val)
       break;
 
     case MISSING_RIGHT:
-      M4ERROR ((warning_status, 0,
-               "%s: bad expression (missing right parenthesis): %s",
-               me, expr));
+      m4_warn (0, me, _("bad expression (missing right parenthesis): %s"),
+              expr);
       break;
 
     case SYNTAX_ERROR:
-      M4ERROR ((warning_status, 0,
-               "%s: bad expression: %s", me, expr));
+      m4_warn (0, me, _("bad expression: %s"), expr);
       break;
 
     case UNKNOWN_INPUT:
-      M4ERROR ((warning_status, 0,
-               "%s: bad expression (bad input): %s", me, expr));
+      m4_warn (0, me, _("bad expression (bad input): %s"), expr);
       break;
 
     case EXCESS_INPUT:
-      M4ERROR ((warning_status, 0,
-               "%s: bad expression (excess input): %s", me, expr));
+      m4_warn (0, me, _("bad expression (excess input): %s"), expr);
       break;
 
     case INVALID_OPERATOR:
-      M4ERROR ((warning_status, 0,
-               "%s: invalid operator: %s", me, expr));
-      retcode = EXIT_FAILURE;
+      m4_error (0, 0, me, _("invalid operator: %s"), expr);
       break;
 
     case DIVIDE_ZERO:
-      M4ERROR ((warning_status, 0,
-               "%s: divide by zero: %s", me, expr));
+      m4_warn (0, me, _("divide by zero: %s"), expr);
       break;
 
     case MODULO_ZERO:
-      M4ERROR ((warning_status, 0,
-               "%s: modulo by zero: %s", me, expr));
+      m4_warn (0, me, _("modulo by zero: %s"), expr);
       break;
 
     case NEGATIVE_EXPONENT:
-      M4ERROR ((warning_status, 0,
-               "%s: negative exponent: %s", me, expr));
+      m4_warn (0, me, _("negative exponent: %s"), expr);
       break;
 
     default:
@@ -530,8 +521,7 @@ equality_term (const char *me, eval_token et, int32_t *v1)
 
       if (op == ASSIGN)
       {
-       M4ERROR ((warning_status, 0, "\
-Warning: %s: recommend ==, not =, for equality", me));
+       m4_warn (0, me, _("recommend ==, not =, for equality"));
        op = EQ;
       }
       *v1 = (op == EQ) == (*v1 == v2);
diff --git a/src/format.c b/src/format.c
index a9e7150..96ac562 100644
--- a/src/format.c
+++ b/src/format.c
@@ -233,8 +233,7 @@ format (struct obstack *obs, int argc, token_data **argv)
       c = *fmt++;
       if (c > sizeof ok || !ok[c])
        {
-         M4ERROR ((warning_status, 0,
-                   "Warning: %s: unrecognized specifier in `%s'", me, f));
+         m4_warn (0, me, _("unrecognized specifier in `%s'"), f);
          if (c == '\0')
            fmt--;
          continue;
@@ -308,8 +307,7 @@ format (struct obstack *obs, int argc, token_data **argv)
         Issue a warning, then proceed.  */
       if (str == NULL)
        {
-         M4ERROR ((warning_status, 0,
-                   "Warning: %s: unable to format output for `%s'", me, f));
+         m4_warn (0, me, _("unable to format output for `%s'"), f);
          continue;
        }
 
diff --git a/src/freeze.c b/src/freeze.c
index df68f3a..16a4ed2 100644
--- a/src/freeze.c
+++ b/src/freeze.c
@@ -56,9 +56,10 @@ produce_frozen_state (const char *name)
   symbol *sym;
   const builtin *bp;
 
-  if (file = fopen (name, O_BINARY ? "wb" : "w"), !file)
+  file = fopen (name, O_BINARY ? "wb" : "w");
+  if (!file)
     {
-      M4ERROR ((warning_status, errno, "%s", name));
+      m4_error (0, errno, NULL, _("cannot open %s"), name);
       return;
     }
 
@@ -151,7 +152,7 @@ produce_frozen_state (const char *name)
 
   fputs ("# End of frozen state file\n", file);
   if (close_stream (file) != 0)
-    M4ERROR ((EXIT_FAILURE, errno, "unable to create frozen state"));
+    m4_error (EXIT_FAILURE, errno, NULL, _("unable to create frozen state"));
 }
 
 /*----------------------------------------------------------------------.
@@ -162,10 +163,10 @@ static void
 issue_expect_message (int expected)
 {
   if (expected == '\n')
-    M4ERROR ((EXIT_FAILURE, 0, "expecting line feed in frozen file"));
+    m4_error (EXIT_FAILURE, 0, NULL, _("expecting line feed in frozen file"));
   else
-    M4ERROR ((EXIT_FAILURE, 0, "expecting character `%c' in frozen file",
-             expected));
+    m4_error (EXIT_FAILURE, 0, NULL,
+             _("expecting character `%c' in frozen file"), expected);
 }
 
 /*-------------------------------------------------.
@@ -226,7 +227,7 @@ reload_frozen_state (const char *name)
 
   file = m4_path_search (name, NULL);
   if (file == NULL)
-    M4ERROR ((EXIT_FAILURE, errno, "cannot open %s", name));
+    m4_error (EXIT_FAILURE, errno, NULL, _("cannot open %s"), name);
 
   allocated[0] = 100;
   string[0] = xcharalloc ((size_t) allocated[0]);
@@ -239,12 +240,12 @@ reload_frozen_state (const char *name)
   GET_CHARACTER;
   GET_NUMBER (number[0]);
   if (number[0] > 1)
-    M4ERROR ((EXIT_MISMATCH, 0,
-             "frozen file version %d greater than max supported of 1",
-             number[0]));
+    m4_error (EXIT_MISMATCH, 0, NULL,
+             _("frozen file version %d greater than max supported of 1"),
+             number[0]);
   else if (number[0] < 1)
-    M4ERROR ((EXIT_FAILURE, 0,
-             "ill-formed frozen file, version directive expected"));
+    m4_error (EXIT_FAILURE, 0, NULL,
+             _("ill-formed frozen file, version directive expected"));
   VALIDATE ('\n');
 
   GET_DIRECTIVE;
@@ -253,7 +254,7 @@ reload_frozen_state (const char *name)
       switch (character)
        {
        default:
-         M4ERROR ((EXIT_FAILURE, 0, "ill-formed frozen file"));
+         m4_error (EXIT_FAILURE, 0, NULL, _("ill-formed frozen file"));
 
        case 'C':
        case 'D':
@@ -292,7 +293,8 @@ reload_frozen_state (const char *name)
 
              if (number[0] > 0)
                if (!fread (string[0], (size_t) number[0], 1, file))
-                 M4ERROR ((EXIT_FAILURE, 0, "premature end of frozen file"));
+                 m4_error (EXIT_FAILURE, 0, NULL,
+                           _("premature end of frozen file"));
 
              string[0][number[0]] = '\0';
            }
@@ -308,7 +310,8 @@ reload_frozen_state (const char *name)
 
          if (number[1] > 0)
            if (!fread (string[1], (size_t) number[1], 1, file))
-             M4ERROR ((EXIT_FAILURE, 0, "premature end of frozen file"));
+             m4_error (EXIT_FAILURE, 0, NULL,
+                       _("premature end of frozen file"));
 
          string[1][number[1]] = '\0';
          GET_CHARACTER;
@@ -372,7 +375,7 @@ reload_frozen_state (const char *name)
   free (string[1]);
   errno = 0;
   if (ferror (file) || fclose (file) != 0)
-    M4ERROR ((EXIT_FAILURE, errno, "unable to read frozen state"));
+    m4_error (EXIT_FAILURE, errno, NULL, _("unable to read frozen state"));
 
 #undef GET_CHARACTER
 #undef GET_DIRECTIVE
diff --git a/src/input.c b/src/input.c
index 58f24be..3d96ec7 100644
--- a/src/input.c
+++ b/src/input.c
@@ -354,16 +354,12 @@ pop_input (bool cleanup)
 
       if (ferror (isp->u.u_f.fp))
        {
-         M4ERROR ((warning_status, 0, "read error"));
+         m4_error (0, 0, NULL, _("read error"));
          if (isp->u.u_f.close)
            fclose (isp->u.u_f.fp);
-         retcode = EXIT_FAILURE;
        }
       else if (isp->u.u_f.close && fclose (isp->u.u_f.fp) == EOF)
-       {
-         M4ERROR ((warning_status, errno, "error reading file"));
-         retcode = EXIT_FAILURE;
-       }
+       m4_error (0, errno, NULL, _("error reading file"));
       start_of_input_line = isp->u.u_f.advance;
       output_current_line = -1;
       break;
@@ -575,8 +571,8 @@ skip_line (const char *name)
   if (ch == CHAR_EOF)
     /* current_file changed to "" if we see CHAR_EOF, use the
        previous value we stored earlier.  */
-    M4ERROR_AT_LINE ((warning_status, 0, file, line,
-                     "Warning: %s: end of file treated as newline", name));
+    m4_warn_at_line (0, file, line, name,
+                    _("end of file treated as newline"));
   /* On the rare occasion that dnl crosses include file boundaries
      (either the input file did not end in a newline, or changeword
      was used), calling next_char can update current_file and
@@ -691,7 +687,7 @@ input_init (void)
   ecomm.length = strlen (ecomm.string);
 
 #ifdef ENABLE_CHANGEWORD
-  set_word_regexp (user_word_regexp);
+  set_word_regexp (NULL, user_word_regexp);
 #endif
 }
 
@@ -756,7 +752,7 @@ set_comment (const char *bc, const char *ec)
 #ifdef ENABLE_CHANGEWORD
 
 void
-set_word_regexp (const char *regexp)
+set_word_regexp (const char *caller, const char *regexp)
 {
   int i;
   char test[2];
@@ -776,8 +772,8 @@ set_word_regexp (const char *regexp)
 
   if (msg != NULL)
     {
-      M4ERROR ((warning_status, 0,
-               "bad regular expression `%s': %s", regexp, msg));
+      /* FIXME - report on behalf of macro caller.  */
+      m4_warn (0, caller, _("bad regular expression `%s': %s"), regexp, msg);
       return;
     }
 
@@ -874,9 +870,8 @@ next_token (token_data *td, int *line, const char *caller)
       else
        /* current_file changed to "" if we see CHAR_EOF, use the
           previous value we stored earlier.  */
-       M4ERROR_AT_LINE ((EXIT_FAILURE, 0, file, *line,
-                         "%s%send of file in comment",
-                         caller ? caller : "", caller ? ": " : ""));
+       m4_error_at_line (EXIT_FAILURE, 0, file, *line, caller,
+                         _("end of file in comment"));
 
       type = TOKEN_STRING;
     }
@@ -958,9 +953,8 @@ next_token (token_data *td, int *line, const char *caller)
          if (ch == CHAR_EOF)
            /* current_file changed to "" if we see CHAR_EOF, use
               the previous value we stored earlier.  */
-           M4ERROR_AT_LINE ((EXIT_FAILURE, 0, file, *line,
-                             "%s%send of file in string",
-                             caller ? caller : "", caller ? ": " : ""));
+           m4_error_at_line (EXIT_FAILURE, 0, file, *line, caller,
+                             _("end of file in string"));
 
          if (MATCH (ch, rquote.string, true))
            {
diff --git a/src/m4.c b/src/m4.c
index 38e26e9..217d389 100644
--- a/src/m4.c
+++ b/src/m4.c
@@ -24,6 +24,7 @@
 #include <getopt.h>
 #include <limits.h>
 #include <signal.h>
+#include <stdarg.h>
 
 #include "version-etc.h"
 
@@ -83,34 +84,115 @@ typedef struct macro_definition macro_definition;
 
 /* Error handling functions.  */
 
-/*-----------------------.
-| Wrapper around error.  |
-`-----------------------*/
+/*------------------------------------------------------------------.
+| Helper for all the error reporting, as a wrapper around          |
+| error_at_line.  Report error message based on FORMAT and ARGS, on |
+| behalf of MACRO, at the location FILE and LINE (but with no      |
+| location if LINE is 0).  If ERRNUM, decode the errno value that   |
+| caused the error.  If STATUS, exit immediately with that status.  |
+| If WARN, prepend 'Warning: '.                                            |
+`------------------------------------------------------------------*/
+
+static void
+m4_verror_at_line (bool warn, int status, int errnum, const char *file,
+                  int line, const char *macro, const char *format,
+                  va_list args)
+{
+  char *full = NULL;
+  /* Prepend warning and the macro name, as needed.  But if that fails
+     for non-memory reasons (unlikely), then still use the original
+     format.  */
+  if (warn && macro)
+    full = xasprintf (_("Warning: %s: %s"), macro, format);
+  else if (warn)
+    full = xasprintf (_("Warning: %s"), format);
+  else if (macro)
+    full = xasprintf (_("%s: %s"), macro, format);
+  verror_at_line (status, errnum, line ? file : NULL, line,
+                 full ? full : format, args);
+  free (full);
+  if ((!warn || fatal_warnings) && !retcode)
+    retcode = EXIT_FAILURE;
+}
+
+/*----------------------------------------------------------------.
+| Wrapper around error.  Report error message based on FORMAT and |
+| subsequent args, on behalf of MACRO, and the current input line |
+| (if any).  If ERRNUM, decode the errno value that caused the   |
+| error.  If STATUS, exit immediately with that status.                  |
+`----------------------------------------------------------------*/
 
 void
-m4_error (int status, int errnum, const char *format, ...)
+m4_error (int status, int errnum, const char *macro, const char *format, ...)
 {
   va_list args;
   va_start (args, format);
-  verror_at_line (status, errnum, current_line ? current_file : NULL,
-                 current_line, format, args);
-  if (fatal_warnings && ! retcode)
-    retcode = EXIT_FAILURE;
+  if (status == EXIT_SUCCESS && warning_status)
+    status = EXIT_FAILURE;
+  m4_verror_at_line (false, status, errnum, current_file, current_line,
+                    macro, format, args);
+  va_end (args);
 }
 
-/*-------------------------------.
-| Wrapper around error_at_line.  |
-`-------------------------------*/
+/*----------------------------------------------------------------.
+| Wrapper around error_at_line.  Report error message based on   |
+| FORMAT and subsequent args, on behalf of MACRO, at the location |
+| FILE and LINE (but with no location if LINE is 0).  If ERRNUM,  |
+| decode the errno value that caused the error.  If STATUS, exit  |
+| immediately with that status.                                          |
+`----------------------------------------------------------------*/
 
 void
 m4_error_at_line (int status, int errnum, const char *file, int line,
-                 const char *format, ...)
+                 const char *macro, const char *format, ...)
 {
   va_list args;
   va_start (args, format);
-  verror_at_line (status, errnum, line ? file : NULL, line, format, args);
-  if (fatal_warnings && ! retcode)
-    retcode = EXIT_FAILURE;
+  if (status == EXIT_SUCCESS && warning_status)
+    status = EXIT_FAILURE;
+  m4_verror_at_line (false, status, errnum, file, line, macro, format, args);
+  va_end (args);
+}
+
+/*------------------------------------------------------------------.
+| Wrapper around error.  Report warning message based on FORMAT and |
+| subsequent args, on behalf of MACRO, and the current input line   |
+| (if any).  If ERRNUM, decode the errno value that caused the     |
+| warning.                                                         |
+`------------------------------------------------------------------*/
+
+void
+m4_warn (int errnum, const char *macro, const char *format, ...)
+{
+  va_list args;
+  if (!suppress_warnings)
+    {
+      va_start (args, format);
+      m4_verror_at_line (true, warning_status, errnum, current_file,
+                        current_line, macro, format, args);
+      va_end (args);
+    }
+}
+
+/*----------------------------------------------------------------.
+| Wrapper around error_at_line.  Report warning message based on  |
+| FORMAT and subsequent args, on behalf of MACRO, at the location |
+| FILE and LINE (but with no location if LINE is 0).  If ERRNUM,  |
+| decode the errno value that caused the warning.                |
+`----------------------------------------------------------------*/
+
+void
+m4_warn_at_line (int errnum, const char *file, int line, const char *macro,
+                const char *format, ...)
+{
+  va_list args;
+  if (!suppress_warnings)
+    {
+      va_start (args, format);
+      m4_verror_at_line (true, warning_status, errnum, file, line, macro,
+                        format, args);
+      va_end (args);
+    }
 }
 
 #ifdef USE_STACKOVF
@@ -122,8 +204,8 @@ m4_error_at_line (int status, int errnum, const char *file, 
int line,
 static void
 stackovf_handler (void)
 {
-  M4ERROR ((EXIT_FAILURE, 0,
-           "ERROR: stack overflow.  (Infinite define recursion?)"));
+  m4_error (EXIT_FAILURE, 0, NULL,
+           _("ERROR: stack overflow.  (Infinite define recursion?)"));
 }
 
 #endif /* USE_STACKOV */
@@ -406,7 +488,7 @@ main (int argc, char *const *argv, char *const *envp)
        break;
 
       case 'E':
-       if (! fatal_warnings)
+       if (!fatal_warnings)
          fatal_warnings = true;
        else
          warning_status = EXIT_FAILURE;
@@ -485,11 +567,11 @@ main (int argc, char *const *argv, char *const *envp)
        break;
 
       case WARN_MACRO_SEQUENCE_OPTION:
-         /* Don't call set_macro_sequence here, as it can exit.
-            --warn-macro-sequence sets optarg to NULL (which uses the
-            default regexp); --warn-macro-sequence= sets optarg to ""
-            (which disables these warnings).  */
-        macro_sequence = optarg;
+        /* Don't call set_macro_sequence here, as it can exit.
+           --warn-macro-sequence sets optarg to NULL (which uses the
+           default regexp); --warn-macro-sequence= sets optarg to ""
+           (which disables these warnings).  */
+       macro_sequence = optarg;
        break;
 
       case VERSION_OPTION:
@@ -505,8 +587,8 @@ main (int argc, char *const *argv, char *const *envp)
   defines = head;
 
   /* Do the basic initializations.  */
-  if (debugfile && !debug_set_output (debugfile))
-    M4ERROR ((0, errno, "cannot set debug file `%s'", debugfile));
+  if (debugfile && !debug_set_output (NULL, debugfile))
+    m4_error (0, errno, NULL, _("cannot set debug file `%s'"), debugfile);
 
   input_init ();
   output_init ();
@@ -564,7 +646,7 @@ main (int argc, char *const *argv, char *const *envp)
 
        case '\1':
          seen_file = true;
-          process_file (defines->arg);
+         process_file (defines->arg);
          break;
 
        default:
@@ -594,7 +676,7 @@ main (int argc, char *const *argv, char *const *envp)
   /* Change debug stream back to stderr, to force flushing the debug
      stream and detect any errors it might have encountered.  The
      three standard streams are closed by close_stdin.  */
-  debug_set_output (NULL);
+  debug_set_output (NULL, NULL);
 
   if (frozen_file_to_write)
     produce_frozen_state (frozen_file_to_write);
diff --git a/src/m4.h b/src/m4.h
index c372ffd..4f1fa1f 100644
--- a/src/m4.h
+++ b/src/m4.h
@@ -69,6 +69,10 @@
 
 /* Used for version mismatch, when -R detects a frozen file it can't parse.  */
 #define EXIT_MISMATCH 63
+
+/* M4 1.4.x is not yet internationalized.  But when it is, this can be
+   redefined as gettext().  */
+#define _(STRING) STRING
 
 /* Various declarations.  */
 
@@ -128,12 +132,12 @@ extern const char *user_word_regexp;      /* -W */
 extern int retcode;
 extern const char *program_name;
 
-void m4_error (int, int, const char *, ...) M4_GNUC_PRINTF(3, 4);
-void m4_error_at_line (int, int, const char *, int,
-                      const char *, ...) M4_GNUC_PRINTF(5, 6);
-
-#define M4ERROR(Arglist) (m4_error Arglist)
-#define M4ERROR_AT_LINE(Arglist) (m4_error_at_line Arglist)
+void m4_error (int, int, const char *, const char *, ...) M4_GNUC_PRINTF(4, 5);
+void m4_error_at_line (int, int, const char *, int, const char *,
+                      const char *, ...) M4_GNUC_PRINTF(6, 7);
+void m4_warn (int, const char *, const char *, ...) M4_GNUC_PRINTF(3, 4);
+void m4_warn_at_line (int, const char *, int, const char *,
+                     const char *, ...) M4_GNUC_PRINTF(5, 6);
 
 #ifdef USE_STACKOVF
 void setup_stackovf_trap (char *const *, char *const *,
@@ -227,7 +231,7 @@ extern FILE *debug;
 void debug_init (void);
 int debug_decode (const char *);
 void debug_flush_files (void);
-bool debug_set_output (const char *);
+bool debug_set_output (const char *, const char *);
 void debug_message_prefix (void);
 
 void trace_prepre (const char *, int);
@@ -314,7 +318,7 @@ extern STRING lquote, rquote;
 void set_quotes (const char *, const char *);
 void set_comment (const char *, const char *);
 #ifdef ENABLE_CHANGEWORD
-void set_word_regexp (const char *);
+void set_word_regexp (const char *, const char *);
 #endif
 
 /* File: output.c --- output functions.  */
@@ -384,6 +388,8 @@ void hack_all_symbols (hack_symbol *, void *);
 
 /* File: macro.c  --- macro expansion.  */
 
+extern int expansion_level;
+
 void expand_input (void);
 void call_macro (symbol *, int, token_data **, struct obstack *);
 
diff --git a/src/macro.c b/src/macro.c
index 6781cd9..8a678d4 100644
--- a/src/macro.c
+++ b/src/macro.c
@@ -134,8 +134,7 @@ warn_builtin_concat (const char *caller, builtin_func *func)
 {
   const builtin *bp = find_builtin_by_addr (func);
   assert (bp);
-  M4ERROR ((warning_status, 0, "Warning: %s: cannot concatenate builtin `%s'",
-           caller, bp->name));
+  m4_warn (0, caller, _("cannot concatenate builtin `%s'"), bp->name);
 }
 
 /*-------------------------------------------------------------------.
@@ -202,8 +201,8 @@ expand_argument (struct obstack *obs, token_data *argp, 
const char *caller)
        case TOKEN_EOF:
          /* current_file changed to "" if we see TOKEN_EOF, use the
             previous value we stored earlier.  */
-         M4ERROR_AT_LINE ((EXIT_FAILURE, 0, file, line,
-                           "%s: end of file in argument list", caller));
+         m4_error_at_line (EXIT_FAILURE, 0, file, line, caller,
+                           _("end of file in argument list"));
          break;
 
        case TOKEN_WORD:
@@ -342,9 +341,9 @@ expand_macro (symbol *sym)
   SYMBOL_PENDING_EXPANSIONS (sym)++;
   expansion_level++;
   if (nesting_limit > 0 && expansion_level > nesting_limit)
-    M4ERROR ((EXIT_FAILURE, 0,
-             "recursion limit of %d exceeded, use -L<N> to change it",
-             nesting_limit));
+    m4_error (EXIT_FAILURE, 0, NULL,
+             _("recursion limit of %d exceeded, use -L<N> to change it"),
+             nesting_limit);
 
   macro_call_id++;
   my_call_id = macro_call_id;
diff --git a/src/output.c b/src/output.c
index 5873d8c..478d3b2 100644
--- a/src/output.c
+++ b/src/output.c
@@ -169,8 +169,8 @@ cleanup_tmpfile (void)
          if (!diversion->size && diversion->u.file
              && close_stream_temp (diversion->u.file) != 0)
            {
-             M4ERROR ((0, errno,
-                       "cannot clean temporary file for diversion"));
+             m4_warn (errno, NULL,
+                      _("cannot clean temporary file for diversion"));
              fail = true;
            }
        }
@@ -198,8 +198,8 @@ m4_tmpname (int divnum)
       tail = strrchr (buffer, '-') + 1;
     }
   if (sprintf (tail, "%d", divnum) < 0)
-    M4ERROR ((EXIT_FAILURE, errno,
-             "cannot create temporary file for diversion"));
+    m4_error (EXIT_FAILURE, errno, NULL,
+             _("cannot create temporary file for diversion"));
   return buffer;
 }
 
@@ -219,8 +219,8 @@ m4_tmpfile (int divnum)
     {
       output_temp_dir = create_temp_dir ("m4-", NULL, true);
       if (output_temp_dir == NULL)
-       M4ERROR ((EXIT_FAILURE, errno,
-                 "cannot create temporary file for diversion"));
+       m4_error (EXIT_FAILURE, errno, NULL,
+                 _("cannot create temporary file for diversion"));
       atexit (cleanup_tmpfile);
     }
   name = m4_tmpname (divnum);
@@ -229,12 +229,11 @@ m4_tmpfile (int divnum)
   if (file == NULL)
     {
       unregister_temp_file (output_temp_dir, name);
-      M4ERROR ((EXIT_FAILURE, errno,
-               "cannot create temporary file for diversion"));
+      m4_error (EXIT_FAILURE, errno, NULL,
+               _("cannot create temporary file for diversion"));
     }
   else if (set_cloexec_flag (fileno (file), true) != 0)
-    M4ERROR ((warning_status, errno,
-             "Warning: cannot protect diversion across forks"));
+    m4_warn (errno, NULL, _("cannot protect diversion across forks"));
   return file;
 }
 
@@ -249,16 +248,15 @@ m4_tmpopen (int divnum)
 
   file = fopen_temp (name, O_BINARY ? "ab+" : "a+");
   if (file == NULL)
-    M4ERROR ((EXIT_FAILURE, errno,
-             "cannot create temporary file for diversion"));
+    m4_error (EXIT_FAILURE, errno, NULL,
+             _("cannot create temporary file for diversion"));
   else if (set_cloexec_flag (fileno (file), true) != 0)
-    M4ERROR ((warning_status, errno,
-             "Warning: cannot protect diversion across forks"));
+    m4_warn (errno, NULL, _("cannot protect diversion across forks"));
   /* POSIX states that it is undefined whether an append stream starts
      at offset 0 or at the end.  We want the beginning.  */
   else if (fseeko (file, 0, SEEK_SET) != 0)
-    M4ERROR ((EXIT_FAILURE, errno,
-             "cannot seek to beginning of diversion"));
+    m4_error (EXIT_FAILURE, errno, NULL,
+             _("cannot seek to beginning of diversion"));
   return file;
 }
 
@@ -351,8 +349,8 @@ make_room_for (int length)
          count = fwrite (selected_buffer, (size_t) selected_diversion->used,
                          1, selected_diversion->u.file);
          if (count != 1)
-           M4ERROR ((EXIT_FAILURE, errno,
-                     "ERROR: cannot flush diversion to temporary file"));
+           m4_error (EXIT_FAILURE, errno, NULL,
+                     _("cannot flush diversion to temporary file"));
        }
 
       /* Reclaim the buffer space for other diversions.  */
@@ -379,7 +377,8 @@ make_room_for (int length)
          FILE *file = selected_diversion->u.file;
          selected_diversion->u.file = NULL;
          if (m4_tmpclose (file) != 0)
-           M4ERROR ((0, errno, "cannot close temporary file for diversion"));
+           m4_warn (errno, NULL,
+                    _("cannot close temporary file for diversion"));
        }
 
       /* The current buffer may be safely reallocated.  */
@@ -441,7 +440,7 @@ output_text (const char *text, int length)
     {
       count = fwrite (text, length, 1, output_file);
       if (count != 1)
-       M4ERROR ((EXIT_FAILURE, errno, "ERROR: copying inserted file"));
+       m4_error (EXIT_FAILURE, errno, NULL, _("error copying inserted file"));
     }
   else
     {
@@ -605,7 +604,8 @@ make_diversion (int divnum)
          FILE *file = output_diversion->u.file;
          output_diversion->u.file = NULL;
          if (m4_tmpclose (file) != 0)
-           M4ERROR ((0, errno, "cannot close temporary file for diversion"));
+           m4_warn (errno, NULL,
+                    _("cannot close temporary file for diversion"));
        }
       output_diversion = NULL;
       output_file = NULL;
@@ -689,7 +689,7 @@ insert_file (FILE *file)
     {
       length = fread (buffer, 1, COPY_BUFFER_SIZE, file);
       if (ferror (file))
-       M4ERROR ((EXIT_FAILURE, errno, "ERROR: reading inserted file"));
+       m4_error (EXIT_FAILURE, errno, NULL, _("error reading inserted file"));
       if (length == 0)
        break;
       output_text (buffer, length);
@@ -736,10 +736,11 @@ insert_diversion_helper (m4_diversion *diversion)
          diversion->u.file = NULL;
          diversion->used = 0;
          if (m4_tmpclose (file) != 0)
-           M4ERROR ((0, errno, "cannot clean temporary file for diversion"));
+           m4_warn (errno, NULL,
+                    _("cannot clean temporary file for diversion"));
        }
       if (m4_tmpremove (diversion->divnum) != 0)
-       M4ERROR ((0, errno, "cannot clean temporary file for diversion"));
+       m4_warn (errno, NULL, _("cannot clean temporary file for diversion"));
     }
   gl_oset_remove (diversion_table, diversion);
   diversion->u.next = free_list;
@@ -819,10 +820,11 @@ freeze_diversions (FILE *file)
              struct stat file_stat;
              diversion->u.file = m4_tmpopen (diversion->divnum);
              if (fstat (fileno (diversion->u.file), &file_stat) < 0)
-               M4ERROR ((EXIT_FAILURE, errno, "cannot stat diversion"));
+               m4_error (EXIT_FAILURE, errno, NULL,
+                         _("cannot stat diversion"));
              if (file_stat.st_size < 0
                  || file_stat.st_size != (unsigned long int) file_stat.st_size)
-               M4ERROR ((EXIT_FAILURE, 0, "diversion too large"));
+               m4_error (EXIT_FAILURE, 0, NULL, _("diversion too large"));
              xfprintf (file, "D%d,%lu\n", diversion->divnum,
                        (unsigned long int) file_stat.st_size);
            }
diff --git a/src/path.c b/src/path.c
index 27ac4cc..98d4567 100644
--- a/src/path.c
+++ b/src/path.c
@@ -133,8 +133,7 @@ m4_path_search (const char *file, char **result)
   if (fp != NULL)
     {
       if (set_cloexec_flag (fileno (fp), true) != 0)
-       M4ERROR ((warning_status, errno,
-                 "Warning: cannot protect input file across forks"));
+       m4_warn (errno, NULL, _("cannot protect input file across forks"));
       if (result)
        *result = xstrdup (file);
       return fp;
@@ -163,8 +162,7 @@ m4_path_search (const char *file, char **result)
          if (debug_level & DEBUG_TRACE_PATH)
            DEBUG_MESSAGE2 ("path search for `%s' found `%s'", file, name);
          if (set_cloexec_flag (fileno (fp), true) != 0)
-           M4ERROR ((warning_status, errno,
-                     "Warning: cannot protect input file across forks"));
+           m4_warn (errno, NULL, _("cannot protect input file across forks"));
          if (result)
            *result = name;
          else


hooks/post-receive
--
GNU M4 source repository




reply via email to

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