bug-m4
[Top][All Lists]
Advanced

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

Re: m4 fails to expand macros after changequote


From: Eric Blake
Subject: Re: m4 fails to expand macros after changequote
Date: Tue, 16 May 2023 11:33:55 -0500
User-agent: NeoMutt/20230512

On Tue, May 16, 2023 at 12:16:17PM +0200, Andreas F. Borchert wrote:
> 
> Here is a minimal example that demonstrates the problem:
> 
>    changequote({,})dnl
>    define(P1, {changequote([,])`}$[]1{'changequote()})dnl
>    changequote()dnl

This line is your problem.  Per POSIX,
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/m4.html

changequote
   The changequote macro shall set the begin-quote and end-quote
   strings. With no arguments, the quote strings shall be set to the
   default values (that is, `'). The behavior is unspecified if there
   is a single argument or either argument is null. With two non-null
   arguments, the first argument shall become the begin-quote string
   and the second argument shall become the end-quote string. Systems
   shall support quote strings of at least five characters.

You have called changequote() which passes a single null argument,
rather than a well-specified behavior of zero arguments or two
non-null arguments.  But even though POSIX says behavior is
unspecified, 'info m4 changequote' does declare what GNU does:

 -- Builtin: changequote ([START = ‘`’], [END = ‘'’])
     This sets START as the new begin-quote delimiter and END as the new
     end-quote delimiter.  If both arguments are missing, the default
     quotes (‘`’ and ‘'’) are used.  If START is void, then quoting is
     disabled.  Otherwise, if END is missing or void, the default
     end-quote delimiter (‘'’) is used.  The quote delimiters can be of
     any length.

Thus, you have managed to disable quoting altogether (m4's choice of
disabling quoting may seem an odd decision, but it was made decades
ago before I started m4 development, and since it is documented, it is
one that is unlikely to be changed due to back-compat concerns).  I
don't know if Solaris m4 documents their behavior, but based on their
behavior and your email, I'm assuming they treat "changequote()" as a
synonym to "changequote".

But I can offer some advice: to be portable to both GNU and Solaris
m4, write:

changequote`'dnl

Since ` is neither ( nor a macro name character, it forces a call of
changequote with zero parameters per POSIX, which in turn restores
quoting to normal, so that the `' is then parsed as an empty string
after quotes are removed.

>    define(`foo', `$1 is not P1')dnl

Given your mistake in the line above, this was defining the macro
named "`foo'" (5-character name, non-invokable without indir) rather
than the macro "foo" (3-character name),...

>    foo(`bar')

...so this line sees no macro invocations whatsoever, but neither does
it recognize `' as quote characters.

> 
> Running this example with GNU m4:
> 
>    theon$ m4 --version
>    m4 (GNU M4) 1.4.19
>    Copyright (C) 2021 Free Software Foundation, Inc.
>    License GPLv3+: GNU GPL version 3 or later 
> <https://gnu.org/licenses/gpl.html>.
>    This is free software: you are free to change and redistribute it.
>    There is NO WARRANTY, to the extent permitted by law.
> 
>    Written by René Seindal.
>    theon$ m4 bug.m4
>    foo(`bar')
>    theon$ 
> 
> In comparison, running this with Solaris 11.4 m4:
> 
>    theon$ /usr/bin/m4 bug.m4
>    bar is not `$1'
>    theon$

Thanks for a nice report, even if the bug turned out to be in your
script rather than in GNU m4 proper.

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




reply via email to

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