m4-discuss
[Top][All Lists]
Advanced

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

Re: Newbie - having difficulty with a macro


From: Eric Blake
Subject: Re: Newbie - having difficulty with a macro
Date: Sat, 01 Nov 2008 07:59:15 -0600
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.17) Gecko/20080914 Thunderbird/2.0.0.17 Mnenhy/0.7.5.666

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

[Please don't top-post]

According to John Christopher on 11/1/2008 6:41 AM:

Hello John,

> I could be wrong, but this seems like a bug,
> unless there is something I don't understand
> about the behavior of commas within a quoted
> string.

This is not a bug.  The manual gives examples of this:
http://www.gnu.org/software/m4/manual/m4.html#Quoting-Arguments
In fact, the ability to use commas in "inner" to make "outer(inner)" see
more than one argument to "outer" is one of the powerful notions of m4 not
present in other macro languages, although until you are used to the
implications of it, it can seem rather confusing.

The thing to remember is that m4 rescans strings literally after macro
expansion, including any m4 active characters like (, ), or , that were
not quoted.  Thus, in your example,

$ cat m4test.txt
m4_define(`MACRO1', `%d foo, bar %d')
m4_format(MACRO1, `3', `2')

MACRO1 is defined to the contents "%d foo, bar %d", with no extra m4
quoting around the comma.  In the second line, MACRO1 is unquoted, so it
is treated as a macro name to expand.  After the expansion, it is exactly
if you had provided:

m4_format(%d foo, bar %d, `3', `2')

Notice how you have given four arguments to m4_format.  The argument 'bar
%d' is not a number, hence the %d of the first argument is treated as 0.
The remaining arguments `3' and `2' are ignored, since you only had one %
directive in the first argument (m4 1.6 will warn you about unused
arguments to the format builtin, to make these kinds of scripting bugs
easier to detect).

There are two ways to work around it - Jack suggested one, which was to
double-quote the comma when defining MACRO1.  That would mean that the
intermediate line is:

m4_format(%d foo`,' bar %d, `3', `2')

which is then rescanned for quote removal, and invokes m4_format with "%d
foo, bar %d", "3", and "2".

The other way is to recognize that you are using MACRO1 as a means of
holding a text value, rather than a macro that you want expanded.  In
other words, you want the definition of MACRO1 as the argument to
m4_format, and not its expansion.

m4_format(m4_defn(`MACRO1'), `3', `2')

does what you want, because the intermediate expansion is:

m4_format(`%d foo, bar %d', `3', `2')

You may also want to play with the --debug=aeqt flag to m4 to see the
various macro expansions in action.

- --
Don't work too hard, make some time for fun as well!

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

iEYEARECAAYFAkkMYLMACgkQ84KuGfSFAYCpmgCg0dEGn9NhKZ9GBv6cr5jHNTCw
3PcAniKdR/bFG6kN0yHf4JzemG/DkEFT
=r557
-----END PGP SIGNATURE-----




reply via email to

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