m4-discuss
[Top][All Lists]
Advanced

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

Re: popdef(undefined), __m4_version__


From: Eric Blake
Subject: Re: popdef(undefined), __m4_version__
Date: Mon, 25 Aug 2008 07:07:21 -0600
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.16) Gecko/20080708 Thunderbird/2.0.0.16 Mnenhy/0.7.5.666

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

According to Eric Blake on 8/3/2008 5:39 PM:
> |
> | That's not to say the default mode need necessarily be compatible, but
> | at least detecting that we are running inside autoconf and setting the
> | right options to work without patching would be the kindest thing to
> | do.
> 
> You are doing a good job of convincing me that the inability of m4 1.6 to
> work with unpatched autoconf 2.62 is bad.  Here's my current idea:
> 
> In m4, add a new debugmode() letter (perhaps 'd' for dereference), then
> condition all warnings related to dereferencing undefined macros on that
> option being set.  Right now, if you don't use m4 -d, you default to a
> debugmode of ""; we could change this to default to a debugmode of "d", so
> that a vanilla user of m4 gets the warning.  Likewise, 'm4 -d' was
> equivalent to 'm4 -daeq'; it would now be equivalent to 'm4 -dadeq'.

Here's what I'm planning on committing to m4; it adds debugmode(d) as a
new flag that controls whether dereferencing undefined macros warns, then
enables the flag by default unless an explicit -d specifies other flags or
if -E is in effect.  Both conditions for disabling the debugmode(d) flag
were necessary, so that branch-1.6 of m4.git can once again handle
autoconf 2.62 out of the box.

By committing this series, I now need a followup patch to autoconf;
m4sugar now needs to explicitly request m4_debugmode([+d]) when it detects
__m4_version__, before it can rely on native defn/popdef/undefine for speed.

I am also working on an autom4te patch that detects status 63 when loading
a frozen file, and falls back to retrying the load without the use of a
frozen file; which, if I then make m4 1.6 use frozen file format 2, will
allow the user to install autoconf with m4 1.6, then downgrade to m4 1.4.x
without being penalized by quadratic performance.

- --
Don't work too hard, make some time for fun as well!

Eric Blake             address@hidden
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (Cygwin)
Comment: Public key at home.comcast.net/~ericblake/eblake.gpg
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org

iEYEARECAAYFAkiyrokACgkQ84KuGfSFAYA4VwCeM+wrCY82PDzbfZS4ZKYWJyuL
95MAoKG7EGXRMx7G04FpCHPCUplTnETH
=I2oY
-----END PGP SIGNATURE-----
>From 8912baaae894abfe31716a003126b680351be33c Mon Sep 17 00:00:00 2001
From: Eric Blake <address@hidden>
Date: Mon, 18 Aug 2008 06:29:31 -0600
Subject: [PATCH] Allow + and - in --debug, and add --debugmode.

* src/builtin.c (m4_debugmode): Move +- handling...
* src/debug.c (debug_decode): ...here.
* src/m4.c (main): Adjust caller.
(long_options): Add alternate spelling for --debug.
(usage): Mention it.
* doc/m4.texinfo (Debugging options): Document additional
semantics.
* NEWS: Likewise.

Signed-off-by: Eric Blake <address@hidden>
(cherry picked from commit c2e093a955214b8aaf4da8dd44bd595b06fea235)
---
 ChangeLog      |   12 ++++++++++++
 NEWS           |    7 +++++++
 doc/m4.texinfo |   39 ++++++++++++++++++++++++++++++---------
 src/builtin.c  |   37 ++-----------------------------------
 src/debug.c    |   35 ++++++++++++++++++++++++++++++-----
 src/m4.c       |   12 +++++-------
 6 files changed, 86 insertions(+), 56 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 0e06082..bb719cf 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2008-08-22  Eric Blake  <address@hidden>
+
+       Allow + and - in --debug, and add --debugmode.
+       * src/builtin.c (m4_debugmode): Move +- handling...
+       * src/debug.c (debug_decode): ...here.
+       * src/m4.c (main): Adjust caller.
+       (long_options): Add alternate spelling for --debug.
+       (usage): Mention it.
+       * doc/m4.texinfo (Debugging options): Document additional
+       semantics.
+       * NEWS: Likewise.
+
 2008-08-21  Eric Blake  <address@hidden>
 
        Fix crash with traced defn(undef), regression from 2007-08-09.
diff --git a/NEWS b/NEWS
index 109c80a..0099383 100644
--- a/NEWS
+++ b/NEWS
@@ -42,6 +42,13 @@ Foundation, Inc.
    then apply this patch:
      http://git.sv.gnu.org/gitweb/?p=autoconf.git;a=commitdiff;h=56d42fa71
 
