On Wed, May 14, 2025 at 02:22:55AM -0400, Lawrence Velázquez wrote:
> On Wed, May 14, 2025, at 2:13 AM, Nikolaos Chatzikonstantinou wrote:
> > With
> >     len
> >  we get it back as-is, but with
> >     builtin(`len')
> > we get a warning about too few arguments to len. Is this intentional?
> 
> Yes, according to the manual:
> 
>       Note that `indir' and `builtin' can be used to invoke
>       builtins without arguments, even when they normally require
>       parameters to be recognized; but it will provoke a warning,
>       and result in a void expansion.
> 
> https://www.gnu.org/software/m4/manual/html_node/Builtin.html

Correct for 1.4.x - builtin with only one argument runs that builtin
with 0 arguments, but since the builtin with 0 arguments would
normally output the name it was invoked by but here you are invoking
by the name "builtin", it instead outputs nothing and warns.  But for
1.6, I'm hoping to change the implementation slightly.  Right now,
defn(`define') outputs a magic token, which is only parseable as the
second argument to a define(alias, XXX) call, and which basically
behaves as a quoted string that occupies zero bytes in the output
stream but non-empty in the parser when encountered in the right
context.  I'm thinking of making builtin(`define') output the same
magic token but with an indicator that the token is unquoted, at which
point the magic token can itself be invoked as a macro wherever it is
encountered unquoted.

That would mean that "builtin(`divnum')`'" outputs an unquoted token
for "<divnum>" rather than actually invoking m4_divnum() with 0
arguments, but in turn the unquoted token can then immediately do what
invoking the builtin with zero arguments normally does.  It also means
you could write "builtin(`define')(`a', `b')" instead of
"builtin(`define', `a', `b')"; the effect is the same for that
spelling, but there are corner cases where you can get nicer effects,
but with the warning from 1.4.x removed.

At any rate, with the latest commit (v0.6, 13560d), I'm still seeing
subtle differences between builtins and other functions when using
defn to alias them:

$ m4
define(a,A)define(b,defn(`defn'))define(c,b(`a'))dnl
a b c
A b A
$ m4p
define(a,A)define(b,defn(`defn'))define(c,b(`a'))dnl
a b c
A  A

which may be related to how you output the empty string for
builtin(`defn') while still outputting "`defn'" for defn directly
invoked with zero arguments.

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


Reply via email to