diff options
author | Eric Blake <ebb9@byu.net> | 2008-08-23 22:51:03 -0600 |
---|---|---|
committer | Eric Blake <ebb9@byu.net> | 2008-08-23 22:51:03 -0600 |
commit | c70fbd65dd345fa4c96b9ca631d70424c644cbc7 (patch) | |
tree | 52d9ad42c2d31082cd1ad37ef2dbac7e9a558723 | |
parent | 8eb70fbb1969717d7cfefea93ee9f117fd3933cd (diff) | |
download | m4-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-- | ChangeLog | 27 | ||||
-rw-r--r-- | NEWS | 52 | ||||
-rw-r--r-- | doc/m4.texinfo | 194 | ||||
-rw-r--r-- | ltdl/m4/gnulib-cache.m4 | 3 | ||||
-rw-r--r-- | m4/debug.c | 4 | ||||
-rw-r--r-- | m4/m4.c | 1 | ||||
-rw-r--r-- | m4/m4module.h | 14 | ||||
-rw-r--r-- | m4/utility.c | 3 | ||||
-rw-r--r-- | modules/gnu.c | 22 | ||||
-rw-r--r-- | src/freeze.c | 7 | ||||
-rw-r--r-- | src/main.c | 4 | ||||
-rw-r--r-- | tests/freeze.at | 2 | ||||
-rw-r--r-- | tests/options.at | 2 |
13 files changed, 241 insertions, 94 deletions
@@ -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. @@ -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 @@ -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; @@ -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); @@ -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' |