[Top][All Lists]

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

Re: m4_map

From: Eric Blake
Subject: Re: m4_map
Date: Thu, 14 Aug 2008 07:11:44 -0600
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv: Gecko/20080708 Thunderbird/ Mnenhy/

Hash: SHA1

[adding bug-bison]

According to Eric Blake on 8/7/2008 2:01 PM:
| On Oct 16 2007, Eric Blake <ebb9 <at> byu.net> writes:
|> Here's the patch for these macros, along with m4_apply, and semantics
|> to m4_map{,_sep} to make it reliably distinguish between an empty list of
|> arguments to apply, vs. a list containing a macro application with 0
| arguments,
|> vs. a list containing an argument list that contains an empty argument.
|> (m4_map): Change semantics to allow calling macro without
|> arguments.
|> (m4_map_sep): Likewise.  Also change semantics to quote separator,
|> to match m4_join and m4_append.
| I'm starting to have regrets about this semantic change to m4_map_sep.
At the
| time I made it, I did not know of any use of m4_map_sep in the wild
| certainly did not use it, neither did libtool).  But I overlooked bison,
| makes heavy use of m4_map_sep.

In addition to the issue of whether the separator is quoted, I've finally
pin-pointed the other m4_map regression that is breaking bison, were I to
use the current autoconf m4sugar instead of bison's.  Bison has a number
of places that invoke macro($@) with a (possibly empty) list of arguments,
where macro is in turn defined to call m4_map{,_sep}([helper], address@hidden).
Unfortunately, in m4, the mere presence of () guarantees the creation of a
parameter, so macro sees an empty argument, rather than realizing that its
caller had no arguments (ie. m4_map is called with [[]] rather than []).

Both the old and new version treat "m4_map([func], [])" as 0 sublists to
map, so func is never expanded.  And both versions treat "m4_map([func],
[[[]]])" as the single sublist containing an empty string, invoking
"func([])".  But the old version treated "m4_map([func], [[]])" as a
no-op, while the new version treats it as single empty sublist, and
invokes "m4_apply([func], [])", which in turn invokes "func" without
arguments.  That means bison's usage of address@hidden as the argument to 
m4_map now
triggers invocation of func with no arguments, where it was previously
unexpanded, leading to problems in the places where func was not prepared
to deal with 0 arguments.

Finally, the old version treated "m4_map([func], [[], [[1]]])" as a call
to "func()" followed by "func([1])" (that is, both sublists invoke func
with one argument), where the new version treats it as "func" followed by
"func([1])" (that is, the first call of func has zero arguments).
Fortunately, bison never uses an empty argument sublist anywhere except
when created by an empty address@hidden

So, to solve things, I'm thinking of the following change:

m4_map, m4_map_sep no longer invoke func on an empty argument sublist.
This means "m4_map([func], [[]])" goes back to being a no-op, while
"m4_map([func], [[], [[1]])" now invokes only "func([1])", instead of two
invocations.  Additionally, m4_map_sep behaves like m4_join, where the
separator is omitted if the func call is omitted, so that
"m4_map_sep([m4_dquote], [-], [[[1]], [], [[]]])" results in "[1]-[]",
rather than "[1]--[]".  For all cases bison is worried about, this makes
m4_map go back to its pre-2.62 behavior.

Meanwhile, I will add two new functions m4_mapall and m4_mapall_sep,
similar to the paradigm of m4_joinall, where the empty sublist implies an
invocation of func with zero arguments, so that the 2.62 semantics of
"m4_map_sep([func], [sep], [list])" are now available as
"m4_mapall_sep([func], [[sep]], [list])".

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

Eric Blake             address@hidden
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


reply via email to

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