diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/wdye/wdye.c | 206 |
1 files changed, 185 insertions, 21 deletions
diff --git a/tools/wdye/wdye.c b/tools/wdye/wdye.c index 6ab903f..a827732 100644 --- a/tools/wdye/wdye.c +++ b/tools/wdye/wdye.c @@ -155,7 +155,6 @@ pty_fork (int *ptrfdm, char **slave_name, static struct { lua_State *L; ///< Lua state - struct poller poller; ///< Event loop } g; @@ -183,6 +182,96 @@ xlua_getfield (lua_State *L, int idx, const char *name, lua_typename (L, found), lua_typename (L, expected)); } +static void +xlua_newtablecopy (lua_State *L, int idx, int first, int last) +{ + int len = last - first + 1; + lua_createtable (L, len, 0); + if (idx < 0) + idx--; + + for (lua_Integer i = 0; i < len; i++) + { + lua_rawgeti (L, idx, first + i); + lua_rawseti (L, -2, 1 + i); + } +} + +// --- Patterns ---------------------------------------------------------------- + +#define XLUA_PATTERN_METATABLE "pattern" + +enum pattern_kind +{ + PATTERN_RE, ///< Regular expression match + PATTERN_TIMEOUT, ///< Timeout + PATTERN_EOF, ///< EOF condition + PATTERN_DEFAULT, ///< Either timeout or EOF +}; + +struct pattern +{ + enum pattern_kind kind; ///< Tag + int ref_process; ///< Process for RE/EOF/DEFAULT + regex_t *re; ///< Regular expression for RE + int64_t timeout; ///< Timeout for TIMEOUT/DEFAULT + bool notransfer; ///< Do not consume process buffer + int ref_values; ///< Return values as a table reference + + struct error *e; ///< Error buffer + + // TODO(p): + // - ref_values is a LUA_TTABLE with arbitrary values. + // - https://www.lua.org/source/5.3/ltablib.c.html#unpack + // to then return everything as multiple values. + // - Function values will be executed and expanded. +}; + +static struct pattern * +xlua_pattern_new (lua_State *L, enum pattern_kind kind) +{ + struct pattern *self = lua_newuserdata (L, sizeof *self); + luaL_setmetatable (L, XLUA_PATTERN_METATABLE); + memset (self, 0, sizeof *self); + + self->kind = kind; + self->ref_process = LUA_NOREF; + self->timeout = -1; + self->ref_values = LUA_NOREF; + return self; +} + +static int +xlua_pattern_gc (lua_State *L) +{ + struct pattern *self = luaL_checkudata (L, 1, XLUA_PATTERN_METATABLE); + luaL_unref (L, LUA_REGISTRYINDEX, self->ref_process); + if (self->re) + regex_free (self->re); + luaL_unref (L, LUA_REGISTRYINDEX, self->ref_values); + if (self->e) + error_free (self->e); + return 0; +} + +static bool +xlua_pattern_readtimeout (struct pattern *self, lua_State *L, int idx) +{ + lua_rawgeti (L, idx, 1); + bool ok = lua_isinteger (L, -1); + lua_Integer v = lua_tointeger (L, -1); + lua_pop (L, 1); + if (ok) + self->timeout = v; + return ok; +} + +static luaL_Reg xlua_pattern_table[] = +{ + { "__gc", xlua_pattern_gc }, + { NULL, NULL } +}; + // --- Process ----------------------------------------------------------------- #define XLUA_PROCESS_METATABLE "process" @@ -220,25 +309,13 @@ xlua_process_gc (lua_State *L) } static int -xlua_process_expect (lua_State *L) -{ - struct process *self = luaL_checkudata (L, 1, XLUA_PROCESS_METATABLE); - // TODO(p): Arguments. - // TODO(p): Keep reading input into a buffer, - // until there's a match. - // - It seems we need to keep the buffer within the process object, - // because we can read too much. - return 0; -} - -static int xlua_process_send (lua_State *L) { struct process *self = luaL_checkudata (L, 1, XLUA_PROCESS_METATABLE); int nargs = lua_gettop (L); for (int i = 2; i <= nargs; i++) if (!lua_isstring (L, i)) - return luaL_error (L, "need string arguments"); + return luaL_argerror (L, i, "need string arguments"); for (int i = 2; i <= nargs; i++) { @@ -254,11 +331,47 @@ xlua_process_send (lua_State *L) return 1; } +static int +xlua_process_re (lua_State *L) +{ + struct process *self = luaL_checkudata (L, 1, XLUA_PROCESS_METATABLE); + luaL_checktype (L, 2, LUA_TTABLE); + if (lua_gettop (L) != 2) + return luaL_error (L, "too many arguments"); + + struct pattern *pattern = xlua_pattern_new (L, PATTERN_RE); + + lua_getfield (L, 2, "nocase"); + int flags = REG_EXTENDED; + if (lua_toboolean (L, -1)) + flags |= REG_ICASE; + + lua_getfield (L, 2, "notransfer"); + if (lua_toboolean (L, -1)) + pattern->notransfer = true; + + lua_rawgeti (L, 2, 1); + if (!lua_isstring (L, -1)) + return luaL_error (L, "expected regular expression"); + + size_t len = 0; + const char *re = lua_tolstring (L, -1, &len); + if (!(pattern->re = regex_compile (re, flags, &pattern->e))) + return luaL_error (L, "%s", pattern->e->message); + lua_pop (L, 3); + + xlua_newtablecopy (L, 2, 2, lua_rawlen (L, 2)); + pattern->ref_values = luaL_ref (L, LUA_REGISTRYINDEX); + return 1; +} + static luaL_Reg xlua_process_table[] = { { "__gc", xlua_process_gc }, - { "expect", xlua_process_expect }, { "send", xlua_process_send }, + { "re", xlua_process_re }, +// { "eof", xlua_process_eof }, +// { "default", xlua_process_default }, { NULL, NULL } }; @@ -457,10 +570,65 @@ xlua_spawn (lua_State *L) return 1; } +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +static int +xlua_expect (lua_State *L) +{ + int nargs = lua_gettop (L); + for (int i = 1; i <= nargs; i++) + luaL_checkudata (L, i, XLUA_PATTERN_METATABLE); + + struct poller poller; + poller_init (&poller); + + // TODO(p): Add pattern terminals to an event loop, + // add timers, run the loop... + + for (int i = 1; i <= nargs; i++) + { + struct pattern *pattern = + luaL_checkudata (L, i, XLUA_PATTERN_METATABLE); + switch (pattern->kind) + { + } + } + + // TODO(p): Keep reading input into a buffer, + // until there's a match. + // - It seems we need to keep the buffer within the process object, + // because we can read too much. + + poller_free (&poller); + return 0; +} + +// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +static int +xlua_timeout (lua_State *L) +{ + luaL_checktype (L, 1, LUA_TTABLE); + if (lua_gettop (L) != 1) + return luaL_error (L, "too many arguments"); + + struct pattern *pattern = xlua_pattern_new (L, PATTERN_TIMEOUT); + int first = 1, last = lua_rawlen (L, 1); + if (xlua_pattern_readtimeout (pattern, L, 1)) + first++; + + xlua_newtablecopy (L, 1, first, last); + pattern->ref_values = luaL_ref (L, LUA_REGISTRYINDEX); + return 1; +} + static luaL_Reg xlua_library[] = { - { "spawn", xlua_spawn }, - { NULL, NULL } + { "spawn", xlua_spawn }, + { "expect", xlua_expect }, + { "timeout", xlua_timeout }, +// { "continue", xlua_continue }, + { NULL, NULL } }; // --- Initialisation, event handling ------------------------------------------ @@ -513,8 +681,6 @@ main (int argc, char *argv[]) luaL_setfuncs (g.L, xlua_process_table, 0); lua_pop (g.L, 1); - poller_init (&g.poller); - const char *path = argv[1]; lua_pushcfunction (g.L, xlua_error_handler); if (luaL_loadfile (g.L, path) @@ -525,7 +691,5 @@ main (int argc, char *argv[]) } lua_pop (g.L, 1); lua_close (g.L); - - poller_free (&g.poller); return 0; } |