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