m4: Trace

 
 7.2 Tracing macro calls
 =======================
 
 It is possible to trace macro calls and expansions through the builtins
 'traceon' and 'traceoff':
 
  -- Builtin: traceon ([NAMES...])
  -- Builtin: traceoff ([NAMES...])
      When called without any arguments, 'traceon' and 'traceoff' will
      turn tracing on and off, respectively, for all currently defined
      macros.
 
      When called with arguments, only the macros listed in NAMES are
      affected, whether or not they are currently defined.
 
      The expansion of 'traceon' and 'traceoff' is void.
 
    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 to the current debug file (defaulting to standard error, ⇒
 Debug Output).
 
      $ m4 -d
      define(`foo', `Hello World.')
      =>
      define(`echo', `$@')
      =>
      traceon(`foo', `echo')
      =>
      foo
      error->m4trace: -1- foo -> `Hello World.'
      =>Hello World.
      echo(`gnus', `and gnats')
      error->m4trace: -1- echo(`gnus', `and gnats') -> ``gnus',`and gnats''
      =>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.  The
 maximum number that will appear between dashes is controlled by the
 option '--nesting-limit' (or '-L', ⇒Invoking m4 Limits control.).
 Additionally, the option '--trace' (or '-t') can be used to invoke
 'traceon(NAME)' before parsing input.
 
      $ m4 -L 3 -t ifelse
      ifelse(`one level')
      error->m4trace: -1- ifelse
      =>
      ifelse(ifelse(ifelse(`three levels')))
      error->m4trace: -3- ifelse
      error->m4trace: -2- ifelse
      error->m4trace: -1- ifelse
      =>
      ifelse(ifelse(ifelse(ifelse(`four levels'))))
      error->m4:stdin:3: recursion limit of 3 exceeded, use -L<N> to change it
 
    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.
 
      $ m4 -d
      traceoff(`foo')
      =>
      traceon(`foo')
      =>
      foo
      =>foo
      defn(`foo')
      =>
      define(`foo', `bar')
      =>
      foo
      error->m4trace: -1- foo -> `bar'
      =>bar
      undefine(`foo')
      =>
      ifdef(`foo', `yes', `no')
      =>no
      indir(`foo')
      error->m4:stdin:9: undefined macro `foo'
      =>
      define(`foo', `blah')
      =>
      foo
      error->m4trace: -1- foo -> `blah'
      =>blah
      traceoff
      =>
      foo
      =>blah
 
    Tracing even works on builtins.  However, 'defn' (⇒Defn) does
 not transfer tracing status.
 
      $ m4 -d
      traceon(`traceon')
      =>
      traceon(`traceoff')
      error->m4trace: -1- traceon(`traceoff')
      =>
      traceoff(`traceoff')
      error->m4trace: -1- traceoff(`traceoff')
      =>
      traceoff(`traceon')
      =>
      traceon(`eval', `m4_divnum')
      =>
      define(`m4_eval', defn(`eval'))
      =>
      define(`m4_divnum', defn(`divnum'))
      =>
      eval(divnum)
      error->m4trace: -1- eval(`0') -> `0'
      =>0
      m4_eval(m4_divnum)
      error->m4trace: -2- m4_divnum -> `0'
      =>0
 
    ⇒Debug Levels, for information on controlling the details of
 the display.  The format of the trace output is not specified by POSIX,
 and varies between implementations of 'm4'.