### 5.3 Special arguments to macros ¶

There is a special notation for the number of actual arguments supplied, and for all the actual arguments.

The number of actual arguments in a macro call is denoted by `$#` in the expansion text.

Composite: nargs (…) ¶

  Expands to a count of the number of arguments supplied.

    define(`nargs', `$#')
    ⇒
    nargs
    ⇒0
    nargs()
    ⇒1
    nargs(`arg1', `arg2', `arg3')
    ⇒3
    nargs(`commas can be quoted, like this')
    ⇒1
    nargs(arg1#inside comments, commas do not separate arguments
    still arg1)
    ⇒1
    nargs((unquoted parentheses, like this, group arguments))
    ⇒1

Remember that ‘`#`’ defaults to the comment character; if you forget quotes to inhibit the comment behavior, your macro definition may not end where you expected.

    dnl Attempt to define a macro to just `$#'
    define(underquoted, $#)
    oops)
    ⇒
    underquoted
    ⇒0)
    ⇒oops

The notation `$*` can be used in the expansion text to denote all the actual arguments, unquoted, with commas in between. For example

    define(`echo', `$*')
    ⇒
    echo(arg1,    arg2, arg3 , arg4)
    ⇒arg1,arg2,arg3 ,arg4

Often each argument should be quoted, and the notation `$@` handles that. It is just like `$*`, except that it quotes each argument. A simple example of that is:

    define(`echo', `$@')
    ⇒
    echo(arg1,    arg2, arg3 , arg4)
    ⇒arg1,arg2,arg3 ,arg4

Where did the quotes go? Of course, they were eaten, when the expanded text were reread by `m4`. To show the difference, try

    define(`echo1', `$*')
    ⇒
    define(`echo2', `$@')
    ⇒
    define(`foo', `This is macro `foo'.')
    ⇒
    echo1(foo)
    ⇒This is macro This is macro foo..
    echo1(`foo')
    ⇒This is macro foo.
    echo2(foo)
    ⇒This is macro foo.
    echo2(`foo')
    ⇒foo

See Tracing macro calls, if you do not understand this. As another example of the difference, remember that comments encountered in arguments are passed untouched to the macro, and that quoting disables comments.

    define(`echo1', `$*')
    ⇒
    define(`echo2', `$@')
    ⇒
    define(`foo', `bar')
    ⇒
    echo1(#foo'foo
    foo)
    ⇒#foo'foo
    ⇒bar
    echo2(#foo'foo
    foo)
    ⇒#foobar
    ⇒bar'

A ‘`$`’ sign in the expansion text, that is not followed by anything `m4` understands, is simply copied to the macro expansion, as any other text is.

    define(`foo', `$$$ hello $$$')
    ⇒
    foo
    ⇒$$$ hello $$$

If you want a macro to expand to something like ‘`$12`’, the judicious use of nested quoting can put a safe character between the `$` and the next character, relying on the rescanning to remove the nested quote. This will prevent `m4` from interpreting the `$` sign as a reference to an argument.

    define(`foo', `no nested quote: $1')
    ⇒
    foo(`arg')
    ⇒no nested quote: arg
    define(`foo', `nested quote around $: `$'1')
    ⇒
    foo(`arg')
    ⇒nested quote around $: $1
    define(`foo', `nested empty quote after $: $`'1')
    ⇒
    foo(`arg')
    ⇒nested empty quote after $: $1
    define(`foo', `nested quote around next character: $`1'')
    ⇒
    foo(`arg')
    ⇒nested quote around next character: $1
    define(`foo', `nested quote around both: `$1'')
    ⇒
    foo(`arg')
    ⇒nested quote around both: arg