On Mon, May 19, 2025 at 04:14:09AM -0400, Nikolaos Chatzikonstantinou wrote:
> > > Good catch. The info manual mentions arguments like $10 to mean the
> > > 10th argument will be phased out of GNU m4. Should I still emulate
> > > that or should I keep the single-digit-only expansion?
> >
> > For now I went with multi digit expansions to keep the 1.4.20 behavior.

You absolutely must support multi-digit parameters for GNU
compatability: Autoconf _depends_ on being able to access $10 as the
tenth parameter (and not the concatenation of $1 with literal "0") in
order to implement foreach() in O(N) rather than O(N^2) effort with m4
1.4.x.  In branch-1.6, where shift($@) recursion is no longer O(N^2),
that requirement goes away (autoconf already has code in place in
lib/m4sugar/foreach.m4 to probe whether to rely on $10 or on fast
shift($@)).  The comment in that file is telling:

# This file is designed to overcome the quadratic nature of $@
# recursion by writing a variant of m4_foreach that uses m4_for rather
# than $@ recursion to operate on the list.  This involves more macro
# expansions, but avoids the need to rescan a quadratic number of
# arguments, making these replacements very attractive for M4 1.4.x.
# On the other hand, in any version of M4, expanding additional macros
# costs additional time; therefore, in M4 1.6, where $@ recursion uses
# fewer macros, these replacements actually pessimize performance.
# Additionally, the use of $10 to mean the tenth argument violates
# POSIX; although all versions of m4 1.4.x support this meaning, a
# future m4 version may switch to take it as the first argument
# concatenated with a literal 0, so the implementations in this file
# are not future-proof.  Thus, this file is conditionally included as
# part of m4_init(), only when it is detected that M4 probably has
# quadratic behavior (ie. it lacks the macro __m4_version__).

That said, POSIX says that $10 _must_ be the first parameter
concatenated with literal "0", and there ARE other m4 scripts out
there that depend on the POSIX behavior.  If you invoke 'm4 -G', you
are specifically asking for that alternative behavior.  For future m4
versions, the solution is as follows: POSIX says that "${" may start
an implementation-defined interpretation rather than being a literal
"$" and "{" (you can always output a literal "$" and "{" by separating
the two with quote characters).  M4 1.4 will not take advantage of
that (for back-compat reasons), but at least branch-2.0 has taken the
tack that "${{10}}" is unambiguously interpreted as the tenth
parameter, "${10}" is unambiguously interpreted as literal "$"
followed by literal "{10}" (why? because existing m4 scripts that
output shell scripts don't have to be scrubbed for intentional uses of
"${1}" to access the shell's first variable rather than m4's first
parameter), and "$10" will obey POSIX as outputting "$1" concatenated
with "0" unconditionally.  I haven't yet decided whether to port that
change into branch-1.6 (Autoconf _should_ be prepared for it, but I
would also add a debugmode() flag to opt in to warning suspicious
uses).

Autoconf doesn't care if m4p implements -G (Autoconf depends on GNU
mode).  But if you want m4p to be a drop-in replacement for m4 in
other uses, you need to implement -G (aka --traditional) eventually.

> 
> I also implemented --freeze-state and --reload-state just now. The
> produced files are not compatible with GNU m4's frozen files, but I
> don't think that's an issue, right? I need to implement a better test
> suite so that I can include tests that include all sorts of
> command-line options, so that's going to be the next goal.

It _is_ an issue (although not necessarily your highest priority).
The m4 manual documents the format of frozen files, and says that they
are cross-platform compatible.  And on my machine:

$ rpm -ql autoconf | grep m4f
/usr/share/autoconf/autoconf/autoconf.m4f
/usr/share/autoconf/autotest/autotest.m4f
/usr/share/autoconf/m4sugar/m4sh.m4f
/usr/share/autoconf/m4sugar/m4sugar.m4f

shows that Autoconf depends on being able to install frozen files
built by one version of m4 for reuse by Autoconf - if m4p is ever
going to be a drop-in replacement, it MUST be able to parse those
files the same as m4 would.

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.
Virtualization:  qemu.org | libguestfs.org


Reply via email to