summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Blake <ebb9@byu.net>2008-08-23 22:51:03 -0600
committerEric Blake <ebb9@byu.net>2008-08-23 22:51:03 -0600
commitc70fbd65dd345fa4c96b9ca631d70424c644cbc7 (patch)
tree52d9ad42c2d31082cd1ad37ef2dbac7e9a558723
parent8eb70fbb1969717d7cfefea93ee9f117fd3933cd (diff)
downloadm4-c70fbd65dd345fa4c96b9ca631d70424c644cbc7.tar.gz
Allow debugmode control over whether defn(undef) warns.
* ltdl/m4/gnulib-cache.m4: Import verify module. * m4/m4module.h (M4_DEBUG_TRACE_DEREF, M4_DEBUG_TRACE_INITIAL): New values. (M4_DEBUG_TRACE_VERBOSE, M4_DEBUG_TRACE_DEFAULT): Adjust. * m4/m4.c (m4_create): Start with debugmode = d. * src/main.c (usage): Mention this. (main): Let -E impact debug mode. * m4/utility.c (m4_symbol_value_lookup): Squelch undefined warning if flag is clear. * modules/gnu.c (builtin, inder): Likewise. * m4/debug.c (m4_debug_decode): Parse new mode. * src/freeze.c (produce_debugmode_state): Accomodate new mode. * doc/m4.texinfo (Debugging options): Mention change in the default behavior. (Debugmode): Mention new flag d. (Operation modes): Mention interaction with -E. (Undefine, Defn, Pushdef, Indir, Builtin, Dumpdef): Document and test its effect. * tests/options.at (--debugmode): Update tests. * tests/freeze.at (reloading debugmode): Likewise. * 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 <ebb9@byu.net>
-rw-r--r--ChangeLog27
-rw-r--r--NEWS52
-rw-r--r--doc/m4.texinfo194
-rw-r--r--ltdl/m4/gnulib-cache.m43
-rw-r--r--m4/debug.c4
-rw-r--r--m4/m4.c1
-rw-r--r--m4/m4module.h14
-rw-r--r--m4/utility.c3
-rw-r--r--modules/gnu.c22
-rw-r--r--src/freeze.c7
-rw-r--r--src/main.c4
-rw-r--r--tests/freeze.at2
-rw-r--r--tests/options.at2
13 files changed, 241 insertions, 94 deletions
diff --git a/ChangeLog b/ChangeLog
index f21cbd8c..9fe67363 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,30 @@
+2008-08-23 Eric Blake <ebb9@byu.net>
+
+ Allow debugmode control over whether defn(undef) warns.
+ * ltdl/m4/gnulib-cache.m4: Import verify module.
+ * m4/m4module.h (M4_DEBUG_TRACE_DEREF, M4_DEBUG_TRACE_INITIAL):
+ New values.
+ (M4_DEBUG_TRACE_VERBOSE, M4_DEBUG_TRACE_DEFAULT): Adjust.
+ * m4/m4.c (m4_create): Start with debugmode = d.
+ * src/main.c (usage): Mention this.
+ (main): Let -E impact debug mode.
+ * m4/utility.c (m4_symbol_value_lookup): Squelch undefined warning
+ if flag is clear.
+ * modules/gnu.c (builtin, inder): Likewise.
+ * m4/debug.c (m4_debug_decode): Parse new mode.
+ * src/freeze.c (produce_debugmode_state): Accomodate new mode.
+ * doc/m4.texinfo (Debugging options): Mention change in the
+ default behavior.
+ (Debugmode): Mention new flag d.
+ (Operation modes): Mention interaction with -E.
+ (Undefine, Defn, Pushdef, Indir, Builtin, Dumpdef): Document and
+ test its effect.
+ * tests/options.at (--debugmode): Update tests.
+ * tests/freeze.at (reloading debugmode): Likewise.
+ * 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 <ebb9@byu.net>
Improve --debugmode behavior.
diff --git a/NEWS b/NEWS
index e8b08d07..4420c83e 100644
--- a/NEWS
+++ b/NEWS
@@ -29,21 +29,12 @@ promoted to 2.0.
*** New `-B'/`--prepend-include' command-line option allows prepending to
the include path, rather than always searching `.' first.
-*** 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'. Also, the
- position of `-d' with respect to files on the command line is now
- significant.
-
*** New `--debuglen' command-line option matches the spelling of a new
macro, and the old spelling `--arglength' now issues a warning that it
might be withdrawn in the future.
-*** New `-g'/`--gnu' command-line option overrides `-G'/`--traditional',
- allowing the GNU module to be selected even when POSIXLY_CORRECT.
+*** The `-g'/`--gnu' command-line option is now required to allow all GNU
+ extensions when POSIXLY_CORRECT is set.
*** The `-H'/`--hashsize' command-line options, which were made no-ops in
a previous beta, now issue a deprecation warning.
@@ -253,9 +244,42 @@ promoted to 2.0.
then apply this patch:
http://git.sv.gnu.org/gitweb/?p=autoconf.git;a=commitdiff;h=56d42fa71
-** The `defn' builtin now warns when operating on an undefined macro name.
- To simulate 1.4.x behavior, use:
- pushdef(`defn', `ifdef(`$1', `builtin(`defn', `$1')')')
+** 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'. 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
+ behavior; but a future release of M4 will behave as though --traditional
+ is implied if POSIXLY_CORRECT is set (this future change is necessary,
+ because in the current release, there is no way to disable GNU
+ extensions that conflict with POSIX without the use of a non-POSIX
+ command-line argument). Clients of M4 that want to use GNU extensions,
+ even when POSIXLY_CORRECT is set, should start using the -g command-line
+ argument, even though it is currently a no-op if -G did not appear
+ earlier in the command line, so that the client will not break in the
+ face of an upgraded m4 and a POSIXLY_CORRECT execution environment.
+
+** A new predefined text macro, `__m4_version__', expands to the unquoted
+ version number of M4, if GNU extensions are enabled. While you should
+ generally favor feature tests over version number checks, this macro can
+ be used, via `defn', to determine whether the version of m4 processing
+ your file is adequate.
+
+** 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 0b84d089..54ecf8f3 100644
--- a/doc/m4.texinfo
+++ b/doc/m4.texinfo
@@ -644,6 +644,57 @@ a warning is issued. The introduction of behavior levels is new to M4
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.
+
+@example
+$ @kbd{m4}
+defn(`oops')
+@error{}m4:stdin:1: Warning: defn: undefined macro `oops'
+@result{}
+^D
+@end example
+
+@comment ignore
+@example
+$ @kbd{echo $?}
+@result{}0
+@end example
+
+@comment options: -E
+@example
+$ @kbd{m4 -E}
+defn(`oops')
+@result{}
+^D
+@end example
+
+@comment ignore
+@example
+$ @kbd{echo $?}
+@result{}0
+@end example
+
+@comment options: -E -d
+@comment status: 1
+@example
+$ @kbd{m4 -E -d}
+defn(`oops')
+@error{}m4:stdin:1: Warning: defn: undefined macro `oops'
+@result{}
+^D
+@end example
+
+@comment ignore
+@example
+$ @kbd{echo $?}
+@result{}1
+@end example
+
@item -i
@itemx --interactive
@itemx -e
@@ -944,17 +995,20 @@ 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{Debugmode}, for more details on the format and
meaning of @var{FLAGS}. If omitted, @var{FLAGS} defaults to
-@samp{+aeq}. If the option occurs multiple times, @var{FLAGS} starting
+@samp{+adeq}. 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
+@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
@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
@@ -2142,7 +2196,8 @@ A macro definition can be removed with @code{undefine}:
@deffn {Builtin (m4)} undefine (@var{name}@dots{})
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{Debugmode}).
The expansion of @code{undefine} is void.
The macro @code{undefine} is recognized only with parameters.
@@ -2177,30 +2232,19 @@ f(`bye')
@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
-@option{-Q} (@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{Debugmode}) or the command line option
+@option{-d} (@option{--debugmode}, @pxref{Debugging options, , Invoking
+m4}).
@example
-define(`a', `1')
-@result{}
-undefine
-@result{}undefine
-undefine(`a', `a')
-@error{}m4:stdin:3: Warning: undefine: undefined macro `a'
-@result{}
-define(`a', `1')
-@result{}
-pushdef(`undefine', `ifelse(`$#', `0', ``undefine'', `_$0($@@)')')
+$ @kbd{m4}
+undefine(`a')
+@error{}m4:stdin:1: Warning: undefine: undefined macro `a'
@result{}
-define(`_undefine', `ifdef(`$1', `builtin(`undefine',
- `$1')')ifelse(`$#', `1', `', `$0(shift($@@))')')
+debugmode(`-d')
@result{}
-undefine
-@result{}undefine
-undefine(`a', `a')
+undefine(`a')
@result{}
@end example
@@ -2217,7 +2261,8 @@ the builtin @code{defn}:
@deffn {Builtin (m4)} defn (@var{name}@dots{})
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{Debugmode}).
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
@@ -2386,9 +2431,11 @@ bar
@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{Debugmode}) or the command line option
+@option{-d} (@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.
@@ -2398,6 +2445,10 @@ $ @kbd{m4 -d}
defn(`foo')
@error{}m4:stdin:1: Warning: defn: undefined macro `foo'
@result{}
+debugmode(`-d')
+@result{}
+defn(`foo')
+@result{}
define(`a', `A')define(`AA', `b')
@result{}
traceon(`defn', `define')
@@ -2407,25 +2458,25 @@ defn(`a', `divnum', `a')
@result{}AA
define(`mydivnum', defn(`divnum', `divnum'))mydivnum
@error{}m4trace: -2- defn(`divnum', `divnum') -> `<divnum><divnum>'
-@error{}m4:stdin:5: Warning: define: cannot concatenate builtins
+@error{}m4: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
-@error{}m4:stdin:7: Warning: define: cannot concatenate builtins
+@error{}m4:stdin:9: Warning: define: cannot concatenate builtins
@result{}
define(`mydivnum', defn(`divnum')`a')mydivnum
-@error{}m4:stdin:8: Warning: define: cannot concatenate builtins
+@error{}m4:stdin:10: Warning: define: cannot concatenate builtins
@result{}A
define(`mydivnum', `a'defn(`divnum'))mydivnum
-@error{}m4:stdin:9: Warning: define: cannot concatenate builtins
+@error{}m4:stdin:11: Warning: define: cannot concatenate builtins
@result{}A
define(`q', ``$@@'')
@result{}
define(`foo', q(`a', defn(`divnum')))foo
-@error{}m4:stdin:11: Warning: define: cannot concatenate builtins
+@error{}m4:stdin:13: Warning: define: cannot concatenate builtins
@result{}a,
ifdef(`foo', `yes', `no')
@result{}yes
@@ -2456,7 +2507,8 @@ exactly like @code{define}.
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{Debugmode}).
The expansion of both @code{pushdef} and @code{popdef} is void.
The macros @code{pushdef} and @code{popdef} are recognized only with
@@ -2529,11 +2581,10 @@ revealing the former definition.
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
-@option{-Q} (@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{Debugmode}) or the command line option
+@option{-d} (@option{--debugmode}, @pxref{Debugging options, , Invoking
+m4}).
@example
define(`a', `1')
@@ -2543,16 +2594,9 @@ popdef
popdef(`a', `a')
@error{}m4:stdin:3: Warning: popdef: undefined macro `a'
@result{}
-define(`a', `1')
-@result{}
-pushdef(`popdef', `ifelse(`$#', `0', ``popdef'', `_$0($@@)')')
-@result{}
-define(`_popdef', `ifdef(`$1', `builtin(`popdef',
- `$1')')ifelse(`$#', `1', `', `$0(shift($@@))')')
+debugmode(`-d')
@result{}
-popdef
-@result{}popdef
-popdef(`a', `a')
+popdef(`a')
@result{}
@end example
@@ -2683,9 +2727,10 @@ popdef(`bar')bar
Any macro can be called indirectly with @code{indir}:
@deffn {Builtin (gnu)} indir (@var{name}, @ovar{args@dots{}})
-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{Debugmode}).
The macro @code{indir} is recognized only with parameters.
@end deffn
@@ -2724,6 +2769,10 @@ indir(`f', define(`f', `3'))
indir(`f', undefine(`f'))
@error{}m4:stdin:4: Warning: indir: undefined macro `f'
@result{}
+debugmode(`-d')
+@result{}
+indir(`f')
+@result{}
@end example
When handed the result of @code{defn} (@pxref{Defn}) as one of its
@@ -2775,7 +2824,8 @@ Builtin macros can be called indirectly with @code{builtin}:
@deffnx {Builtin (gnu)} builtin (@code{defn(`builtin')}, @var{name1})
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, a warning 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{Debugmode}).
As a special case, if @var{name} is exactly the special token
representing the @code{builtin} macro, as obtained by @code{defn}
@@ -2835,6 +2885,10 @@ m4_indir(`divnum')
@result{}
m4_indir(`m4_divnum')
@result{}0
+m4_debugmode(`-d')
+@result{}
+m4_builtin(`m4_divnum')
+@result{}
@end example
Note that @code{indir} and @code{builtin} can be used to invoke builtins
@@ -3794,14 +3848,15 @@ Fortunately, there is support for macro debugging in @code{m4}.
If you want to see what a name expands into, you can use the builtin
@code{dumpdef}:
-@deffn {Builtin (m4)} dumpdef (@ovar{names@dots{}})
+@deffn {Builtin (m4)} dumpdef (@ovar{name@dots{}})
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
+the definitions of each @var{name} given. The output is printed
directly to standard error, independently of the @option{--debugfile}
option (@pxref{Debugging options, , Invoking m4}), or @code{debugfile} macro.
-The output is sorted by name. If an unknown name is encountered, a
-warning is printed.
+The output is sorted by name. If a @var{name} is undefined, the
+@samp{d} debug level controls whether a warning is issued
+(@pxref{Debugmode}).
The expansion of @code{dumpdef} is void.
@end deffn
@@ -3833,6 +3888,10 @@ f(popdef(`f')dumpdef(`f'))
f(popdef(`f')dumpdef(`f'))
@error{}m4:stdin:3: Warning: dumpdef: undefined macro `f'
@result{}f1
+debugmode(`-d')
+@result{}
+dumpdef(`-f')
+@result{}
@end example
@xref{Debugmode}, for information on how the @samp{m}, @samp{q}, and
@@ -4171,6 +4230,19 @@ the expansion determined. The definition is subject to length
truncation specified by @code{debuglen} (@pxref{Debuglen}). This is
often used with the @samp{x} flag.
+@item d
+Output a warning on any attempt to dereference an undefined macro via
+@code{builtin}, @code{defn}, @code{dumpdef}, @code{indir},
+@code{popdef}, or @code{undefine}. Note that @code{indef},
+@code{m4symbols},
+@code{traceon}, 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
+@option{--fatal-warnings} are specified on the command line.
+
@item e
In trace output, show the expansion of each macro call. The expansion
is subject to length truncation specified by @code{debuglen}
@@ -4236,7 +4308,7 @@ the previous setting.
@comment currently enabled?
If no flags are specified with the @option{--debug} option, the default is
-@samp{+aeq}. Many examples in this manual show their output using
+@samp{+adeq}. Many examples in this manual show their output using
default flags.
@cindex @acronym{GNU} extensions
@@ -4248,7 +4320,7 @@ The argument @var{flags} should be a subset of the letters listed above.
If no argument is present, all debugging flags are cleared (as if
@var{flags} were an explicit @samp{-V}). With an empty argument, the
most common flags are enabled (as if @var{flags} were an explicit
-@samp{+aeq}). If an unknown flag is encountered, an error is issued.
+@samp{+adeq}). If an unknown flag is encountered, an error is issued.
The expansion of @code{debugmode} is void.
@end deffn
@@ -4260,7 +4332,7 @@ define(`foo', `FOO$1')
@result{}
traceon(`foo', `divnum')
@result{}
-debugmode()dnl same as debugmode(`+aeq')
+debugmode()dnl same as debugmode(`+adeq')
foo
@error{}m4trace: -1- foo -> `FOO'
@result{}FOO
diff --git a/ltdl/m4/gnulib-cache.m4 b/ltdl/m4/gnulib-cache.m4
index da4eef3f..f61b8d7d 100644
--- a/ltdl/m4/gnulib-cache.m4
+++ b/ltdl/m4/gnulib-cache.m4
@@ -15,7 +15,7 @@
# Specification in the form of a command-line invocation:
-# gnulib-tool --import --dir=. --local-dir=local --lib=libgnu --source-base=gnu --m4-base=ltdl/m4 --doc-base=doc --aux-dir=build-aux --with-tests --libtool --macro-prefix=M4 assert autobuild avltree-oset binary-io clean-temp cloexec close-stream closein config-h configmake dirname error exit fdl fflush filenamecat flexmember fopen-safer fseeko gendocs gettext git-version-gen gnumakefile gnupload gpl-3.0 intprops memmem mkstemp obstack obstack-printf-posix progname propername quote regex regexprops-generic sprintf-posix stdbool stdlib-safer strnlen strtod strtol tempname unlocked-io vasnprintf-posix verror xalloc xalloc-die xmemdup0 xprintf-posix xstrndup xvasprintf-posix
+# gnulib-tool --import --dir=. --local-dir=local --lib=libgnu --source-base=gnu --m4-base=ltdl/m4 --doc-base=doc --aux-dir=build-aux --with-tests --libtool --macro-prefix=M4 assert autobuild avltree-oset binary-io clean-temp cloexec close-stream closein config-h configmake dirname error exit fdl fflush filenamecat flexmember fopen-safer fseeko gendocs gettext git-version-gen gnumakefile gnupload gpl-3.0 intprops memmem mkstemp obstack obstack-printf-posix progname propername quote regex regexprops-generic sprintf-posix stdbool stdlib-safer strnlen strtod strtol tempname unlocked-io vasnprintf-posix verify verror xalloc xalloc-die xmemdup0 xprintf-posix xstrndup xvasprintf-posix
# Specification in the form of a few gnulib-tool.m4 macro invocations:
gl_LOCAL_DIR([local])
@@ -64,6 +64,7 @@ gl_MODULES([
tempname
unlocked-io
vasnprintf-posix
+ verify
verror
xalloc
xalloc-die
diff --git a/m4/debug.c b/m4/debug.c
index d9efc8b8..f4005ebf 100644
--- a/m4/debug.c
+++ b/m4/debug.c
@@ -97,6 +97,10 @@ m4_debug_decode (m4 *context, const char *opts)
level |= M4_DEBUG_TRACE_STACK;
break;
+ case 'd':
+ level |= M4_DEBUG_TRACE_DEREF;
+ break;
+
case 'V':
level |= M4_DEBUG_TRACE_VERBOSE;
break;
diff --git a/m4/m4.c b/m4/m4.c
index 1fc1f113..31d977f2 100644
--- a/m4/m4.c
+++ b/m4/m4.c
@@ -37,6 +37,7 @@ m4_create (void)
obstack_init (&context->trace_messages);
context->nesting_limit = DEFAULT_NESTING_LIMIT;
+ context->debug_level = M4_DEBUG_TRACE_INITIAL;
context->max_debug_arg_length = SIZE_MAX;
context->search_path =
diff --git a/m4/m4module.h b/m4/m4module.h
index 6c0587b9..1f3b7bcf 100644
--- a/m4/m4module.h
+++ b/m4/m4module.h
@@ -402,14 +402,20 @@ enum {
M4_DEBUG_TRACE_MODULE = (1 << 10),
/* s: trace pushdef stacks */
M4_DEBUG_TRACE_STACK = (1 << 11),
+ /* d: warn if dereferencing undefined macro */
+ M4_DEBUG_TRACE_DEREF = (1 << 12),
/* V: very verbose -- print everything */
- M4_DEBUG_TRACE_VERBOSE = ((1 << 12) - 1)
+ M4_DEBUG_TRACE_VERBOSE = ((1 << 13) - 1)
};
-/* default flags -- equiv: aeq */
-#define M4_DEBUG_TRACE_DEFAULT \
- (M4_DEBUG_TRACE_ARGS | M4_DEBUG_TRACE_EXPANSION | M4_DEBUG_TRACE_QUOTE)
+/* initial flags, used if no -d or -E -- equiv: d */
+#define M4_DEBUG_TRACE_INITIAL M4_DEBUG_TRACE_DEREF
+
+/* default flags, used by debugmode() -- equiv: +adeq */
+#define M4_DEBUG_TRACE_DEFAULT \
+ (M4_DEBUG_TRACE_ARGS | M4_DEBUG_TRACE_EXPANSION \
+ | M4_DEBUG_TRACE_QUOTE | M4_DEBUG_TRACE_DEREF)
#define m4_is_debug_bit(C,B) ((m4_get_debug_level_opt (C) & (B)) != 0)
diff --git a/m4/utility.c b/m4/utility.c
index 596c6215..31c17051 100644
--- a/m4/utility.c
+++ b/m4/utility.c
@@ -134,7 +134,8 @@ m4_symbol_value_lookup (m4 *context, m4_macro_args *argv, size_t i,
const char *name = M4ARG (i);
size_t len = M4ARGLEN (i);
result = m4_symbol_lookup (M4SYMTAB, name, len);
- if (must_exist && !result)
+ if (must_exist && !result
+ && m4_is_debug_bit (context, M4_DEBUG_TRACE_DEREF))
m4_warn (context, 0, argv->info, _("undefined macro %s"),
quotearg_style_mem (locale_quoting_style, name, len));
}
diff --git a/modules/gnu.c b/modules/gnu.c
index 2e960305..74e1c4a7 100644
--- a/modules/gnu.c
+++ b/modules/gnu.c
@@ -424,14 +424,14 @@ M4BUILTIN_HANDLER (builtin)
len = M4ARGLEN (2);
if (len == strlen (name))
value = m4_builtin_find_by_name (NULL, name);
- if (value == NULL)
- m4_warn (context, 0, me, _("undefined builtin %s"),
- quotearg_style_mem (locale_quoting_style, name, len));
- else
+ if (value)
{
m4_push_builtin (context, obs, value);
free (value);
}
+ else if (m4_is_debug_bit (context, M4_DEBUG_TRACE_DEREF))
+ m4_warn (context, 0, me, _("undefined builtin %s"),
+ quotearg_style_mem (locale_quoting_style, name, len));
}
else
m4_warn (context, 0, me, _("invalid macro name ignored"));
@@ -443,8 +443,11 @@ M4BUILTIN_HANDLER (builtin)
if (len == strlen (name))
value = m4_builtin_find_by_name (NULL, name);
if (value == NULL)
- m4_warn (context, 0, me, _("undefined builtin %s"),
- quotearg_style_mem (locale_quoting_style, name, len));
+ {
+ if (m4_is_debug_bit (context, M4_DEBUG_TRACE_DEREF))
+ m4_warn (context, 0, me, _("undefined builtin %s"),
+ quotearg_style_mem (locale_quoting_style, name, len));
+ }
else
{
const m4_builtin *bp = m4_get_symbol_value_builtin (value);
@@ -692,8 +695,11 @@ M4BUILTIN_HANDLER (indir)
m4_symbol *symbol = m4_symbol_lookup (M4SYMTAB, name, len);
if (symbol == NULL)
- m4_warn (context, 0, me, _("undefined macro %s"),
- quotearg_style_mem (locale_quoting_style, name, len));
+ {
+ if (m4_is_debug_bit (context, M4_DEBUG_TRACE_DEREF))
+ m4_warn (context, 0, me, _("undefined macro %s"),
+ quotearg_style_mem (locale_quoting_style, name, len));
+ }
else
{
m4_macro_args *new_argv;
diff --git a/src/freeze.c b/src/freeze.c
index 4d3a2b0f..44400f3f 100644
--- a/src/freeze.c
+++ b/src/freeze.c
@@ -27,6 +27,7 @@
#include "binary-io.h"
#include "close-stream.h"
#include "quotearg.h"
+#include "verify.h"
#include "xmemdup0.h"
static void produce_mem_dump (FILE *, const char *, size_t);
@@ -110,9 +111,9 @@ static void
produce_debugmode_state (FILE *file, int flags)
{
/* This code tracks the number of bits in M4_DEBUG_TRACE_VERBOSE. */
- char str[13];
+ char str[14];
int offset = 0;
- assert ((1 << (sizeof str - 1)) - 1 == M4_DEBUG_TRACE_VERBOSE);
+ verify ((1 << (sizeof str - 1)) - 1 == M4_DEBUG_TRACE_VERBOSE);
if (flags & M4_DEBUG_TRACE_ARGS)
str[offset++] = 'a';
if (flags & M4_DEBUG_TRACE_EXPANSION)
@@ -137,6 +138,8 @@ produce_debugmode_state (FILE *file, int flags)
str[offset++] = 'm';
if (flags & M4_DEBUG_TRACE_STACK)
str[offset++] = 's';
+ if (flags & M4_DEBUG_TRACE_DEREF)
+ str[offset++] = 'd';
str[offset] = '\0';
if (offset)
xfprintf (file, "d%d\n%s\n", offset, str);
diff --git a/src/main.c b/src/main.c
index 341a9e81..ee72381a 100644
--- a/src/main.c
+++ b/src/main.c
@@ -149,7 +149,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, --debuglen=NUM restrict macro tracing size\n\
-t, --trace=NAME, --traceon=NAME\n\
@@ -161,6 +161,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\
@@ -459,6 +460,7 @@ main (int argc, char *const *argv, char *const *envp)
break;
case 'E':
+ m4_debug_decode (context, "-d");
if (m4_get_fatal_warnings_opt (context))
m4_set_warnings_exit_opt (context, true);
else
diff --git a/tests/freeze.at b/tests/freeze.at
index 995c4a68..9b8c9463 100644
--- a/tests/freeze.at
+++ b/tests/freeze.at
@@ -364,7 +364,7 @@ AT_CHECK_M4([-R frozen.m4f unfrozen.m4], [0], [[1
]], [[m4trace:unfrozen.m4:1: -1- len
]])
-dnl With plain -d after -R, add +aeq to the frozen file
+dnl With plain -d after -R, add +adeq to the frozen file
AT_CHECK_M4([-R frozen.m4f -d unfrozen.m4], [0], [[1
]], [[m4trace:unfrozen.m4:1: -1- len(`a') -> `1'
]], [], [ ])
diff --git a/tests/options.at b/tests/options.at
index e220c0a4..904cc7d6 100644
--- a/tests/options.at
+++ b/tests/options.at
@@ -386,7 +386,7 @@ AT_DATA([[nested]],
')dnl
]])
-dnl AT_CHECK_M4 starts life with -d. Make sure it looks like -d+aeq.
+dnl AT_CHECK_M4 starts life with -d. Make sure it looks like -d+adeq.
AT_CHECK_M4([-tlen in], [0], [[3
0
]], [[m4trace: -1- len(`abc') -> `3'