On Tue, Oct 07, 2025 at 02:08:17PM -0400, R. Clayton wrote: ... > But LNK() is scoped to LINKS() and I'd like the code to reflect that. Seems > easy too: > > $ cat x > #! /bin/bash > > m4 -P <<'eof!' > m4_define(LINKS, > `m4_define(LNK, `hrf(flquotes-$1.html, $1)') > LNK(m4_eval($1 + 1)) > m4_undefine(`LNK') > ') > > LINKS(2025) > eof! > > $ ./x > > > > hrf(flquotes-2025.html, 2025) > > > > $ > > except it doesn't work. It seems $1 in LNK() is being bound at definition > time, and I can't figure out a quoting structure to delay the binding to call > time. Is that sort of thing possible, and if so, how do I do it?
Yes, you are correct that $1 in the definition of LINKS is bound before the m4_define(LNK...) is expanded. But what you want is possible; here's one way: m4_define(`LINKS', `m4_define(`LNK', `hrf(flquotes-$'`1.html, $'`1)') LNK(m4_eval($1 + 1)) m4_undefine(`LNK') ') LINKS(2025) The trick here was to use consecutive string concatenation, defining LNK to the strings `hrf(flquotes-$', `1.html, $', and `1)' each in turn, so that its overall content assigned to LNK is "hrf(flquotes-$1.html, $1)", even though a literal $1 did not appear in that part of the definition of LINKS. I also took the liberty of adding quotes around the macro name being defined, as that is safer if you ever want to redefine a macro. You may encounter situations where you cannot break up a macro body into consecutive strings; there are other approaches that can still defer the injection of $1 into a secondary macro defined in a first, such as this that passes a literal "1" as the $2 argument to LINKS, so that the "$$2" text becomes a literal "$1" before the nested m4_define (also taking the liberty to optimize m4_eval into m4_incr, and use pushdef/popdef instead of define/undefine for a bit more safety in case LNK is used as a macro elsewhere): m4_define(`LINKS', `m4_pushdef(`LNK', `hrf(flquotes-$$2.html, $$2)') LNK(m4_incr($1)) m4_popdef(`LNK') ') LINKS(2025, 1) -- Eric Blake, Principal Software Engineer Red Hat, Inc. Virtualization: qemu.org | libguestfs.org
