[Top][All Lists]
[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