Pass parametric macro options and arguments to Lua natively (#1092)

We already have the macro arguments in an ARGV that's suitable for
passing to Lua, just store it in the macro buffer for passing around.
As macros can nest arbitrarily, we need to store and restore the mb
args which is a bit hacky, but much less trouble than changing all the
related functions to pass argound an argv which only one function
ever uses. Ditto with the macro entry itself, which is needed to pass
around the options (and name, and maybe something else too later).

Besides all the normal rpm defined macros for arguments and options,
parametric Lua macros now get pre-processed options and arguments
in native local tables "opt" and "arg" for much more pleasant access.
"opt" and "arg" tables are always there even if no options or arguments
were passed, this avoids having to deal with multiple cases and test
for nil's all over the place.

Fixes: #1092
This commit is contained in:
Panu Matilainen 2020-10-08 11:10:40 +03:00
parent 717a3f7ecf
commit 67abf72ef5
3 changed files with 62 additions and 2 deletions

View File

@ -39,6 +39,32 @@ The above is a silly example and doesn't even begin to show how powerful a featu
%sources %{lua: for i, s in ipairs(sources) do print(s.." ") end}
```
Parametric Lua macros receive their options and arguments as two local
tables "opt" and "arg", where "opt" holds processed option values keyed by
the option character, and "arg" contains arguments numerically indexed.
These tables are always present regardless of whether options or arguments
were actually passed to simplify use.
```
%foo(a:b) %{lua:
if opt.b then
print('do b')
else
print('or not')
end
if opt.a == 's' then
print('do s')
end
if #arg == 0 then
print('no arguments :(')
else
for i = 1, #arg do
print(arg[i])
end
end
}
```
## Available Lua extensions in RPM
In addition to all Lua standard libraries (subject to the Lua version rpm is linked to), a few custom extensions are available in the RPM internal Lua interpreter. These can be used in all contexts where the internal Lua can be used.

View File

@ -111,6 +111,8 @@ typedef struct MacroBuf_s {
int macro_trace; /*!< Pre-print macro to expand? */
int expand_trace; /*!< Post-print macro expansion? */
int flags; /*!< Flags to control behavior */
rpmMacroEntry me; /*!< Current macro (or NULL if anonymous) */
ARGV_t args; /*!< Current macro arguments (or NULL) */
rpmMacroContext mc;
} * MacroBuf;
@ -857,6 +859,8 @@ freeArgs(MacroBuf mb)
popMacro(mc, me->name);
}
mb->level--;
mb->args = argvFree(mb->args);
mb->me = NULL;
}
static void splitQuoted(ARGV_t *av, const char * str, const char * seps)
@ -1010,7 +1014,8 @@ grabArgs(MacroBuf mb, const rpmMacroEntry me, const char * se,
free(args);
exit:
argvFree(argv);
mb->me = me;
mb->args = argv;
return cont;
}
@ -1056,8 +1061,19 @@ static void doLua(MacroBuf mb, int chkexist, int negate, const char * f, size_t
char *scriptbuf = xmalloc(gn + 1);
char *printbuf;
rpmMacroContext mc = mb->mc;
rpmMacroEntry me = mb->me;
int odepth = mc->depth;
int olevel = mc->level;
const char *opts = NULL;
const char *name = NULL;
ARGV_t args = NULL;
if (me) {
opts = me->opts;
name = me->name;
if (mb->args)
args = mb->args;
}
if (g != NULL && gn > 0)
memcpy(scriptbuf, g, gn);
@ -1065,7 +1081,7 @@ static void doLua(MacroBuf mb, int chkexist, int negate, const char * f, size_t
rpmluaPushPrintBuffer(lua);
mc->depth = mb->depth;
mc->level = mb->level;
if (rpmluaRunScript(lua, scriptbuf, NULL, NULL, NULL) == -1)
if (rpmluaRunScript(lua, scriptbuf, name, opts, args) == -1)
mb->error = 1;
mc->depth = odepth;
mc->level = olevel;
@ -1540,6 +1556,8 @@ expandMacro(MacroBuf mb, const char *src, size_t slen)
}
/* Setup args for "%name " macros with opts */
rpmMacroEntry prevme = mb->me;
ARGV_t prevarg = mb->args;
if (me && me->opts != NULL) {
const char *xe = grabArgs(mb, me, fe, lastc);
if (xe != NULL)
@ -1557,6 +1575,8 @@ expandMacro(MacroBuf mb, const char *src, size_t slen)
/* Free args for "%name " macros with opts */
if (me->opts != NULL)
freeArgs(mb);
mb->args = prevarg;
mb->me = prevme;
s = se;
}

View File

@ -517,6 +517,20 @@ runroot rpm --eval '%{lua:print(5*5)}'
])
AT_CLEANUP
AT_SETUP([lua macro arguments])
AT_KEYWORDS([macros lua])
AT_SKIP_IF([$LUA_DISABLED])
AT_CHECK([[
runroot rpm \
--define "foo(a:) %{lua:print(opt.a, arg[1])}" \
--define "bar() %{lua:print(rpm.expand('%foo -a'..arg[2]..' '..arg[1]))}" \
--eval '%bar 5 3'
]],
[0],
[3 5
])
AT_CLEANUP
AT_SETUP([lua rpm extensions 1])
AT_KEYWORDS([macros lua])
AT_CHECK([