Next: , Previous: , Up: Definitions   [Contents][Index]


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')
⇒

Next: , Previous: , Up: Definitions   [Contents][Index]