+** The `-d'/`--debug' command-line option now understands `-' and `+'
+   modifiers, the way the builtin `debugmode' has always done; this allows
+   `-d-V' to disable prior debug settings from the command line, similar to
+   using the builtin `debugmode' without arguments.  The option
+   `--debugmode' is added as an alias for `-d'.  When given the empty
+   string, the mode is treated as `+aeq' instead of `aeq'.
+
 ** New `-g'/`--gnu' command-line option overrides `-G'/`--traditional'.
    For now, the environment variable POSIXLY_CORRECT has no effect on M4
    behavior; but a future release of M4 will behave as though --traditional
diff --git a/doc/m4.texinfo b/doc/m4.texinfo
index 7540b2e..f47fd3c 100644
--- a/doc/m4.texinfo
+++ b/doc/m4.texinfo
@@ -838,12 +838,34 @@ Debugging options
 scripts.
 
 @table @code
address@hidden address@hidden@address@hidden
address@hidden address@hidden@address@hidden
address@hidden address@hidden@address@hidden|address@hidden@address@hidden
address@hidden address@hidden@address@hidden|address@hidden@address@hidden
address@hidden address@hidden@address@hidden|address@hidden@address@hidden
 Set the debug-level according to the flags @var{FLAGS}.  The debug-level
 controls the format and amount of information presented by the debugging
 functions.  @xref{Debug Levels}, for more details on the format and
-meaning of @var{FLAGS}.  If omitted, @var{FLAGS} defaults to @samp{aeq}.
+meaning of @var{FLAGS}.  If omitted, @var{FLAGS} defaults to
address@hidden  If the option occurs multiple times, @var{FLAGS} starting
+with @samp{-} or @samp{+} are cumulative, while @var{FLAGS} starting
+with a letter override all earlier settings.  Therefore, to disable all
+previously set flags, specify an explicit @var{FLAGS} of @samp{-V}.  The
+spelling @option{--debug} is recognized as an unambiguous option for
+compatibility with earlier versions of @acronym{GNU} M4, but for
+consistency with the builtin name, you can also use the spelling
address@hidden
+
+The cumulative effect of the various options in this example is
+equivalent to a single invocation of @code{debugmode(`alqx')}:
+
address@hidden options: -d-V -d+lx --debug --debugmode=-e
address@hidden
+$ @kbd{m4 -d+lx --debug --debugmode=-e}
+traceon(`len')
address@hidden
+len(`123')
address@hidden:2: -1- id 2: len(`123')
address@hidden
address@hidden example
 
 @item address@hidden
 @itemx -o @var{FILE}
@@ -2483,6 +2505,7 @@ Pushdef
 @option{-Q} (@option{--quiet}, @pxref{Operation modes, , Invoking m4}).
 
 @example
+$ @kbd{m4}
 define(`a', `1')
 @result{}
 popdef
@@ -3646,10 +3669,10 @@ Dumpdef
 If you want to see what a name expands into, you can use the builtin
 @code{dumpdef}:
 
address@hidden Builtin dumpdef (@address@hidden)
address@hidden Builtin dumpdef (@address@hidden)
 Accepts any number of arguments.  If called without any arguments,
 it displays the definitions of all known names, otherwise it displays
-the definitions of the @var{names} given.  The output is printed to the
+the definitions of each @var{name} given.  The output is printed to the
 current debug file (usually standard error), and is sorted by name.  If
 an unknown name is encountered, a warning is printed.
 
@@ -3741,8 +3764,7 @@ Trace
 @option{-t}) can be used to invoke @code{traceon(@var{name})} before
 parsing input.
 
address@hidden The explicit -dp neutralizes the testsuite default of -d.
address@hidden options: -dp -L3 -tifelse
address@hidden options: -d-V -L3 -tifelse
 @comment status: 1
 @example
 $ @kbd{m4 -L 3 -t ifelse}
@@ -3992,8 +4014,7 @@ Debug Levels
 The expansion of @code{debugmode} is void.
 @end deffn
 
address@hidden The explicit -dp neutralizes the testsuite default of -d.
address@hidden options: -dp
address@hidden options: -d-V
 @example
 $ @kbd{m4}
 define(`foo', `FOO')
diff --git a/src/builtin.c b/src/builtin.c
index b8449a0..34387b9 100644
--- a/src/builtin.c
+++ b/src/builtin.c
@@ -1759,46 +1759,13 @@ m4_debugmode (struct obstack *obs, int argc, 
macro_arguments *argv)
 {
   const call_info *me = arg_info (argv);
   const char *str = ARG (1);
-  int new_debug_level;
-  int change_flag;
 
   bad_argc (me, argc, 0, 1);
 
   if (argc == 1)
     debug_level = 0;
-  else
-    {
-      if (*str == '+' || *str == '-')
-       {
-         change_flag = *str;
-         new_debug_level = debug_decode (str + 1);
-       }
-      else
-       {
-         change_flag = 0;
-         new_debug_level = debug_decode (str);
-       }
-
-      if (new_debug_level < 0)
-       m4_warn (0, me, _("bad debug flags: `%s'"), str);
-      else
-       {
-         switch (change_flag)
-           {
-           case 0:
-             debug_level = new_debug_level;
-             break;
-
-           case '+':
-             debug_level |= new_debug_level;
-             break;
-
-           case '-':
-             debug_level &= ~new_debug_level;
-             break;
-           }
-       }
-    }
+  else if (debug_decode (str) < 0)
+    m4_warn (0, me, _("bad debug flags: `%s'"), str);
 }
 
 /*-------------------------------------------------------------------------.
diff --git a/src/debug.c b/src/debug.c
index c3f85bd..579960b 100644
--- a/src/debug.c
+++ b/src/debug.c
@@ -43,20 +43,24 @@ debug_init (void)
   obstack_init (&trace);
 }
 
-/*-----------------------------------------------------------------.
-| Function to decode the debugging flags OPTS.  Used by main while |
-| processing option -d, and by the builtin debugmode ().          |
-`-----------------------------------------------------------------*/
+/*------------------------------------------------------------------.
+| Function to decode the debugging flags OPTS.  Used by main while  |
+| processing option -d, and by the builtin debugmode ().  Return -1 |
+| if the parse failed, otherwise change the debug level.           |
+`------------------------------------------------------------------*/
 
 int
 debug_decode (const char *opts)
 {
   int level;
+  char mode = '\0';
 
   if (opts == NULL || *opts == '\0')
-    level = DEBUG_TRACE_DEFAULT;
+    level = DEBUG_TRACE_DEFAULT | debug_level;
   else
     {
+      if (*opts == '-' || *opts == '+')
+       mode = *opts++;
       for (level = 0; *opts; opts++)
        {
          switch (*opts)
@@ -110,6 +114,27 @@ debug_decode (const char *opts)
            }
        }
     }
+  switch (mode)
+    {
+    case '\0':
+      /* Replace old level.  */
+      break;
+
+    case '-':
+      /* Subtract flags.  */
+      level = debug_level & ~level;
+      break;
+
+    case '+':
+      /* Add flags.  */
+      level |= debug_level;
+      break;
+
+    default:
+      assert (!"debug_decode");
+      abort ();
+    }
+  debug_level = level;
   return level;
 }
 
