m4-discuss
[Top][All Lists]
Advanced

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

Re: Filter user macro invocation


From: Eric Blake
Subject: Re: Filter user macro invocation
Date: Sat, 03 May 2008 06:38:17 -0600
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.14) Gecko/20080421 Thunderbird/2.0.0.14 Mnenhy/0.7.5.666

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

According to address@hidden on 5/2/2008 9:06 AM:
|
|
|     You can even go one step further:
|
|     pushdef(`define', `builtin(`define', `$1',
|     ~ `ifelse(`$#', `0', ``$1'', `$2')')')

Sorry; I typed this without testing it.

| 1) Is the tilda ~ really part of the syntax or is that a typo/email
| conversion problem?

Email.  Thunderbird's enigmail plugin insists on tilde-quoting all leading
whitespace; if the recipient also uses a gpg client, the quotes are
stripped, but not everyone has an email client that understands gpg
(sometimes I really hate enigmail's behavior).

| 2) Even when I remove the ~, text substitution seems to work but the
| instances without parens are also getting substituted. And thats the
| orig problem I was attempting to fix.
| I would love to get your idea working !!

| I think the problem with Eric's solution is my inability to get the $#
| to stale it substitution. I need $# to reference the number of arguments
| in the calling instance and not in the current define. As it sits now $#
| appears to always resolve to `2' which is not zero and thus a stnd
| expansion occurs at all locations including loose text locations.

Indeed, that is the correct assessment.  It is sometimes difficult to
force adjacent $ and another character when writing a macro that defines
other macros.  You need to break up the quoting so the two characters are
not adjacent in the outer macro.  If the $# were single or even double
quoted in the outer macro, this would just be a matter of quoting
differently.  But as it is triple-quoted, the only way to do this is via
a helper macro.  Also, it would be wiser to make the inner definition use
a literal $0 rather than a hard-coded pre-expansion of $1, so that the
macro can be renamed and still behave correctly.

Also, it turns out that you want to use the original define when copying
definitions and not the override (hence the different name) - why? because
there is no way to define a macro that consists of wrapper text and a
builtin definition, so this idiom:

define(`foo', defn(`bar'))

breaks if `bar' happens to be a builtin macro but you've overridden
`define' to be your wrapper.

So, here's the improved version; actually tested this time, and with no
leading whitespace, and without overwriting the original define() macro.
Use plain `define' when copying macros, and `define_blind' when creating a
new text macro that behaves blind like various builtins.  Notice how this
uses a two-level macro expansion; the first provides extra arguments with
properly quoted adjacent $ and #/0, so that the second level can supply a
literal $#/$0 into the inner define call by referring to $3 and $4.
Definitely worth adding to the manual, since it wasn't trivial :)

define(`define_blind', `_$0(`$1', `$2', `$'`#', `$'`0')')
define(`_define_blind', `define(`$1',
`ifelse(`$3', `0', ``$4'', `$2')')')

And to test it:

define_blind(`foo', `bar-$1')dnl
defn(`foo')
=> ifelse(`$3', `0', ``$0'', `bar-$1')
foo
=> foo
foo(`blah')
=> bar-blah
define(`renamed_foo', defn(`foo'))dnl
renamed_foo
=> renamed_foo
renamed_foo(`blah')
=> bar-blah

- --
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

iEYEARECAAYFAkgcXLkACgkQ84KuGfSFAYAT+QCg1R8bllPHoV/qNUjzJ0NqZQiI
WzMAnRtPAzR/U6v/2nDo1/qBtUoY5uUV
=P0DA
-----END PGP SIGNATURE-----




reply via email to

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