Re: m4_patsubst equivalent of: sed -e 's~(~%28~g' -e 's~)~%29~g'

Eric Blake <[email protected]> Wed, 29 Aug 2018 11:53:15 -0500
Newsgroups gmane.comp.gnu.m4.general
Organization Red Hat, Inc.
Message-ID <[email protected]>
On 08/29/2018 11:38 AM, [email protected] wrote:
> Is there an m4 macro in one of the autoconf m4 libs that can do
> two substitutions like?:
> 
>      sed -e 's~(~%28~g' -e 's~)~%29~g'
> 
> or does this require calling m4_patsubst twice with nesting and
> perhaps m4_pushdef / m4_popdef?  I want to do this substitution on the
> expanded results of another m4 macro.

You mention the autoconf m4 libs; have you looked at 
m4_bpatsubsts(string, regex-1, subst-1, regex-2, subst-2, ...)

But under the hood, native m4 patsubst can only do one substitution per 
macro invitation, so you'd have to arrange your two separate pattern 
substitutions via multiple calls (whether nested or sequential); similar 
to how m4_bpatsubsts in Autoconf is already set to perform those 
multiple calls.

> 
> In general is there a suggested approach to this, without resorting to 'sed'?

Looking at how autoconf did it may be informative:

m4_define([m4_bpatsubsts],
[m4_if([$#], 0, [m4_fatal([$0: too few arguments: $#])],
        [$#], 1, [m4_fatal([$0: too few arguments: $#: $1])],
        [$#], 2, [m4_unquote(m4_builtin([patsubst], [[$1]], [$2]))],
        [$#], 3, [m4_unquote(m4_builtin([patsubst], [[$1]], [$2], [$3]))],
        [_$0($@m4_if(m4_eval($# & 1), 0, [,]))])])
m4_define([_m4_bpatsubsts],
[m4_if([$#], 2, [$1],
        [$0(m4_builtin([patsubst], [[$1]], [$2], [$3]),
            m4_shift3($@))])])

Basically, the iteration performs the substitution on an over-quoted 
string for each pattern to be substituted, then removes the 
overquotation at the end of the recursion, with the drawback that ^ and 
$ anchors don't work quite as expected (but your example sed script did 
not use anchors).

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3266
Virtualization:  qemu.org | libvirt.org