diff --git a/src/m4.c b/src/m4.c
index 73ccce1..c368021 100644
--- a/src/m4.c
+++ b/src/m4.c
@@ -256,7 +256,8 @@ Frozen state files:\n\
       puts ("");
       fputs (_("\
 Debugging:\n\
-  -d, --debug[=FLAGS]          set debug level (no FLAGS implies `aeq')\n\
+  -d, --debug[=[-|+]FLAGS], --debugmode[=[-|+]FLAGS]\n\
+                               set debug level (no FLAGS implies `+aeq')\n\
       --debugfile=FILE         redirect debug and trace output\n\
   -l, --arglength=NUM          restrict macro tracing size\n\
   -t, --trace=NAME             trace NAME when it is defined\n\
@@ -318,6 +319,7 @@ static const struct option long_options[] =
 {
   {"arglength", required_argument, NULL, 'l'},
   {"debug", optional_argument, NULL, 'd'},
+  {"debugmode", optional_argument, NULL, 'd'},
   {"define", required_argument, NULL, 'D'},
   {"error-output", required_argument, NULL, 'o'}, /* FIXME: deprecate in 2.0 */
   {"fatal-warnings", no_argument, NULL, 'E'},
@@ -521,12 +523,8 @@ main (int argc, char *const *argv, char *const *envp)
 #endif
 
       case 'd':
-       debug_level = debug_decode (optarg);
-       if (debug_level < 0)
-         {
-           error (0, 0, "bad debug flags: `%s'", optarg);
-           debug_level = 0;
-         }
+       if (debug_decode (optarg) < 0)
+         error (0, 0, "bad debug flags: `%s'", optarg);
        break;
 
       case 'e':
-- 
1.6.0


>From cb3bbd28fa8a04d3eddc08261169b5c3e98c252f Mon Sep 17 00:00:00 2001
From: Eric Blake <address@hidden>
Date: Mon, 18 Aug 2008 07:17:35 -0600
Subject: [PATCH] Interleave -d handling with files.

* src/m4.c (main): Defer -d handling when appropriate.
* doc/m4.texinfo (Debugging options): Mention it.
(Command line files): Test it.
* NEWS: Mention it.

Signed-off-by: Eric Blake <address@hidden>
---
 ChangeLog      |    6 ++++++
 NEWS           |    4 +++-
 doc/m4.texinfo |   18 +++++++++++++++++-
 src/m4.c       |   13 +++++++++++--
 4 files changed, 37 insertions(+), 4 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index bb719cf..07fced3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,11 @@
 2008-08-22  Eric Blake  <address@hidden>
 
+       Interleave -d handling with files.
+       * src/m4.c (main): Defer -d handling when appropriate.
+       * doc/m4.texinfo (Debugging options): Mention it.
+       (Command line files): Test it.
+       * NEWS: Mention it.
+
        Allow + and - in --debug, and add --debugmode.
        * src/builtin.c (m4_debugmode): Move +- handling...
        * src/debug.c (debug_decode): ...here.
diff --git a/NEWS b/NEWS
index 0099383..9e69a3b 100644
--- a/NEWS
+++ b/NEWS
@@ -47,7 +47,9 @@ Foundation, Inc.
    `-d-V' to disable prior debug settings from the command line, similar to
    using the builtin `debugmode' without arguments.  The option
    `--debugmode' is added as an alias for `-d'.  When given the empty
-   string, the mode is treated as `+aeq' instead of `aeq'.
+   string, the mode is treated as `+aeq' instead of `aeq'.  Also, the
+   position of `-d' with respect to files on the command line is now
+   significant.
 
 ** New `-g'/`--gnu' command-line option overrides `-G'/`--traditional'.
    For now, the environment variable POSIXLY_CORRECT has no effect on M4
diff --git a/doc/m4.texinfo b/doc/m4.texinfo
index f47fd3c..5cfdb1a 100644
--- a/doc/m4.texinfo
+++ b/doc/m4.texinfo
@@ -852,7 +852,7 @@ Debugging options
 spelling @option{--debug} is recognized as an unambiguous option for
 compatibility with earlier versions of @acronym{GNU} M4, but for
 consistency with the builtin name, you can also use the spelling
address@hidden
address@hidden  Order is significant with respect to file names.
 
 The cumulative effect of the various options in this example is
 equivalent to a single invocation of @code{debugmode(`alqx')}:
@@ -926,6 +926,7 @@ Command line files
 The text @samp{bar} can then be redefined over multiple uses of
 @file{foo}:
 
address@hidden examples
 @comment options: -Dbar=hello foo -Dbar=world foo
 @example
 $ @kbd{m4 -Dbar=hello foo -Dbar=world foo}
@@ -933,6 +934,21 @@ Command line files
 @result{}world
 @end example
 
address@hidden
address@hidden Not worth putting the manual, but worth testing.
+
address@hidden examples
address@hidden options: -Dbar=hello -d foo -t bar foo -d-V foo
address@hidden
+$ @kbd{m4 -Dbar=hello -d foo -t bar foo -d-V foo
address@hidden
address@hidden: -1- bar -> `hello'
address@hidden
address@hidden: -1- bar
address@hidden
address@hidden example
address@hidden ignore
+
 If none of the input files invoked @code{m4exit} (@pxref{M4exit}), the
 exit status of @code{m4} will be 0 for success, 1 for general failure
 (such as problems with reading an input file), and 63 for version
diff --git a/src/m4.c b/src/m4.c
index c368021..22586fc 100644
--- a/src/m4.c
+++ b/src/m4.c
@@ -455,11 +455,14 @@ main (int argc, char *const *argv, char *const *envp)
               optchar);
        break;
 
+      case '\1':
+       seen_file = true;
+       /* fall through */
       case 'D':
       case 'U':
       case 's':
       case 't':
-      case '\1':
+      defer:
        /* Arguments that cannot be handled until later are accumulated.  */
 
        defn = (macro_definition *) xmalloc (sizeof (macro_definition));
@@ -523,6 +526,8 @@ main (int argc, char *const *argv, char *const *envp)
 #endif
 
       case 'd':
+       if (seen_file)
+         goto defer;
        if (debug_decode (optarg) < 0)
          error (0, 0, "bad debug flags: `%s'", optarg);
        break;
@@ -621,6 +626,11 @@ main (int argc, char *const *argv, char *const *envp)
          lookup_symbol (defines->arg, strlen (defines->arg), SYMBOL_DELETE);
          break;
 
+       case 'd':
+         if (debug_decode (defines->arg) < 0)
+           error (0, 0, "bad debug flags: `%s'", defines->arg);
+         break;
+
        case 't':
          sym = lookup_symbol (defines->arg, strlen (defines->arg),
                               SYMBOL_INSERT);
@@ -632,7 +642,6 @@ main (int argc, char *const *argv, char *const *envp)
          break;
 
        case '\1':
-         seen_file = true;
          process_file (defines->arg);
          break;
 
-- 
1.6.0


>From d918ca5f34a4653ed4120d5732c8b46738f78bb3 Mon Sep 17 00:00:00 2001
From: Eric Blake <address@hidden>
Date: Fri, 22 Aug 2008 17:26:01 -0600
Subject: [PATCH] Allow debugmode control over whether defn(undef) warns.

* src/m4.h (DEBUG_TRACE_DEREF): New define.
(DEBUG_TRACE_VERBOSE, DEBUG_TRACE_DEFAULT): Adjust.
* src/m4.c (debug_level): Start with debugmode = d.
(usage): Mention this.
(main): Let -E impact debug mode.
* src/builtin.c (m4_undefine, m4_popdef, m4_dumpdef, m4_builtin)
(m4_indir, m4_defn): Squelch undefined warning if debug flag is
clear.
* src/debug.c (debug_decode): Parse new mode.
* doc/m4.texinfo (Debugging options): Mention change in the
default behavior.
(Debug Levels): Mention new flag d.
(Operation modes): Mention interaction with -E.
(Undefine, Defn, Pushdef, Indir, Builtin, Dumpdef): Document and
test its effect.
* NEWS: Document this.
Reported by Ralf Wildenhues; without this patch, M4 1.6 would be
incompatible with Autoconf 2.62.

Signed-off-by: Eric Blake <address@hidden>
---
 ChangeLog      |   22 +++++++
 NEWS           |   32 ++++------
 doc/m4.texinfo |  186 ++++++++++++++++++++++++++++++++++++++-----------------
 src/builtin.c  |   29 ++++++---
 src/debug.c    |    4 +
 src/m4.c       |    6 +-
 src/m4.h       |    8 ++-
 7 files changed, 195 insertions(+), 92 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 07fced3..1b9bbaa 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,25 @@
+2008-08-23  Eric Blake  <address@hidden>
+
+       Allow debugmode control over whether defn(undef) warns.
+       * src/m4.h (DEBUG_TRACE_DEREF): New define.
+       (DEBUG_TRACE_VERBOSE, DEBUG_TRACE_DEFAULT): Adjust.
+       * src/m4.c (debug_level): Start with debugmode = d.
+       (usage): Mention this.
+       (main): Let -E impact debug mode.
+       * src/builtin.c (m4_undefine, m4_popdef, m4_dumpdef, m4_builtin)
+       (m4_indir, m4_defn): Squelch undefined warning if debug flag is
+       clear.
+       * src/debug.c (debug_decode): Parse new mode.
+       * doc/m4.texinfo (Debugging options): Mention change in the
+       default behavior.
+       (Debug Levels): Mention new flag d.
+       (Operation modes): Mention interaction with -E.
+       (Undefine, Defn, Pushdef, Indir, Builtin, Dumpdef): Document and
+       test its effect.
+       * NEWS: Document this.
+       Reported by Ralf Wildenhues; without this patch, M4 1.6 would be
+       incompatible with Autoconf 2.62.
+
 2008-08-22  Eric Blake  <address@hidden>
 
        Interleave -d handling with files.
diff --git a/NEWS b/NEWS
index 9e69a3b..5a3ecb3 100644
--- a/NEWS
+++ b/NEWS
@@ -46,10 +46,12 @@ Foundation, Inc.
    modifiers, the way the builtin `debugmode' has always done; this allows
    `-d-V' to disable prior debug settings from the command line, similar to
    using the builtin `debugmode' without arguments.  The option
-   `--debugmode' is added as an alias for `-d'.  When given the empty
-   string, the mode is treated as `+aeq' instead of `aeq'.  Also, the
-   position of `-d' with respect to files on the command line is now
-   significant.
+   `--debugmode' is added as an alias for `-d'.  The new flag `d' is added
+   to control whether dereferncing an undefined macro causes a warning;
+   this flag is enabled by default if neither `-d' nor `-E' are specified.
+   When given the empty string, the mode is treated as `+adeq' instead of
+   `aeq'.  Also, the position of `-d' with respect to files on the command
+   line is now significant.
 
 ** New `-g'/`--gnu' command-line option overrides `-G'/`--traditional'.
    For now, the environment variable POSIXLY_CORRECT has no effect on M4
@@ -69,21 +71,13 @@ Foundation, Inc.
    be used, via `defn', to determine whether the version of m4 processing
    your file is adequate.
 
-** The `defn', `popdef', and `undefine' builtins now warn when operating
-   on an undefined macro name, similar to what was already done in the
-   `indir' and `dumpdef' builtins.  To simulate 1.4.x behavior, use:
-     pushdef(`defn', `ifelse(`$#', `0', ``defn'',
-                             `ifdef(`$1', `builtin(`defn', `$1')')')')
-     pushdef(`popdef', `ifelse(`$#', `0', ``popdef'', `_$0($@)')')
-     define(`_popdef', `ifdef(`$1', `builtin(`popdef', `$1')')ifelse(`$#',
-                `1', `', `$0(shift($@))')')
-     pushdef(`undefine', `ifelse(`$#', `0', ``undefine'', `_$0($@)')')
-     define(`_undefine', `ifdef(`$1', `builtin(`undefine', `$1')')ifelse(`$#',
-                `1', `', `$0(shift($@))')')
-
-   Additionally, if you want to install Autoconf 2.62 or earlier, then
-   apply this patch:
-     http://git.sv.gnu.org/gitweb/?p=autoconf.git;a=commitdiff;h=c4a32a009
+** The `defn', `popdef', and `undefine' builtins gained a new warning when
+   operating on an undefined macro name, to match the warning already
+   present in `builtin', `indir', and `dumpdef'.  For backwards
+   compatibility, the warning can be disabled by using `debugmode(`-d')'
+   (or the command line option `--debug=-d').  The flag is also cleared by
+   the command line option `-E'/`--fatal-warnings', so that scripts written
+   for 1.4.x do not cause the script to fail because of new warnings.
 
 ** Enhance the `indir' builtin to trace indirect macros, where the trace
    is requested via `traceon' or the command-line option `-t'.  Previously,
diff --git a/doc/m4.texinfo b/doc/m4.texinfo
index 5cfdb1a..e537c79 100644
--- a/doc/m4.texinfo
+++ b/doc/m4.texinfo
@@ -598,6 +598,56 @@ Operation modes
 1.4.9; for behavior consistent with earlier versions, you should specify
 @option{-E} twice.
 
+For backwards compatibility reasons, using @option{-E} behaves as if an
+implicit @option{--debug=-d} option is also present.  This is so that
+scripts written for older M4 versions will not fail if they used
+constructs that were previously silently allowed, but would now trigger
+a warning.
+
address@hidden
+$ @kbd{m4}
+defn(`oops')
address@hidden:stdin:1: Warning: defn: undefined macro `oops'
address@hidden
+^D
address@hidden example
+
address@hidden ignore
address@hidden
+$ @kbd{echo $?}
address@hidden
address@hidden example
+
address@hidden options: -E
address@hidden
+$ @kbd{m4 -E}
+defn(`oops')
address@hidden
+^D
address@hidden example
+
address@hidden ignore
address@hidden
+$ @kbd{echo $?}
address@hidden
address@hidden example
+
address@hidden options: -E -d
address@hidden status: 1
address@hidden
+$ @kbd{m4 -E -d}
+defn(`oops')
address@hidden:stdin:1: Warning: defn: undefined macro `oops'
address@hidden
+^D
address@hidden example
+
address@hidden ignore
address@hidden
+$ @kbd{echo $?}
address@hidden
address@hidden example
+
 @item -i
 @itemx --interactive
 @itemx -e
@@ -845,17 +895,20 @@ Debugging options
 controls the format and amount of information presented by the debugging
 functions.  @xref{Debug Levels}, for more details on the format and
 meaning of @var{FLAGS}.  If omitted, @var{FLAGS} defaults to
address@hidden  If the option occurs multiple times, @var{FLAGS} starting
address@hidden  If the option occurs multiple times, @var{FLAGS} starting
 with @samp{-} or @samp{+} are cumulative, while @var{FLAGS} starting
-with a letter override all earlier settings.  Therefore, to disable all
-previously set flags, specify an explicit @var{FLAGS} of @samp{-V}.  The
-spelling @option{--debug} is recognized as an unambiguous option for
+with a letter override all earlier settings.  The debug-level starts
+with @samp{d} enabled and all other flags disabled.  To disable all
+previously set flags, specify an explicit @var{FLAGS} of @samp{-V}.  For
+backward compatibility reasons, the option @option{--fatal-warnings}
+implies @samp{--debug=-d} as part of its effects.  The spelling
address@hidden is recognized as an unambiguous option for
 compatibility with earlier versions of @acronym{GNU} M4, but for
 consistency with the builtin name, you can also use the spelling
 @option{--debugmode}.  Order is significant with respect to file names.
 
 The cumulative effect of the various options in this example is
-equivalent to a single invocation of @code{debugmode(`alqx')}:
+equivalent to a single invocation of @code{debugmode(`adlqx')}:
 
 @comment options: -d-V -d+lx --debug --debugmode=-e
 @example
@@ -2130,7 +2183,8 @@ Undefine
 @deffn Builtin undefine (@address@hidden)
 For each argument, remove the macro @var{name}.  The macro names must
 necessarily be quoted, since they will be expanded otherwise.  If an
-argument is not a defined macro, a warning is issued.
+argument is not a defined macro, then the @samp{d} debug level controls
+whether a warning is issued (@pxref{Debug Levels}).
 
 The expansion of @code{undefine} is void.
 The macro @code{undefine} is recognized only with parameters.
@@ -2165,30 +2219,19 @@ Undefine
 @result{}f(bye)
 @end example
 
-As of M4 1.6, @code{undefine} will warn if @var{name} is not a macro.
-The following example shows how to recover earlier behavior that
-silently ignores undefined names, using concepts that will be explained
-later in the manual.  Or, you could use the command line option
address@hidden (@option{--quiet}, @pxref{Operation modes, , Invoking m4}).
+As of M4 1.6, @code{undefine} can warn if @var{name} is not a macro, by
+using @code{debugmode} (@pxref{Debug Levels}) or the command line option
address@hidden (@option{--debugmode}, @pxref{Debugging options, , Invoking
+m4}).
 
 @example
-define(`a', `1')
address@hidden
-undefine
address@hidden
-undefine(`a', `a')
address@hidden:stdin:3: Warning: undefine: undefined macro `a'
address@hidden
-define(`a', `1')
address@hidden
-pushdef(`undefine', `ifelse(`$#', `0', ``undefine'', `_$0($@@)')')
+$ @kbd{m4}
+undefine(`a')
address@hidden:stdin:1: Warning: undefine: undefined macro `a'
 @result{}
-define(`_undefine', `ifdef(`$1', `builtin(`undefine',
-  `$1')')ifelse(`$#', `1', `', `$0(shift($@@))')')
+debugmode(`-d')
 @result{}
-undefine
address@hidden
-undefine(`a', `a')
+undefine(`a')
 @result{}
 @end example
 
@@ -2205,7 +2248,8 @@ Defn
 @deffn Builtin defn (@address@hidden)
 Expands to the @emph{quoted definition} of each @var{name}.  If an
 argument is not a defined macro, the expansion for that argument is
-empty and triggers a warning.
+empty, and the @samp{d} debug level controls whether a warning is issued
+(@pxref{Debug Levels}).
 
 If @var{name} is a user-defined macro, the quoted definition is simply
 the quoted expansion text.  If, instead, @var{name} is a builtin, the
@@ -2371,9 +2415,11 @@ Defn
 @result{}0
 @end example
 
-A warning is issued if @var{name} is undefined.  Also note that as of M4
-1.6, @code{defn} with multiple arguments can join text with builtin
-tokens.  However, when defining a macro via @code{define} or
+As of M4 1.6, @code{defn} can warn if @var{name} is not a macro, by
+using @code{debugmode} (@pxref{Debug Levels}) or the command line option
address@hidden (@option{--debugmode}, @pxref{Debugging options, , Invoking
+m4}).  Also, @code{defn} with multiple arguments can join text with
+builtin tokens.  However, when defining a macro via @code{define} or
 @code{pushdef}, a warning is issued and the builtin token ignored if the
 builtin token does not occur in isolation.  A future version of
 @acronym{GNU} M4 may lift this restriction.
@@ -2383,6 +2429,10 @@ Defn
 defn(`foo')
 @error{}m4:stdin:1: Warning: defn: undefined macro `foo'
 @result{}
+debugmode(`-d')
address@hidden
+defn(`foo')
address@hidden
 define(`a', `A')define(`AA', `b')
 @result{}
 traceon(`defn', `define')
@@ -2392,25 +2442,25 @@ Defn
 @result{}AA
 define(`mydivnum', defn(`divnum', `divnum'))mydivnum
 @error{}m4trace: -2- defn(`divnum', `divnum') -> `<divnum><divnum>'
address@hidden:stdin:5: Warning: define: cannot concatenate builtins
address@hidden:stdin:7: Warning: define: cannot concatenate builtins
 @error{}m4trace: -1- define(`mydivnum', `<divnum><divnum>') -> `'
 @result{}
 traceoff(`defn', `define')dumpdef(`mydivnum')
 @error{}mydivnum:@tabchar{}`'
 @result{}
 define(`mydivnum', defn(`divnum')defn(`divnum'))mydivnum
address@hidden:stdin:7: Warning: define: cannot concatenate builtins
address@hidden:stdin:9: Warning: define: cannot concatenate builtins
 @result{}
 define(`mydivnum', defn(`divnum')`a')mydivnum
address@hidden:stdin:8: Warning: define: cannot concatenate builtins
address@hidden:stdin:10: Warning: define: cannot concatenate builtins
 @result{}A
 define(`mydivnum', `a'defn(`divnum'))mydivnum
address@hidden:stdin:9: Warning: define: cannot concatenate builtins
address@hidden:stdin:11: Warning: define: cannot concatenate builtins
 @result{}A
 define(`q', ``$@@'')
 @result{}
 define(`foo', q(`a', defn(`divnum')))foo
address@hidden:stdin:11: Warning: define: cannot concatenate builtins
address@hidden:stdin:13: Warning: define: cannot concatenate builtins
 @result{}a,
 ifdef(`foo', `yes', `no')
 @result{}yes
@@ -2441,7 +2491,8 @@ Pushdef
 If a macro has several definitions (of which only one is accessible),
 the topmost definition can be removed with @code{popdef}.  If there is
 no previous definition, @code{popdef} behaves like @code{undefine}, and
-if there is no definition at all, @code{popdef} issues a warning.
+if there is no definition at all, the @samp{d} debug level controls
+whether a warning is issued (@pxref{Debug Levels}).
 
 The expansion of both @code{pushdef} and @code{popdef} is void.
 The macros @code{pushdef} and @code{popdef} are recognized only with
@@ -2514,11 +2565,10 @@ Pushdef
 It is possible to temporarily redefine a builtin with @code{pushdef}
 and @code{defn}.
 
-As of M4 1.6, @code{popdef} will warn if @var{name} is not a macro.
-The following example shows how to recover earlier behavior that
-silently ignores undefined names, using concepts that will be explained
-later in the manual.  Or, you could use the command line option
address@hidden (@option{--quiet}, @pxref{Operation modes, , Invoking m4}).
+As of M4 1.6, @code{popdef} can warn if @var{name} is not a macro, by
+using @code{debugmode} (@pxref{Debug Levels}) or the command line option
address@hidden (@option{--debugmode}, @pxref{Debugging options, , Invoking
+m4}).
 
 @example
 $ @kbd{m4}
@@ -2529,16 +2579,9 @@ Pushdef
 popdef(`a', `a')
 @error{}m4:stdin:3: Warning: popdef: undefined macro `a'
 @result{}
-define(`a', `1')
address@hidden
-pushdef(`popdef', `ifelse(`$#', `0', ``popdef'', `_$0($@@)')')
address@hidden
-define(`_popdef', `ifdef(`$1', `builtin(`popdef',
-  `$1')')ifelse(`$#', `1', `', `$0(shift($@@))')')
+debugmode(`-d')
 @result{}
-popdef
address@hidden
-popdef(`a', `a')
+popdef(`a')
 @result{}
 @end example
 
@@ -2552,9 +2595,10 @@ Indir
 Any macro can be called indirectly with @code{indir}:
 
 @deffn Builtin indir (@var{name}, @address@hidden)
-Results in a call to the macro @var{name}, which is passed the
-rest of the arguments @var{args}.  If @var{name} is not defined, an
-error message is printed, and the expansion is void.
+Results in a call to the macro @var{name}, which is passed the rest of
+the arguments @var{args}.  If @var{name} is not defined, the expansion
+is void, and the @samp{d} debug level controls whether a warning is
+issued (@pxref{Debug Levels}).
 
 The macro @code{indir} is recognized only with parameters.
 @end deffn
@@ -2593,6 +2637,10 @@ Indir
 indir(`f', undefine(`f'))
 @error{}m4:stdin:4: Warning: indir: undefined macro `f'
 @result{}
+debugmode(`-d')
address@hidden
+indir(`f')
address@hidden
 @end example
 
 When handed the result of @code{defn} (@pxref{Defn}) as one of its
@@ -2643,7 +2691,8 @@ Builtin
 @deffn Builtin builtin (@var{name}, @address@hidden)
 Results in a call to the builtin @var{name}, which is passed the
 rest of the arguments @var{args}.  If @var{name} does not name a
-builtin, an error message is printed, and the expansion is void.
+builtin, the expansion is void, and the @samp{d} debug level controls
+whether a warning is issued (@pxref{Debug Levels}).
 
 The macro @code{builtin} is recognized only with parameters.
 @end deffn
@@ -2697,6 +2746,10 @@ Builtin
 @result{}
 m4_indir(`m4_divnum')
 @result{}0
+m4_debugmode(`-d')
address@hidden
+m4_builtin(`m4_divnum')
address@hidden
 @end example
 
 Note that @code{indir} and @code{builtin} can be used to invoke builtins
@@ -3690,7 +3743,8 @@ Dumpdef
 it displays the definitions of all known names, otherwise it displays
 the definitions of each @var{name} given.  The output is printed to the
 current debug file (usually standard error), and is sorted by name.  If
-an unknown name is encountered, a warning is printed.
+a @var{name} is undefined, the @samp{d} debug level controls whether a
+warning is issued (@pxref{Debug Levels}).
 
 The expansion of @code{dumpdef} is void.
 @end deffn
@@ -3722,6 +3776,10 @@ Dumpdef
 f(popdef(`f')dumpdef(`f'))
 @error{}m4:stdin:3: Warning: dumpdef: undefined macro `f'
 @result{}f1
+debugmode(`-d')
address@hidden
+dumpdef(`f')
address@hidden
 @end example
 
 @xref{Debug Levels}, for information on controlling the details of the
@@ -3966,6 +4024,18 @@ Debug Levels
 only one line is printed, after all arguments are collected and the
 expansion determined.  This is often used with the @samp{x} flag.
 
address@hidden d
+Output a warning on any attempt to dereference an undefined macro via
address@hidden, @code{defn}, @code{dumpdef}, @code{indir},
address@hidden, or @code{undefine}.  Note that @code{indef},
address@hidden, and @code{traceoff} do not dereference undefined macros.
+Like any other warning, the warnings enabled by this flag go to standard
+error regardless of the current @code{debugfile} setting, and will
+change exit status if the command line option @option{--fatal-warnings}
+was specified.  This flag is useful in diagnosing spelling mistakes in
+macro names.  It is enabled by default when neither @option{--debug} nor
address@hidden are specified on the command line.
+
 @item e
 In trace output, show the expansion of each macro call, if it is not
 void.  This applies to all macro calls if the @samp{t} flag is used,
@@ -4012,7 +4082,7 @@ Debug Levels
 @end table
 
 If no flags are specified with the @option{-d} option, the default is
address@hidden  The examples throughout this manual assume the default
address@hidden  The examples throughout this manual assume the default
 flags.
 
 @cindex @acronym{GNU} extensions
@@ -4024,8 +4094,8 @@ Debug Levels
 As special cases, if the argument starts with a @samp{+}, the flags are
 added to the current debug flags, and if it starts with a @samp{-}, they
 are removed.  If no argument is present, all debugging flags are cleared
-(as if no @option{-d} was given), and with an empty argument the flags
-are reset to the default of @samp{aeq}.
+(as if by @samp{-V}), and with an empty argument the flags are reset to
+the default of @samp{+adeq}.
 
 The expansion of @code{debugmode} is void.
 @end deffn
diff --git a/src/builtin.c b/src/builtin.c
index 34387b9..a4e5bee 100644
--- a/src/builtin.c
+++ b/src/builtin.c
@@ -724,7 +724,8 @@ m4_undefine (struct obstack *obs, int argc, macro_arguments 
*argv)
   for (i = 1; i < argc; i++)
     if (arg_type (argv, i) != TOKEN_TEXT)
       m4_warn (0, me, _("invalid macro name ignored"));
-    else if (!lookup_symbol (ARG (i), ARG_LEN (i), SYMBOL_DELETE))
+    else if (!lookup_symbol (ARG (i), ARG_LEN (i), SYMBOL_DELETE)
+            && (debug_level & DEBUG_TRACE_DEREF))
       m4_warn (0, me, _("undefined macro %s"),
               quotearg_style_mem (locale_quoting_style, ARG (i),
                                   ARG_LEN (i)));
@@ -746,7 +747,8 @@ m4_popdef (struct obstack *obs, int argc, macro_arguments 
*argv)
   for (i = 1; i < argc; i++)
     if (arg_type (argv, i) != TOKEN_TEXT)
       m4_warn (0, me, _("invalid macro name ignored"));
-    else if (!lookup_symbol (ARG (i), ARG_LEN (i), SYMBOL_POPDEF))
+    else if (!lookup_symbol (ARG (i), ARG_LEN (i), SYMBOL_POPDEF)
+            && (debug_level & DEBUG_TRACE_DEREF))
       m4_warn (0, me, _("undefined macro %s"),
               quotearg_style_mem (locale_quoting_style, ARG (i),
                                   ARG_LEN (i)));
@@ -896,7 +898,7 @@ m4_dumpdef (struct obstack *obs, int argc, macro_arguments 
*argv)
          s = lookup_symbol (ARG (i), ARG_LEN (i), SYMBOL_LOOKUP);
          if (s != NULL && SYMBOL_TYPE (s) != TOKEN_VOID)
            dump_symbol (s, &data);
-         else
+         else if (debug_level & DEBUG_TRACE_DEREF)
            m4_warn (0, me, _("undefined macro %s"),
                     quotearg_style_mem (locale_quoting_style, ARG (i),
                                         ARG_LEN (i)));
@@ -970,8 +972,11 @@ m4_builtin (struct obstack *obs, int argc, macro_arguments 
*argv)
   name = ARG (1);
   bp = find_builtin_by_name (name);
   if (bp->func == m4_placeholder)
-    m4_warn (0, me, _("undefined builtin %s"),
-            quotearg_style_mem (locale_quoting_style, name, ARG_LEN (1)));
+    {
+      if (debug_level & DEBUG_TRACE_DEREF)
+       m4_warn (0, me, _("undefined builtin %s"),
+                quotearg_style_mem (locale_quoting_style, name, ARG_LEN (1)));
+    }
   else
     {
       macro_arguments *new_argv = make_argv_ref (argv, name, ARG_LEN (1),
@@ -1007,8 +1012,11 @@ m4_indir (struct obstack *obs, int argc, macro_arguments 
*argv)
   len = ARG_LEN (1);
   s = lookup_symbol (name, len, SYMBOL_LOOKUP);
   if (s == NULL || SYMBOL_TYPE (s) == TOKEN_VOID)
-    m4_warn (0, me, _("undefined macro %s"),
-            quotearg_style_mem (locale_quoting_style, name, len));
+    {
+      if (debug_level & DEBUG_TRACE_DEREF)
+       m4_warn (0, me, _("undefined macro %s"),
+                quotearg_style_mem (locale_quoting_style, name, len));
+    }
   else
     {
       macro_arguments *new_argv = make_argv_ref (argv, name, len,
@@ -1046,9 +1054,10 @@ m4_defn (struct obstack *obs, int argc, macro_arguments 
*argv)
       s = lookup_symbol (ARG (i), ARG_LEN (i), SYMBOL_LOOKUP);
       if (s == NULL || SYMBOL_TYPE (s) == TOKEN_VOID)
        {
-         m4_warn (0, me, _("undefined macro %s"),
-                  quotearg_style_mem (locale_quoting_style, ARG (i),
-                                      ARG_LEN (i)));
+         if (debug_level & DEBUG_TRACE_DEREF)
+           m4_warn (0, me, _("undefined macro %s"),
+                    quotearg_style_mem (locale_quoting_style, ARG (i),
+                                        ARG_LEN (i)));
          continue;
        }
 
diff --git a/src/debug.c b/src/debug.c
index 579960b..babaf87 100644
--- a/src/debug.c
+++ b/src/debug.c
@@ -105,6 +105,10 @@ debug_decode (const char *opts)
              level |= DEBUG_TRACE_CALLID;
              break;
 
+           case 'd':
+             level |= DEBUG_TRACE_DEREF;
+             break;
+
            case 'V':
              level |= DEBUG_TRACE_VERBOSE;
              break;
diff --git a/src/m4.c b/src/m4.c
index 22586fc..93beb40 100644
--- a/src/m4.c
+++ b/src/m4.c
@@ -36,7 +36,7 @@ static void usage (int);
 int sync_output = 0;
 
 /* Debug (-d[flags]).  */
-int debug_level = 0;
+int debug_level = DEBUG_TRACE_DEREF;
 
 /* Disable GNU extensions (-G).  */
 int no_gnu_extensions = 0;
@@ -257,7 +257,7 @@ Frozen state files:\n\
       fputs (_("\
 Debugging:\n\
   -d, --debug[=[-|+]FLAGS], --debugmode[=[-|+]FLAGS]\n\
-                               set debug level (no FLAGS implies `+aeq')\n\
+                               set debug level (no FLAGS implies `+adeq')\n\
       --debugfile=FILE         redirect debug and trace output\n\
   -l, --arglength=NUM          restrict macro tracing size\n\
   -t, --trace=NAME             trace NAME when it is defined\n\
@@ -267,6 +267,7 @@ Debugging:\n\
 FLAGS is any of:\n\
   a   show actual arguments in trace\n\
   c   show collection line in trace\n\
+  d   warn when dereferencing undefined macros (default on unless -E)\n\
   e   show expansion in trace\n\
   f   include current input file name in trace and debug\n\
   i   show changes in input files in debug\n\
@@ -479,6 +480,7 @@ main (int argc, char *const *argv, char *const *envp)
        break;
 
       case 'E':
+       debug_decode ("-d");
        if (!fatal_warnings)
          fatal_warnings = true;
        else
diff --git a/src/m4.h b/src/m4.h
index 8da7d3c..27c0fa7 100644
--- a/src/m4.h
+++ b/src/m4.h
@@ -192,11 +192,13 @@ extern FILE *debug;
 #define DEBUG_TRACE_INPUT 0x100
 /* x: add call id to trace output */
 #define DEBUG_TRACE_CALLID 0x200
+/* d: warn if dereferencing undefined macro */
+#define DEBUG_TRACE_DEREF 0x400
 
 /* V: very verbose --  print everything */
-#define DEBUG_TRACE_VERBOSE 0x3FF
-/* default flags -- equiv: aeq */
-#define DEBUG_TRACE_DEFAULT 0x007
+#define DEBUG_TRACE_VERBOSE 0x7FF
+/* default flags -- equiv: adeq */
+#define DEBUG_TRACE_DEFAULT 0x407
 
 void debug_init (void);
 int debug_decode (const char *);
-- 
1.6.0


reply via email to

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