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:
parent
717a3f7ecf
commit
67abf72ef5
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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([
|
||||
|
|
Loading…
Reference in New Issue