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