lib: Change frrscript_call to call function instead

There is some rather heavy error checking logic in frrscript_call. Normally
I'd put this in the _frrscript_call function, but the error checking needs
to happen before the encoders/decoders in the macro are called.

The error checking looks messy but its really just nested ternary
expressions insite a larger statement expression.

Signed-off-by: Donald Lee <dlqs@gmx.com>
This commit is contained in:
Donald Lee 2021-07-04 23:08:18 +08:00
parent f0cddf950f
commit 40d038d2a1
2 changed files with 59 additions and 30 deletions

View File

@ -138,41 +138,57 @@ static void lua_function_free(struct lua_function_state *lfs)
/* Generic script APIs */ /* Generic script APIs */
int _frrscript_call(struct frrscript *fs) int _frrscript_call_lua(struct lua_function_state *lfs, int nargs)
{ {
int ret = lua_pcall(fs->L, 0, 0, 0); int ret;
ret = lua_pcall(lfs->L, nargs, 1, 0);
switch (ret) { switch (ret) {
case LUA_OK: case LUA_OK:
break; break;
case LUA_ERRRUN: case LUA_ERRRUN:
zlog_err("Script '%s' runtime error: %s", fs->name, zlog_err("Lua hook call '%s' : runtime error: %s", lfs->name,
lua_tostring(fs->L, -1)); lua_tostring(lfs->L, -1));
break; break;
case LUA_ERRMEM: case LUA_ERRMEM:
zlog_err("Script '%s' memory error: %s", fs->name, zlog_err("Lua hook call '%s' : memory error: %s", lfs->name,
lua_tostring(fs->L, -1)); lua_tostring(lfs->L, -1));
break; break;
case LUA_ERRERR: case LUA_ERRERR:
zlog_err("Script '%s' error handler error: %s", fs->name, zlog_err("Lua hook call '%s' : error handler error: %s",
lua_tostring(fs->L, -1)); lfs->name, lua_tostring(lfs->L, -1));
break; break;
case LUA_ERRGCMM: case LUA_ERRGCMM:
zlog_err("Script '%s' garbage collector error: %s", fs->name, zlog_err("Lua hook call '%s' : garbage collector error: %s",
lua_tostring(fs->L, -1)); lfs->name, lua_tostring(lfs->L, -1));
break; break;
default: default:
zlog_err("Script '%s' unknown error: %s", fs->name, zlog_err("Lua hook call '%s' : unknown error: %s", lfs->name,
lua_tostring(fs->L, -1)); lua_tostring(lfs->L, -1));
break; break;
} }
if (ret != LUA_OK) { if (ret != LUA_OK) {
lua_pop(fs->L, 1); lua_pop(lfs->L, 1);
goto done; goto done;
} }
if (lua_gettop(lfs->L) != 1) {
zlog_err(
"Lua hook call '%s': Lua function should return only 1 result",
lfs->name);
ret = 1;
goto done;
}
if (lua_istable(lfs->L, 1) != 1) {
zlog_err(
"Lua hook call '%s': Lua function should return a Lua table",
lfs->name);
ret = 1;
}
done: done:
/* LUA_OK is 0, so we can just return lua_pcall's result directly */ /* LUA_OK is 0, so we can just return lua_pcall's result directly */
return ret; return ret;

View File

@ -119,16 +119,12 @@ void frrscript_register_type_codecs(struct frrscript_codec *codecs);
*/ */
void frrscript_init(const char *scriptdir); void frrscript_init(const char *scriptdir);
#define ENCODE_ARGS(name, value) \ #define ENCODE_ARGS(name, value) ENCODE_ARGS_WITH_STATE(lfs->L, value)
do { \
ENCODE_ARGS_WITH_STATE(L, value); \
lua_setglobal(L, name); \
} while (0)
#define DECODE_ARGS(name, value) \ #define DECODE_ARGS(name, value) \
do { \ do { \
lua_getglobal(L, name); \ lua_getfield(lfs->L, 1, name); \
DECODE_ARGS_WITH_STATE(L, value); \ DECODE_ARGS_WITH_STATE(lfs->L, value); \
} while (0) } while (0)
/* /*
@ -179,7 +175,7 @@ const struct prefix * : lua_decode_noop \
* Returns: * Returns:
* 0 if the script ran successfully, nonzero otherwise. * 0 if the script ran successfully, nonzero otherwise.
*/ */
int _frrscript_call(struct frrscript *fs); int _frrscript_call_lua(struct lua_function_state *lfs, int nargs);
/* /*
* Wrapper for call script. Maps values passed in to their encoder * Wrapper for call script. Maps values passed in to their encoder
@ -191,15 +187,32 @@ int _frrscript_call(struct frrscript *fs);
* Returns: * Returns:
* 0 if the script ran successfully, nonzero otherwise. * 0 if the script ran successfully, nonzero otherwise.
*/ */
#define frrscript_call(fs, ...) \
({ \ #define frrscript_call(fs, f, ...) \
lua_State *L = fs->L; \ ({ \
MAP_LISTS(ENCODE_ARGS, ##__VA_ARGS__); \ struct lua_function_state lookup = {.name = f}; \
int ret = _frrscript_call(fs); \ struct lua_function_state *lfs; \
if (ret == 0) { \ lfs = hash_lookup(fs->lua_function_hash, &lookup); \
MAP_LISTS(DECODE_ARGS, ##__VA_ARGS__); \ lfs == NULL ? ({ \
} \ zlog_err( \
ret; \ "Lua script call: tried to call '%s' in '%s' which was not loaded", \
f, fs->name); \
1; \
}) \
: ({ \
MAP_LISTS(ENCODE_ARGS, ##__VA_ARGS__); \
_frrscript_call_lua(lfs, PP_NARG(__VA_ARGS__)); \
}) != 0 \
? ({ \
zlog_err( \
"Lua script call: '%s' in '%s' returned non-zero exit code", \
f, fs->name); \
1; \
}) \
: ({ \
MAP_LISTS(DECODE_ARGS, ##__VA_ARGS__); \
0; \
}); \
}) })
/* /*