(m4.info)Defn


Next: Pushdef Prev: Undefine Up: Definitions

5.5 Renaming macros
===================

It is possible to rename an already defined macro.  To do this, you need
the builtin `defn':

 -- Builtin: defn (NAME...)
     Expands to the _quoted definition_ of each NAME.  If an argument
     is not a defined macro, the expansion for that argument is empty.

     If NAME is a user-defined macro, the quoted definition is simply
     the quoted expansion text.  If, instead, there is only one NAME
     and it is a builtin, the expansion is a special token, which
     points to the builtin's internal definition.  This token is only
     meaningful as the second argument to `define' (and `pushdef'), and
     is silently converted to an empty string in most other contexts.
     Combining a builtin with anything else is not supported; a warning
     is issued and the builtin is omitted from the final expansion.

     The macro `defn' is recognized only with parameters.

   Its normal use is best understood through an example, which shows
how to rename `undefine' to `zap':

     define(`zap', defn(`undefine'))
     =>
     zap(`undefine')
     =>
     undefine(`zap')
     =>undefine(zap)

   In this way, `defn' can be used to copy macro definitions, and also
definitions of builtin macros.  Even if the original macro is removed,
the other name can still be used to access the definition.

   The fact that macro definitions can be transferred also explains why
you should use `$0', rather than retyping a macro's name in its
definition:

     define(`foo', `This is `$0'')
     =>
     define(`bar', defn(`foo'))
     =>
     bar
     =>This is bar

   Macros used as string variables should be referred through `defn',
to avoid unwanted expansion of the text:

     define(`string', `The macro dnl is very useful
     ')
     =>
     string
     =>The macro 
     defn(`string')
     =>The macro dnl is very useful
     =>

   However, it is important to remember that `m4' rescanning is purely
textual.  If an unbalanced end-quote string occurs in a macro
definition, the rescan will see that embedded quote as the termination
of the quoted string, and the remainder of the macro's definition will
be rescanned unquoted.  Thus it is a good idea to avoid unbalanced
end-quotes in macro definitions or arguments to macros.

     define(`foo', a'a)
     =>
     define(`a', `A')
     =>
     define(`echo', `$@')
     =>
     foo
     =>A'A
     defn(`foo')
     =>aA'
     echo(foo)
     =>AA'

   On the other hand, it is possible to exploit the fact that `defn'
can concatenate multiple macros prior to the rescanning phase, in order
to join the definitions of macros that, in isolation, have unbalanced
quotes.  This is particularly useful when one has used several macros to
accumulate text that M4 should rescan as a whole.  In the example below,
note how the use of `defn' on `l' in isolation opens a string, which is
not closed until the next line; but used on `l' and `r' together
results in nested quoting.

     define(`l', `<[>')define(`r', `<]>')
     =>
     changequote(`[', `]')
     =>
     defn([l])defn([r])
     ])
     =><[>]defn([r])
     =>)
     defn([l], [r])
     =><[>][<]>

   Using `defn' to generate special tokens for builtin macros outside
of expected contexts can sometimes trigger warnings.  But most of the
time, such tokens are silently converted to the empty string.

     $ m4 -d
     defn(`defn')
     =>
     define(defn(`divnum'), `cannot redefine a builtin token')
     error-->m4:stdin:2: Warning: define: invalid macro name ignored
     =>
     divnum
     =>0
     len(defn(`divnum'))
     =>0

   Also note that `defn' with multiple arguments can only join text
macros, not builtins, although a future version of GNU M4 may lift this
restriction.

     $ m4 -d
     define(`a', `A')define(`AA', `b')
     =>
     traceon(`defn', `define')
     =>
     defn(`a', `divnum', `a')
     error-->m4:stdin:3: Warning: cannot concatenate builtin `divnum'
     error-->m4trace: -1- defn(`a', `divnum', `a') -> ``A'`A''
     =>AA
     define(`mydivnum', defn(`divnum', `divnum'))mydivnum
     error-->m4:stdin:4: Warning: cannot concatenate builtin `divnum'
     error-->m4:stdin:4: Warning: cannot concatenate builtin `divnum'
     error-->m4trace: -2- defn(`divnum', `divnum')
     error-->m4trace: -1- define(`mydivnum', `')
     =>
     traceoff(`defn', `define')
     =>


automatically generated by info2www