m4-patches
[Top][All Lists]
Advanced

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

traceon behavior in head [was: another core dump to be fixed before 1.4.


From: Eric Blake
Subject: traceon behavior in head [was: another core dump to be fixed before 1.4.5]
Date: Sun, 17 Sep 2006 23:39:10 -0600
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.7) Gecko/20060909 Thunderbird/1.5.0.7 Mnenhy/0.7.4.666

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

According to Eric Blake on 5/31/2006 10:48 PM:
> 
> Further investigation turned up these additional differences between Solaris 
> and GNU.  I doubt any of them are show-stoppers for 1.4.5, but I will 
> probably 
> be able to fix them anyways as part of fixing John's coredump about 
> undefining 
> a symbol while it is being used in macro expansion.  Of course, a fix 
> includes 
> adding a test case in m4.texinfo, so that we don't regress in the future.
> 
> $ /usr/ccs/bin/m4
> traceon`'define(`foo',`1')foo
> Trace(0): define(foo,1)
> Trace(0): foo
> 1
> ^D
> $ m4
> traceon`'define(`foo',`1')foo
> m4trace: -1- define
> 1
> ^D
> 
> Hmm - Solaris traceon is truly global, so new definitions are traced.  But 
> GNU 
> simply marks all existing macros as traced, which ignores new definitions.
> 
> 
> $ /usr/ccs/bin/m4
> define(`foo',`1')define(`bar',`2')traceon(`foo')
> 
> foo bar
> Trace(0): foo
> 1 2
> traceon
> 
> foo bar
> Trace(0): foo
> Trace(0): bar
> 1 2
> traceoff
> Trace(0): traceoff
> 
> foo bar
> Trace(0): foo
> 1 2
> ^D
> $ m4
> define(`foo',`1')define(`bar',`2')traceon(`foo')
> 
> foo bar
> m4trace: -1- foo
> 1 2
> traceon
> 
> foo bar
> m4trace: -1- foo
> 1 m4trace: -1- bar
> 2
> traceoff
> m4trace: -1- traceoff
> 
> foo bar
> 1 2
> ^D
> 
> Hmm - Solaris global traceon is independent of the macro traceon status, so a 
> named trace remains in force regardless of the global trace status.  GNU m4 
> does not have global trace status, so named traces are lost at global 
> traceoff.
> 
> 
> $ /usr/ccs/bin/m4
> traceon(`bar')define(`bar',`1')bar
> 1
> ^D
> $ m4
> traceon(`bar')define(`bar',`1')bar
> stdin:1: m4: Undefined name bar
> 1
> ^D
> $ m4 -tbar
> traceon(`bar')define(`bar',`1')bar
> m4trace: -1- bar
> 1
> 
> Hmm - when requesting a trace by name, Solaris just ignores the request for 
> undefined macros. GNU m4 warns if the macro is not in use.  But at startup, 
> it 
> reserves a slot in the hashtable at startup for undefined names mentioned by -
> t, and the warning is avoided in that case.  Not very consistent.  When not 
> worried about matching traditional behavior, either GNU should always warn 
> about tracing an undefined macro; or better yet, always behave as though a 
> currently undefined macro can later be defined with tracing already enabled, 
> as 
> though specified by -t.  When trying to be traditional, it should just be 
> silent on unknown trace requests.
> 

Rather than just porting 1.4.x behavior to head, I decided to go more like
Solaris behavior: traceon/traceoff without arguments are now synonyms for
debugmode(+t)/debugmode(-t), and a macro is traced if either global
tracing is on or if it has been traceon'd by name with no subsequent
traceoff by name.  Thanks to the symbols macro added in 1.4o (but not
mentioned in NEWS), you can still emulate 1.4.x behavior with a little
overhead.  This simplified the code, and removed one of the maintenance
issues where we had been passing no_gnu_extensions in order to decide
whether to nuke symbols from the symbol table according to whether they
were traced or not - the code now blindly leaves a placeholder for a
traced macro, as that is permitted by POSIX, and is more useful than
Solaris' behavior of forgetting tracing when a macro is undefined.

A couple of followon patches I would like to make, based on things I
noticed in this patch.  First, the name --error-output is misleading - it
redirects trace and debug output, but does not touch error messages or
errprint.  A better name might be --debug-output (matching the already
existing short option -o), or --debugfile (to match the builtin that it
mirrors, although that name no longer contains an o for the short option
mnemonic).  Any preferences on the name?

Second, since POSIX allows dumpdef to display output in an unspecified
format, would it be worth adding a debug flag to debugmode that enhances
the dumped output to show the entire stack of pushdef'd definitions,
rather than just the topmost?

2006-09-17  Eric Blake  <address@hidden>

        * modules/m4.c (traceon, traceoff): Change to Solaris semantics,
        such that without arguments, the global trace flag is changed
        rather than walking the table of all currently-defined macros.
        (set_trace_CB): No longer needed.
        * m4/m4module.h (m4_set_symbol_name_traced): Add a parameter.
        (m4_set_symbol_traced): Delete.
        (m4_symtab_create): Nuke the nuke parameter.
        * m4/m4private.h (m4_get_symbol_value): Delete.
        * m4/symtab.c (m4_symbol_popdef): No more need for nuke_trace.
        (m4_set_symbol_name_traced): Free undefined entries that are no
        longer traced.
        (symbol_destroy_CB): Update caller.
        * m4/m4.c (m4_create): Update caller.
        * src/main.c (main): Likewise.
        (usage): Fix typo in last commit.
        * doc/m4.texinfo: Minor cleanups throughout.
        (Debugging, Dumpdef, Trace, Debug Levels, Debug Output): Merge
        more nodes from branch.
        (Trace): Document new semantics, and how to simulate the old.
        * tests/builtins.at (multiquotes): Adjust to new semantics.
        * NEWS: Update somewhat.

- --
Life is short - so eat dessert first!

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

iD8DBQFFDjD984KuGfSFAYARApzZAKCMlk+GSCo9VSHl6OAT2ZOhnVmbjwCeI8Cu
pffPCNtJZNLnntduVEm/k2A=
=oauS
-----END PGP SIGNATURE-----
Index: NEWS
===================================================================
RCS file: /sources/m4/m4/NEWS,v
retrieving revision 1.13
diff -u -p -r1.13 NEWS
--- NEWS        22 Aug 2006 16:16:47 -0000      1.13
+++ NEWS        18 Sep 2006 05:36:54 -0000
@@ -2,24 +2,42 @@ GNU m4 NEWS - History of user-visible ch
 Copyright (C) 1992, 1993, 1994, 1998, 2000, 2001, 2006 Free Software
 Foundation, Inc.
 
-Version beta 1.9a - ???, by ???
+Version beta 1.9b - ???, by ??? (CVS version 1.9a)
+
+NOTE - there are still a number of FIXMEs to resolve before this can be
+promoted to 2.0.
+
+* The build environment has been updated to modern GNU practices,
+  depending on newer features of Autoconf, Automake, Libtool, Gettext,
+  and Gnulib to be more portable to a wide variety of platforms.
 
 * If the POSIXLY_CORRECT environment variable is set, m4 now disables
   GNU extensions that are incompatible with POSIX.
+  - FIXME: POSIXLY_CORRECT should imply -G, rather than being a separate
+  conditional in the code.  And we should have -g to override the
+  environment.  Also, the list of features incompatible with POSIX is
+  still larger than what either flag currently affects.
 
 * POSIXLY_CORRECT and `m4 --traditional' now makes the `define' builtin
-  replace all `pushdef'ed values of a macro, as POSIX requires.
+  replace all `pushdef'ed values of a macro.
+  - FIXME: The Austin group clarified that this was never a POSIX
+  requirement; consider reverting this change.
 
 * The `defn' builtin now allows any number of arguments, as POSIX requires.
+  - FIXME: This still doesn't work with concatenating builtins with text.
 
-* The '$' syntax class is now enabled.  See the info docs for examples.
+* The '$' syntax class is now enabled.  See the manual for examples.
+  - FIXME: POSIX recommends using ${10} instead of $10 for the tenth
+  positional argument.  We should deprecate $10.
 
 * New builtin `renamesyms' allows programmatic renaming of all symbols
   according to a regular expression.
+  - FIXME: This feature can cause core dumps when renaming multiple
+  symbols to the same name.
 
-* New `-r' command-line option changes the default regular expression
-  syntax used by M4.  Without this option, M4 continues to use
-  RE_SYNTAX_EMACS style expressions.  A new section in the info docs
+* New `-r'/`--regexp-syntax' command-line option changes the default
+  regular expression syntax used by M4.  Without this option, M4 continues
+  to use EMACS style expressions.  A new section in the info docs
   explains the differences between them, and what builtins are affected.
 
 * The experimental `epatsubst' and `eregexp' have been removed in favor
@@ -28,6 +46,40 @@ Version beta 1.9a - ???, by ???
 * `patsubst' and `regexp' have a new optional 4th argument to use a
   different regular expression syntax for the duration of that invocation.
 
+* New `-B'/`--prepend-include' command-line option allows prepending to
+  the include path, rather than always searching `.' first.
+
+* New `--safer' command-line option cripples the potentially unsafe
+  macros `debugfile', `syscmd', `esyscmd', and `maketemp'.
+
+* New `m' flag to `-d'/`--debug' option or `debugmode' macro traces
+  actions related to module loading and unloading.  Also, the `--debug'
+  option now understands `-' and `+' modifiers, the way `debugmode' has
+  always done.
+
+* The semantics of `traceon' and `traceoff' now match traditional
+  implementations: when called without arguments, they affect global state
+  rather than affecting only the macros defined at that moment.  The
+  manual includes an example of how to recover 1.4.x semantics.
+
+* The syntax of frozen files format V2 has been improved to save
+  additional state.
+  - FIXME: format 2 still needs to be tweaked to allow complete ASCII
+  representation and to catch any more missing state; once 2.0 is released,
+  any further changes would introduce format 3.
+
+* The `dumpdef' macro now always outputs to standard error, rather than
+  the debug file specified by `-o'/`--error-output' or option or
+  `debugfile' macro.
+  - FIXME: the name --error-output is a bit misleading, since it really
+  affects only debugmode and traceon output; we should probably deprecate
+  the --error-output, and rename it something like --trace-output.
+
+* FIXME: `m4wrap' semantics need an update to FIFO.
+
+* FIXME: include the (long) list of changes in 1.4.x that were not already
+  in earlier betas.
+
 Version beta 1.4q - August 2001, by Gary V. Vaughan
 
 * Support for the experimental `changeword' has been dropped.
@@ -89,6 +141,9 @@ Version beta 1.4o - January 2000, by Ren
 
 * Modules now use libtool's wrapper libltdl.
 
+* New builtin `symbols' allows dynamic queries of all currently defined
+  macros.
+
 * Bug fixes.
 
 Version beta 1.4n - November 1998, by Rene' Seindal
Index: doc/m4.texinfo
===================================================================
RCS file: /sources/m4/m4/doc/m4.texinfo,v
retrieving revision 1.44
diff -u -p -r1.44 m4.texinfo
--- doc/m4.texinfo      15 Sep 2006 03:37:53 -0000      1.44
+++ doc/m4.texinfo      18 Sep 2006 05:36:56 -0000
@@ -613,7 +613,7 @@ eventually disappear in future releases.
 @itemx -T @var{NUM}
 These options are present for compatibility with System V @code{m4}, but
 do nothing in this implementation.  They may disappear in future
-releases.
+releases, and issue a warning to that effect.
 @end table
 
 @acronym{GNU} @code{m4} comes with a feature of freezing internal state
@@ -631,8 +631,8 @@ in @samp{.m4f}.
 @itemx address@hidden
 Before execution starts, recover the internal state from the specified
 frozen @var{FILE}.  The options @option{-D}, @option{-U}, @option{-t},
address@hidden, and @option{-r} take effect after state is reloaded, but
-before the input files are read.
address@hidden, @option{-r}, and @option{--import-environment} take effect
+after state is reloaded, but before the input files are read.
 @end table
 
 Finally, there are several options for aiding in debugging @code{m4}
@@ -661,6 +661,11 @@ Redirect debug and trace output to the n
 error messages, and the output of @code{errprint} and @code{dumpdef},
 are still printed to standard error.  @xref{Debug Output}, for more
 details.
address@hidden FIXME the name --error-output is misleading, since errprint
address@hidden and errors still prints to stderr in spite of this option.  We
address@hidden should rename the option; perhaps --trace-output or
address@hidden --debug-output, or perhaps --debugfile to match the macro
address@hidden name.
 
 @item -t @var{NAME}
 @itemx address@hidden
@@ -672,8 +677,8 @@ This option may be given more than once.
 @cindex command line, file names on the
 @cindex file names, on the command line
 The remaining arguments on the command line are taken to be input file
-names.  If no names are present, the standard input is read.  A file
-name of @file{-} is taken to mean the standard input.  It is
+names.  If no names are present, standard input is read.  A file
+name of @file{-} is taken to mean standard input.  It is
 conventional, but not required, for input files to end in @samp{.m4}.
 
 The input files are read in the sequence given.  Standard input can be
@@ -1484,10 +1489,11 @@ or more digits, allowing macros to have 
 is not so in UNIX implementations of @code{m4}, which only recognize
 one digit.
 @comment FIXME - See Austin group XCU ERN 111.  This is controversial,
address@hidden and perhaps we should consider an alternate syntax ${10}
address@hidden and phase out $10, for better POSIX compliance.  There are
address@hidden existing m4 scripts that depend on $10 being the first
address@hidden parameter concatenated with 0, not the tenth argument.
address@hidden and POSIX is moving to reserve ${ for implementation use.  We
address@hidden should phase out $10 and replace it with ${10}, and consider
address@hidden other extensions like ${1-default}.  There are existing m4
address@hidden scripts that depend on $10 being the first parameter
address@hidden concatenated with 0, not the tenth argument.
 
 As a special case, the zeroth argument, @code{$0}, is always the name
 of the macro being expanded.
@@ -1993,10 +1999,10 @@ m4_renamesyms(`^m4_m4(\w*)$', `m4_\1', `
 @cindex @acronym{GNU} extensions
 Any macro can be called indirectly with @code{indir}:
 
address@hidden {Builtin (gnu)} indir (@var{name}, @dots{})
address@hidden {Builtin (gnu)} indir (@var{name}, @address@hidden)
 Results in a call to the macro @var{name}, which is passed the
-rest of the arguments.  If @var{name} is not defined, an error message
-is printed, and the expansion is void.
+rest of the arguments @var{args}.  If @var{name} is not defined, an
+error message is printed, and the expansion is void.
 
 The macro @code{indir} is recognized only with parameters.
 @end deffn
@@ -2045,10 +2051,10 @@ indir(`f', undefine(`f'))
 @cindex @acronym{GNU} extensions
 Builtin macros can be called indirectly with @code{builtin}:
 
address@hidden {Builtin (gnu)} builtin (@var{name}, @dots{})
address@hidden {Builtin (gnu)} builtin (@var{name}, @address@hidden)
 Results in a call to the builtin @var{name}, which is passed the
-rest of the arguments.  If @var{name} does not name a builtin, a warning
-message is printed, and the expansion is void.
+rest of the arguments @var{args}.  If @var{name} does not name a
+builtin, a warning message is printed, and the expansion is void.
 
 The macro @code{builtin} is recognized only with parameters.
 @end deffn
@@ -2130,14 +2136,14 @@ indir(`index')
 The name of the currently defined macros can be accessed by
 @code{symbols}:
 
address@hidden {Builtin (gnu)} symbols (@dots{})
address@hidden {Builtin (gnu)} symbols (@address@hidden)
 Without arguments, @samp{symbols} expands to a sorted list of quoted
 strings, separated by commas.  This contrasts with @code{dumpdef}
 (@pxref{Dumpdef}), whose output cannot be accessed by @code{m4}
 programs.
 
 When given arguments, @code{symbols} returns the sorted subset of the
-symbols currently defined.
address@hidden currently defined, and silently ignores the rest.
 @end deffn
 
 @example
@@ -2524,9 +2530,9 @@ with these semantics yourself, then chec
 @node Debugging
 @chapter How to debug macros and input
 
-When writing macros for @code{m4}, most of the time they would not
-work as intended (as is the case with most programming languages).
-There is a little support for macro debugging in @code{m4}.
+When writing macros for @code{m4}, they often do not work as intended on
+the first try (as is the case with most programming languages).
+Fortunately, there is support for macro debugging in @code{m4}.
 
 @menu
 * Dumpdef::                     Displaying macro definitions
@@ -2544,18 +2550,20 @@ There is a little support for macro debu
 If you want to see what a name expands into, you can use the builtin
 @code{dumpdef}:
 
address@hidden {Builtin (m4)} dumpdef
address@hidden {Builtin (m4)} dumpdef (@dots{})
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 names given.  The output is printed
-directly on the standard error output, independently of
address@hidden
address@hidden {Builtin (m4)} 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
+directly to standard error, independently of the @option{--error-output}
+option (or @option{-o}, @pxref{Invoking m4}), or @code{debugfile} macro.
+The output is sorted by name.  If an unknown name is encountered, a
+warning is printed.
 
 The expansion of @code{dumpdef} is void.
 @end deffn
 
 @example
+$ @kbd{m4 -d}
 define(`foo', `Hello world.')
 @result{}
 dumpdef(`foo')
@@ -2567,9 +2575,25 @@ dumpdef(`define')
 @end example
 
 The last example shows how builtin macros definitions are displayed.
+The definition that is dumped corresponds to what would occur if the
+macro were to be called at that point, even if other definitions are
+still live due to redefining a macro during argument collection.
+
address@hidden
+$ @kbd{m4 -d}
+pushdef(`f', ``$0'1')pushdef(`f', ``$0'2')
address@hidden
+f(popdef(`f')dumpdef(`f'))
address@hidden:@tabchar{}``$0'1'
address@hidden
+f(popdef(`f')dumpdef(`f'))
address@hidden:stdin:3: Warning: dumpdef: undefined macro `f'
address@hidden
address@hidden example
 
 @xref{Debug Levels}, for information on controlling the details of the
-display.
+display; in particular, the @samp{q} flag, implied by @option{-d} in the
+example command line, has an impact.
 
 @node Trace
 @section Tracing macro calls
@@ -2580,13 +2604,16 @@ display.
 It is possible to trace macro calls and expansions through the builtins
 @code{traceon} and @code{traceoff}:
 
address@hidden {Builtin (m4)} traceon
address@hidden {Builtin (m4)} traceon (@dots{})
address@hidden {Builtin (m4)} traceoff
address@hidden {Builtin (m4)} traceoff (@dots{})
address@hidden {Builtin (m4)} traceon (@address@hidden)
address@hidden {Builtin (m4)} traceoff (@address@hidden)
 When called without any arguments, @code{traceon} and @code{traceoff}
-will turn tracing on and off, respectively,  for all defined macros.
-When called with arguments, only the named macros are affected.
+will turn tracing on and off, respectively, for all macros, identical to
+using the @samp{t} flag of @code{debugmode} (@pxref{Debug Levels}).
+When called with arguments, only the named macros are affected, whether
+or not they are currently defined.  A macro's expansion will be traced
+if global tracing is on, or if the individual macro tracing flag is
+set; to avoid tracing a macro, both the global flag and the macro must
+have tracing off.
 
 The expansion of @code{traceon} and @code{traceoff} is void.
 @end deffn
@@ -2594,9 +2621,11 @@ The expansion of @code{traceon} and @cod
 Whenever a traced macro is called and the arguments have been collected,
 the call is displayed.  If the expansion of the macro call is not void,
 the expansion can be displayed after the call.  The output is printed
-directly on the standard error output.
+to the current debug file (defaulting to standard error, @pxref{Debug
+Output}).
 
 @example
+$ @kbd{m4 -d}
 define(`foo', `Hello World.')
 @result{}
 define(`echo', `$@@')
@@ -2613,7 +2642,162 @@ echo(`gnus', `and gnats')
 
 The number between dashes is the depth of the expansion.  It is one most
 of the time, signifying an expansion at the outermost level, but it
-increases when macro arguments contain unquoted macro calls.
+increases when macro arguments contain unquoted macro calls.  The
+maximum number that will appear between dashes is controlled by the
+option @option{--nesting-limit} (or @option{-L}, @pxref{Invoking m4}).
+Additionally, the option @option{--trace} (or @option{-t}) can be used
+to invoke @code{traceon(@var{name})} before parsing input.
+
address@hidden options: -d-V -L3 -tifelse
address@hidden status: 1
address@hidden
+$ @kbd{m4 -L 3 -t ifelse}
+ifelse(`one level')
address@hidden: -1- ifelse
address@hidden
+ifelse(ifelse(ifelse(`three levels')))
address@hidden: -3- ifelse
address@hidden: -2- ifelse
address@hidden: -1- ifelse
address@hidden
+ifelse(ifelse(ifelse(ifelse(`four levels'))))
address@hidden:stdin:3: recursion limit of 3 exceeded, use -L<N> to change it
address@hidden example
+
+Tracing by name is an attribute that is preserved whether the macro is
+defined or not.  This allows the selection of macros to trace before
+those macros are defined.
+
address@hidden
+$ @kbd{m4 -d}
+traceoff(`foo')
address@hidden
+traceon(`foo')
address@hidden
+foo
address@hidden
+define(`foo', `bar')
address@hidden
+foo
address@hidden: -1- foo -> `bar'
address@hidden
+undefine(`foo')
address@hidden
+ifdef(`foo', `yes', `no')
address@hidden
+indir(`foo')
address@hidden:stdin:8: Warning: indir: undefined macro `foo'
address@hidden
+define(`foo', `blah')
address@hidden
+foo
address@hidden: -1- foo -> `blah'
address@hidden
address@hidden example
+
+Tracing even works on builtins.  However, @command{defn} (@pxref{Defn})
+does not transfer tracing status.
+
address@hidden
+$ @kbd{m4 -d}
+traceon(`eval', `m4_divnum')
address@hidden
+define(`m4_eval', defn(`eval'))
address@hidden
+define(`m4_divnum', defn(`divnum'))
address@hidden
+eval(divnum)
address@hidden: -1- eval(`0') -> `0'
address@hidden
+m4_eval(m4_divnum)
address@hidden: -2- m4_divnum -> `0'
address@hidden
address@hidden example
+
+As of @acronym{GNU} M4 2.0, named macro tracing is independent of global
+tracing status; calling @code{traceoff} without arguments turns off the
+global trace flag, but does not turn off tracing for macros where
+tracing was requested by name.  Likewise, calling @code{traceon} without
+arguments will affect tracing of macros that are not defined yet.  This
+behavior matches traditional implementations of @code{m4}.
+
address@hidden
+$ @kbd{m4 -d}
+traceon
address@hidden
+define(`foo', `bar')
address@hidden: -1- define(`foo', `bar')
address@hidden
+foo # traced, even though foo was not defined at traceon
address@hidden: -1- foo -> `bar'
address@hidden # traced, even though foo was not defined at traceon
+traceoff(`foo')
address@hidden: -1- traceoff(`foo')
address@hidden
+foo # traced, since global tracing is still on
address@hidden: -1- foo -> `bar'
address@hidden # traced, since global tracing is still on
+traceon(`foo')
address@hidden: -1- traceon(`foo')
address@hidden
+traceoff
address@hidden: -1- traceoff
address@hidden
+foo # traced, since foo is now traced by name
address@hidden: -1- foo -> `bar'
address@hidden # traced, since foo is now traced by name
+traceoff(`foo')
address@hidden
+foo # untraced
address@hidden # untraced
address@hidden example
+
+However, @acronym{GNU} M4 1.4.7 and earlier had slightly different
+semantics, where @code{traceon} without arguments only affected symbols
+that were defined at that moment, and @code{traceoff} without arguments
+stopped all tracing, even when tracing was requested by macro name.  The
+addition of the macro @code{symbols} (@pxref{Symbols}) in 2.0 makes it
+possible to write a file that approximates the older semantics
+regardless of which version of @acronym{GNU} M4 is in use.
+
address@hidden options: -d-V
address@hidden
+$ @kbd{m4}
+ifdef(`symbols',
+  `define(`traceon', `ifelse(`$#', `0', `builtin(`traceon', symbols)',
+    `builtin(`traceon', $@@)')')dnl
+define(`traceoff', `ifelse(`$#', `0',
+    `builtin(`traceoff')builtin(`traceoff', symbols)',
+    `builtin(`traceoff', $@@)')')')dnl
+define(`a', `1')
address@hidden
+traceon # called before b is defined, so b is not traced
address@hidden # called before b is defined, so b is not traced
+define(`b', `2')
address@hidden: -1- define
address@hidden
+a b
address@hidden: -1- a
address@hidden 2
+traceon(`b')
address@hidden: -1- traceon
address@hidden: -1- ifelse
address@hidden: -1- builtin
address@hidden
+a b
address@hidden: -1- a
address@hidden: -1- b
address@hidden 2
+traceoff # stops tracing b, even though it was traced by name
address@hidden: -1- traceoff
address@hidden: -1- ifelse
address@hidden: -1- builtin
address@hidden: -2- symbols
address@hidden: -1- builtin
address@hidden # stops tracing b, even though it was traced by name
+a b
address@hidden 2
address@hidden example
 
 @xref{Debug Levels}, for information on controlling the details of the
 display.
@@ -2623,43 +2807,37 @@ display.
 
 @cindex controlling debugging output
 @cindex debugging output, controlling
-The @samp{-d} option to @code{m4} controls the amount of details
-presented, when using the macros described in the preceding sections.
+The @option{--debug} option to @code{m4} (or @option{-d},
address@hidden m4}) controls the amount of details presented, when
+using the macros described in the preceding sections.
 
 The @var{flags} following the option can be one or more of the
 following:
 
 @table @code
address@hidden t
-Trace all macro calls made in this invocation of @code{m4}.
-
 @item a
 Show the actual arguments in each macro call.  This applies to all macro
 calls if the @samp{t} flag is used, otherwise only the macros covered by
 calls of @code{traceon}.
 
address@hidden e
-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, otherwise only the
-macros covered by calls of @code{traceon}.
-
address@hidden q
-Quote actual arguments and macro expansions in the display with the
-current quotes.
-
 @item c
 Show several trace lines for each macro call.  A line is shown when the
 macro is seen, but before the arguments are collected; a second line
 when the arguments have been collected and a third line after the call
 has completed.
 
address@hidden x
-Add a unique `macro call id' to each line of the trace output.  This is
-useful in connection with the @samp{c} flag above.
address@hidden e
+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, otherwise only the
+macros covered by calls of @code{traceon}.
 
 @item f
 Show the name of the current input file in each trace output line.
 
address@hidden i
+Print a message each time the current input file is changed, giving file
+name and input line number.
+
 @item l
 Show the current input line number in each trace output line.
 
@@ -2670,54 +2848,119 @@ Print a message each time a module is ma
 Print a message when a named file is found through the path search
 mechanism (@pxref{Search Path}), giving the actual file name used.
 
address@hidden i
-Print a message each time the current input file is changed, giving file
-name and input line number.
address@hidden q
+Quote actual arguments and macro expansions in the display with the
+current quotes.  This affects traced macros, as well as @code{dumpdef}
+output.
+
address@hidden t
+Trace all macro calls made in this invocation of @code{m4}.  This is
+equivalent to using @code{traceon} without arguments.
+
address@hidden x
+Add a unique `macro call id' to each line of the trace output.  This is
+useful in connection with the @samp{c} flag above.
 
 @item V
 A shorthand for all of the above flags.
 @end table
 
-If no flags are specified with the @samp{-d} option, the default is
address@hidden The examples in the previous two sections assumed the
+As special cases, if @var{flags} starts with a @samp{+}, the remaining
+flags are added to the current debug flags, and if it starts with a
address@hidden, remaining flags are removed.  Without either of these
+starting characters, @var{flags} simply replaces the previous setting.
+
+If no flags are specified with the @option{-d} option, the default is
address@hidden Many examples in this manual show their output using
 default flags.
 
address@hidden GNU extensions
address@hidden @acronym{GNU} extensions
 There is a builtin macro @code{debugmode}, which allows on-the-fly control of
 the debugging output format:
 
address@hidden {Builtin (gnu)} debugmode
address@hidden {Builtin (gnu)} debugmode @w{(opt @var{flags})}
address@hidden {Builtin (gnu)} debugmode (@ovar{flags})
 The argument @var{flags} should be a subset of the letters listed above.
-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, the debugging flags are set to
-zero (as if no @samp{-d} was given), and with an empty argument the flags
-are reset to the default.
+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}.  If an unknown flag is
+encountered, an error is issued.
+
+The expansion of @code{debugmode} is void.
 @end deffn
 
address@hidden
+define(`foo', `FOO')
address@hidden
+traceon(`foo')
address@hidden
+debugmode()
address@hidden
+foo
address@hidden: -1- foo -> `FOO'
address@hidden
+debugmode
address@hidden
+foo
address@hidden: -1- foo
address@hidden
+debugmode(`+l')
address@hidden
+foo
address@hidden:8: -1- foo
address@hidden
address@hidden example
+
 @node Debug Output
 @section Saving debugging output
 
 @cindex saving debugging output
 @cindex debugging output, saving
 @cindex output, saving debugging
address@hidden GNU extensions
address@hidden @acronym{GNU} extensions
 Debug and tracing output can be redirected to files using either the
address@hidden option to @code{m4}, or with the builtin macro @code{debugfile}:
address@hidden option to @code{m4} (@pxref{Invoking m4}), or with the
+builtin macro @code{debugfile}:
 
address@hidden {Builtin (gnu)} debugfile
address@hidden {Builtin (gnu)} debugfile @w{(opt @var{file})}
address@hidden {Builtin (gnu)} debugfile (@ovar{file})
 Send all further debug and trace output to @var{file}, opened in append
 mode.  If @var{file} is the empty string, debug and trace output are
-discarded and if @code{debugfile} is called without any arguments, debug
-and trace output are sent to the standard error output.
+discarded.  If @code{debugfile} is called without any arguments,
+debug and trace output are sent to standard error.  This does not
+affect warnings, error messages, or @code{errprint} and @code{dumpdef}
+output, which are always sent to standard error.  If @var{file} cannot
+be opened, the current debug file is unchanged, and an error is issued.
 
 When the @option{--safer} option (@pxref{Invoking m4}) is in effect,
 @var{file} must be empty or omitted, since otherwise an input file
 could cause the modification of arbitrary files.
+
+The expansion of @code{debugfile} is void.
 @end deffn
 
address@hidden
+$ @kbd{m4 -d}
+traceon(`divnum')
address@hidden
+divnum(`extra')
address@hidden:stdin:2: Warning: divnum: extra arguments ignored: 1 > 0
address@hidden: -1- divnum(`extra') -> `0'
address@hidden
+debugfile()
address@hidden
+divnum(`extra')
address@hidden:stdin:4: Warning: divnum: extra arguments ignored: 1 > 0
address@hidden
+debugfile
address@hidden
+divnum
address@hidden: -1- divnum -> `0'
address@hidden
address@hidden example
+
+Although the @option{--safer} option cripples @code{debugfile} to a
+limited subset of capabilities, you may still use the @option{-o}
+option from the command line with no restrictions.
+
 @comment options: --safer
 @comment status: 1
 @example
@@ -2780,7 +3023,7 @@ next newline, on whatever line containin
 
 @cindex changing the quote delimiters
 @cindex quote delimiters, changing the
address@hidden {Builtin (m4)} changequote (@w{opt @var{start}}, @w{opt 
@var{end})}
address@hidden {Builtin (m4)} changequote (@ovar{start}, @ovar{end})
 The default quote delimiters can be changed with the builtin
 @code{changequote}, where @var{start} is the new start-quote delimiter
 and @var{end} is the new end-quote delimiter.  If any of the arguments
@@ -2843,7 +3086,7 @@ the quoting mechanism.
 
 @cindex changing comment delimiters
 @cindex comment delimiters, changing
address@hidden {Builtin (m4)} changecom (@w{opt @var{start}}, @w{opt @var{end})}
address@hidden {Builtin (m4)} changecom (@ovar{start}, @ovar{end})
 The default comment delimiters can be changed with the builtin
 macro @code{changecom}, where @var{start} is the new start-comment
 delimiter and @var{end} is the new end-comment delimiter.  If any of the
@@ -2889,7 +3132,7 @@ changecom
 
 @cindex regular expression syntax, changing
 @cindex GNU extensions
address@hidden {Builtin (gnu)} changeresyntax (@w{opt @var{resyntax}})
address@hidden {Builtin (gnu)} changeresyntax (@var{resyntax})
 By default, the @sc{gnu} extensions @code{patsubst}, @code{regexp} and
 more recently @code{renamesyms} continue to use emacs style regular
 expression syntax (@pxref{Regular expression syntax}).
@@ -3411,11 +3654,11 @@ of @file{incl.m4}:
 @example
 define(`bar', include(`incl.m4'))
 @result{}
-This is `bar':  >>>bar<<<
address@hidden is bar:  >>>Include file start
+This is `bar':  >>bar<<
address@hidden is bar:  >>Include file start
 @result{}foo
 @result{}Include file end
address@hidden<<<
address@hidden<<
 @end example
 
 This use of @code{include} is not trivial, though, as files can contain
@@ -3482,7 +3725,7 @@ limited by the number of available file 
 @cindex output, diverting to files
 @cindex files, diverting output to
 @deffn {Builtin (m4)} divert
address@hidden {Builtin (m4)} divert (@w{opt @var{number}})
address@hidden {Builtin (m4)} divert (@ovar{number})
 Output is diverted using @code{divert} where @var{number} is the
 diversion to be used.  If @var{number} is left out, it is assumed to be
 zero.
@@ -3527,7 +3770,7 @@ This is a common programming idiom in @c
 @section Undiverting output
 
 @deffn {Builtin (m4)} undivert
address@hidden {Builtin (m4)} undivert (@w{opt @var{number}}, @dots{})
address@hidden {Builtin (m4)} undivert (@address@hidden)
 Diverted text can be undiverted explicitly using the builtin
 @code{undivert},  which reinserts the diverted output given by the
 arguments into the current output stream, in the order given.  If no
@@ -3958,7 +4201,8 @@ index(`gnus, gnats, and armadillos', `da
 @cindex regular expressions
 @cindex GNU extensions
 @deffn {Builtin (gnu)} regexp (@var{string}, @var{regexp}, @var{resyntax})
address@hidden {Builtin (gnu)} regexp (@var{string}, @var{regexp}, @w{opt 
@var{replacement},} @w{opt @var{resyntax})}
address@hidden {Builtin (gnu)} regexp (@var{string}, @var{regexp}, @
+  @ovar{replacement}, @ovar{resyntax})
 Searching for regular expressions is done with the builtin
 @code{regexp}, which searches for @var{regexp} in @var{string}.  The
 syntax of regular expressions is similar to that of Perl, @sc{gnu} Awk
@@ -4019,7 +4263,7 @@ regexp(`GNUs not Unix', `\w(\w+)$', `POS
 
 @cindex extracting substrings
 @cindex substrings, extracting
address@hidden {Builtin (m4)} substr (@var{string}, @var{from}, @w{opt 
@var{length})}
address@hidden {Builtin (m4)} substr (@var{string}, @var{from}, @ovar{length})
 Substrings are extracted with @code{substr}, which expands to the
 substring of @var{string}, which starts at index @var{from}, and extends
 for @var{length} characters, or to the end of @var{string}, if
@@ -4084,7 +4328,8 @@ most common.
 @cindex pattern substitution
 @cindex substitution by regular expression
 @cindex GNU extensions
address@hidden {Builtin (gnu)} patsubst (@var{string}, @var{regexp}, @w{opt 
@var{replacement},} @w{opt @var{resyntax})}
address@hidden {Builtin (gnu)} patsubst (@var{string}, @var{regexp}, @
+  @ovar{replacement}, @ovar{resyntax})
 Global substitution in a string is done by @code{patsubst}, which
 searches @var{string} for matches of @var{regexp}, and substitutes
 @var{replacement} for each match.
@@ -4275,7 +4520,7 @@ given arguments.
 @cindex integer expression evaluation
 @cindex evaluation, of integer expressions
 @cindex expressions, evaluation of integer
address@hidden {Builtin (m4)} eval (@var{expression}, @w{opt @var{radix},} 
@w{opt @var{width})}
address@hidden {Builtin (m4)} eval (@var{expression}, @ovar{radix}, 
@ovar{width})
 Integer expressions are evaluated with @code{eval}, which expands to the
 value of @var{expression}.
 
@@ -4393,7 +4638,7 @@ Take note that @var{radix} cannot be lar
 When @code{m4} is compiled with a multiple precision arithmetic library
 (@pxref{Experiments}), a builtin @code{mpeval} is defined.
 
address@hidden {Builtin (mpeval)} mpeval (@var{expression}, @w{opt 
@var{radix},} @w{opt @var{width})}
address@hidden {Builtin (mpeval)} mpeval (@var{expression}, @ovar{radix}, 
@ovar{width})
 It is almost identical to @code{eval}, except the calculations are done
 with infinite precision.  Numbers may be of any length.
 
@@ -4484,7 +4729,7 @@ If you want @code{m4} to read the output
 command @var{shell-command}.
 
 Prior to executing the command, @code{m4} flushes its output buffers.
-The default standard input and error output of @var{shell-command} are
+The default standard input and standard error of @var{shell-command} are
 the same as those of @code{m4}.  The error output of @var{shell-command}
 is not a part of the expansion: it will appear along with the error
 output of @code{m4}.
@@ -4618,8 +4863,8 @@ any of the previous chapters.
 @cindex messages, printing error
 @deffn {Builtin (m4)} errprint (@var{message}, @dots{})
 You can print error messages using @code{errprint}, which simply prints
address@hidden and the rest of the arguments on the standard error
-output, independently of @option{--error-output}.
address@hidden and the rest of the arguments on standard error,
+independently of @option{--error-output}.
 
 The expansion of @code{errprint} is void.
 @end deffn
@@ -4658,8 +4903,7 @@ errprint(`m4:'__file__:__line__: `Input 
 @section Exiting from @code{m4}
 
 @cindex exiting from @code{m4}
address@hidden {Builtin (m4)} m4exit
address@hidden {Builtin (m4)} m4exit (@w{opt @var{code}})
address@hidden {Builtin (m4)} m4exit (@ovar{code})
 If you need to exit from @code{m4} before the entire input has been
 read, you can use @code{m4exit}, which causes @code{m4} to exit, with
 exit code @var{code}.  If @var{code} is left out, the exit code is
Index: m4/m4.c
===================================================================
RCS file: /sources/m4/m4/m4/m4.c,v
retrieving revision 1.18
diff -u -p -r1.18 m4.c
--- m4/m4.c     1 Sep 2006 23:11:05 -0000       1.18
+++ m4/m4.c     18 Sep 2006 05:36:56 -0000
@@ -28,7 +28,7 @@ m4_create (void)
 {
   m4 *context = xzalloc (sizeof *context);
 
-  context->symtab = m4_symtab_create (0, &context->no_gnu_extensions);
+  context->symtab = m4_symtab_create (0);
   context->syntax = m4_syntax_create ();
 
   context->debug_file   = stderr;
Index: m4/m4module.h
===================================================================
RCS file: /sources/m4/m4/m4/m4module.h,v
retrieving revision 1.85
diff -u -p -r1.85 m4module.h
--- m4/m4module.h       15 Sep 2006 03:37:54 -0000      1.85
+++ m4/m4module.h       18 Sep 2006 05:36:56 -0000
@@ -192,7 +192,7 @@ extern void     m4__module_exit    (m4 *
 typedef void *m4_symtab_apply_func (m4_symbol_table *symtab, const char *key,
                                    m4_symbol *symbol, void *userdata);
 
-extern m4_symbol_table *m4_symtab_create  (size_t, bool *);
+extern m4_symbol_table *m4_symtab_create  (size_t);
 extern void      m4_symtab_delete  (m4_symbol_table*);
 extern void *    m4_symtab_apply   (m4_symbol_table*, m4_symtab_apply_func*,
                                     void*);
@@ -214,9 +214,8 @@ extern void       m4_symbol_delete  (m4_
 
 extern m4_symbol_value *m4_get_symbol_value      (m4_symbol*);
 extern bool            m4_get_symbol_traced      (m4_symbol*);
-extern bool            m4_set_symbol_traced      (m4_symbol*, bool);
 extern bool            m4_set_symbol_name_traced (m4_symbol_table*,
-                                                  const char *);
+                                                  const char *, bool);
 
 #define m4_is_symbol_void(symbol)                                      \
        (m4_is_symbol_value_void (m4_get_symbol_value (symbol)))
Index: m4/m4private.h
===================================================================
RCS file: /sources/m4/m4/m4/m4private.h,v
retrieving revision 1.61
diff -u -p -r1.61 m4private.h
--- m4/m4private.h      15 Sep 2006 03:37:54 -0000      1.61
+++ m4/m4private.h      18 Sep 2006 05:36:56 -0000
@@ -201,7 +201,6 @@ struct m4_symbol_value {
    that also have an identically named function exported in m4module.h.  */
 #ifdef NDEBUG
 #  define m4_get_symbol_traced(S)      ((S)->traced)
-#  define m4_set_symbol_traced(S, V)   ((S)->traced = (V))
 #  define m4_get_symbol_value(S)       ((S)->value)
 #  define m4_set_symbol_value(S, V)    ((S)->value = (V))
 
Index: m4/symtab.c
===================================================================
RCS file: /sources/m4/m4/m4/symtab.c,v
retrieving revision 1.59
diff -u -p -r1.59 symtab.c
--- m4/symtab.c 5 Sep 2006 13:25:24 -0000       1.59
+++ m4/symtab.c 18 Sep 2006 05:36:56 -0000
@@ -46,7 +46,6 @@
 
 struct m4_symbol_table {
   m4_hash *table;
-  bool *nuke_trace_bit;        /* default: &(context->no_gnu_ext_opt) */
 };
 
 static m4_symbol *symtab_fetch         (m4_symbol_table*, const char *);
@@ -66,13 +65,12 @@ static void *         arg_copy_CB           (m4_hash *s
    These functions are used to manage a symbol table as a whole.  */
 
 m4_symbol_table *
-m4_symtab_create (size_t size, bool *nuke_trace_bit)
+m4_symtab_create (size_t size)
 {
   m4_symbol_table *symtab = xmalloc (sizeof *symtab);
 
   symtab->table = m4_hash_new (size ? size : M4_SYMTAB_DEFAULT_SIZE,
                               m4_hash_string_hash, m4_hash_string_cmp);
-  symtab->nuke_trace_bit = nuke_trace_bit;
   return symtab;
 }
 
@@ -115,6 +113,7 @@ m4_symtab_apply (m4_symbol_table *symtab
   return result;
 }
 
+/* Ensure that NAME exists in the table, creating an entry if needed.  */
 static m4_symbol *
 symtab_fetch (m4_symbol_table *symtab, const char *name)
 {
@@ -191,7 +190,7 @@ symbol_destroy_CB (m4_symbol_table *symt
 {
   char *key = xstrdup ((char *) name);
 
-  m4_set_symbol_traced (symbol, false);
+  symbol->traced = false;
 
   while (key && m4_hash_lookup (symtab->table, key))
     m4_symbol_popdef (symtab, key);
@@ -216,7 +215,7 @@ m4_symbol_lookup (m4_symbol_table *symta
 
   /* If just searching, return status of search -- if only an empty
      struct is returned, that is treated as a failed lookup.  */
-  return (psymbol && m4_get_symbol_value (*psymbol)) ? *psymbol : 0;
+  return (psymbol && m4_get_symbol_value (*psymbol)) ? *psymbol : NULL;
 }
 
 
@@ -276,18 +275,16 @@ m4_symbol_popdef (m4_symbol_table *symta
 
   assert (psymbol);
   assert (*psymbol);
-  assert (symtab->nuke_trace_bit);
 
   symbol_popval (*psymbol);
 
   /* Only remove the hash table entry if the last value in the
      symbol value stack was successfully removed.  */
-  if (!m4_get_symbol_value (*psymbol))
-    if (*symtab->nuke_trace_bit || !m4_get_symbol_traced (*psymbol))
-      {
-       DELETE (*psymbol);
-       free (m4_hash_remove (symtab->table, name));
-      }
+  if (!m4_get_symbol_value (*psymbol) && !m4_get_symbol_traced (*psymbol))
+    {
+      DELETE (*psymbol);
+      free (m4_hash_remove (symtab->table, name));
+    }
 }
 
 /* Remove the top-most value from SYMBOL's stack.  */
@@ -425,17 +422,43 @@ arg_copy_CB (m4_hash *src, const void *n
   return NULL;
 }
 
+/* Set the tracing status of the symbol NAME to TRACED.  This takes a
+   name, rather than a symbol, since we hide macros that are traced
+   but otherwise undefined from normal lookups, but still can affect
+   their tracing status.  Return true iff the macro was previously
+   traced.  */
 bool
-m4_set_symbol_name_traced (m4_symbol_table *symtab, const char *name)
+m4_set_symbol_name_traced (m4_symbol_table *symtab, const char *name,
+                          bool traced)
 {
   m4_symbol *symbol;
+  bool result;
 
   assert (symtab);
   assert (name);
 
-  symbol = symtab_fetch (symtab, name);
+  if (traced)
+    symbol = symtab_fetch (symtab, name);
+  else
+    {
+      m4_symbol **psymbol = (m4_symbol **) m4_hash_lookup (symtab->table,
+                                                          name);
+      if (!psymbol)
+       return false;
+      symbol = *psymbol;
+    }
 
-  return m4_set_symbol_traced (symbol, true);
+  result = symbol->traced;
+  symbol->traced = traced;
+  if (!traced && !m4_get_symbol_value (symbol))
+    {
+      /* Free an undefined entry once it is no longer traced.  */
+      assert (result);
+      free (symbol);
+      free (m4_hash_remove (symtab->table, name));
+    }
+
+  return result;
 }
 
 
@@ -459,14 +482,6 @@ m4_get_symbol_traced (m4_symbol *symbol)
   return symbol->traced;
 }
 
-#undef m4_set_symbol_traced
-bool
-m4_set_symbol_traced (m4_symbol *symbol, bool value)
-{
-  assert (symbol);
-  return symbol->traced = value;
-}
-
 #undef m4_symbol_value_create
 m4_symbol_value *
 m4_symbol_value_create (void)
Index: modules/m4.c
===================================================================
RCS file: /sources/m4/m4/modules/m4.c,v
retrieving revision 1.70
diff -u -p -r1.70 m4.c
--- modules/m4.c        15 Sep 2006 03:37:54 -0000      1.70
+++ modules/m4.c        18 Sep 2006 05:36:56 -0000
@@ -107,8 +107,6 @@ typedef unsigned long int unumber;
 static void    include         (m4 *context, int argc, m4_symbol_value **argv,
                                 bool silent);
 static int     dumpdef_cmp_CB  (const void *s1, const void *s2);
-static void *  set_trace_CB    (m4_symbol_table *symtab, const char *ignored,
-                                m4_symbol *symbol, void *userdata);
 static void *  dump_symbol_CB  (m4_symbol_table *ignored, const char*name,
                                 m4_symbol *symbol, void *userdata);
 static const char *ntoa                (number value, int radix);
@@ -743,33 +741,16 @@ M4BUILTIN_HANDLER (m4wrap)
    Tracing is disabled by default, when a macro is defined.  This can be
    overridden by the "t" debug flag.  */
 
-/* Set_trace () is used by "traceon" and "traceoff" to enable and disable
-   tracing of a macro.  It disables tracing if DATA is NULL, otherwise it
-   enable tracing.  */
-static void *
-set_trace_CB (m4_symbol_table *hash, const char *ignored, m4_symbol *symbol,
-          void *userdata)
-{
-  m4_set_symbol_traced (symbol, (bool) (userdata != NULL));
-  return NULL;
-}
-
 M4BUILTIN_HANDLER (traceon)
 {
   int i;
 
   if (argc == 1)
-    m4_symtab_apply (M4SYMTAB, set_trace_CB, (void *) obs);
+    m4_set_debug_level_opt (context, (m4_get_debug_level_opt (context)
+                                     | M4_DEBUG_TRACE_ALL));
   else
     for (i = 1; i < argc; i++)
-      {
-       const char *name = M4ARG (i);
-       m4_symbol *symbol = m4_symbol_lookup (M4SYMTAB, name);
-       if (symbol != NULL)
-         set_trace_CB (NULL, NULL, symbol, (char *) obs);
-       else
-         m4_warn (context, 0, _("%s: undefined macro `%s'"), M4ARG (0), name);
-      }
+      m4_set_symbol_name_traced (M4SYMTAB, M4ARG (i), true);
 }
 
 /* Disable tracing of all specified macros, or all, if none is specified.  */
@@ -778,17 +759,11 @@ M4BUILTIN_HANDLER (traceoff)
   int i;
 
   if (argc == 1)
-    m4_symtab_apply (M4SYMTAB, set_trace_CB, NULL);
+    m4_set_debug_level_opt (context, (m4_get_debug_level_opt (context)
+                                     & ~M4_DEBUG_TRACE_ALL));
   else
     for (i = 1; i < argc; i++)
-      {
-       const char *name = M4ARG (i);
-       m4_symbol *symbol = m4_symbol_lookup (M4SYMTAB, name);
-       if (symbol != NULL)
-         set_trace_CB (NULL, NULL, symbol, NULL);
-       else
-         m4_warn (context, 0, _("%s: undefined macro `%s'"), M4ARG (0), name);
-      }
+      m4_set_symbol_name_traced (M4SYMTAB, M4ARG (i), false);
 }
 
 
Index: src/main.c
===================================================================
RCS file: /sources/m4/m4/src/main.c,v
retrieving revision 1.82
diff -u -p -r1.82 main.c
--- src/main.c  15 Sep 2006 03:37:54 -0000      1.82
+++ src/main.c  18 Sep 2006 05:36:56 -0000
@@ -88,7 +88,7 @@ Operation modes:\n\
   -P, --prefix-builtins        force a `m4_' prefix to all builtins\n\
   -Q, --quiet, --silent        suppress some warnings for builtins\n\
   -r, --regexp-syntax=SPEC     change the default regexp syntax\n\
-  -s, --safer                  disable potentially unsafe builtins\n\
+      --safer                  disable potentially unsafe builtins\n\
 "), stdout);
       fputs (_("\
 \n\
@@ -431,7 +431,7 @@ main (int argc, char *const *argv, char 
 
       case SAFER_OPTION:
        m4_set_safer_opt (context, true);
-        break;
+       break;
 
       case VERSION_OPTION:
        version_etc (stdout, PACKAGE, PACKAGE_NAME TIMESTAMP,
@@ -512,7 +512,7 @@ main (int argc, char *const *argv, char 
            break;
 
          case 't':
-           m4_set_symbol_name_traced (M4SYMTAB, arg);
+           m4_set_symbol_name_traced (M4SYMTAB, arg, true);
            break;
 
          case 'm':
Index: tests/builtins.at
===================================================================
RCS file: /sources/m4/m4/tests/builtins.at,v
retrieving revision 1.18
diff -u -p -r1.18 builtins.at
--- tests/builtins.at   5 Sep 2006 16:58:02 -0000       1.18
+++ tests/builtins.at   18 Sep 2006 05:36:56 -0000
@@ -438,12 +438,16 @@ m4trace: -1- dumpdef(``foo'')
 m4trace: -1- dnl
 m4trace: -1- changequote(``!'', ``!'')
 m4trace: -1- dnl
+m4trace: -1- foo -> !``FOO''!
 foo:   !``FOO''!
 m4trace: -1- dumpdef(!foo!)
 m4trace: -1- dnl
 m4trace: -1- define(!bar!, !BAR!)
+m4trace: -1- bar -> !BAR!
 m4trace: -1- changequote(!>*>*>*>*>!, !<*<*<*<*<!)
 m4trace: -1- dnl
+m4trace: -1- foo -> >*>*>*>*>``FOO''<*<*<*<*<
+m4trace: -1- bar -> >*>*>*>*>BAR<*<*<*<*<
 bar:   >*>*>*>*>BAR<*<*<*<*<
 foo:   >*>*>*>*>``FOO''<*<*<*<*<
 m4trace: -1- dumpdef(>*>*>*>*>foo<*<*<*<*<, >*>*>*>*>bar<*<*<*<*<)

reply via email to

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