diff options
-rw-r--r-- | spec/04-term_spec.lua | 6 | ||||
-rw-r--r-- | src/bitflags.c | 26 | ||||
-rw-r--r-- | src/bitflags.h | 9 | ||||
-rw-r--r-- | src/term.c | 29 |
4 files changed, 49 insertions, 21 deletions
diff --git a/spec/04-term_spec.lua b/spec/04-term_spec.lua index c5b91e6..50fba45 100644 --- a/spec/04-term_spec.lua +++ b/spec/04-term_spec.lua @@ -246,7 +246,7 @@ describe("Terminal:", function() flags.iflag = 0 assert.has.error(function() system.tcsetattr(io.stdin, system.TCSANOW, flags) - end, "bad argument #3 to 'tcsetattr' (table expected, got number)") + end, "bad argument #3, field 'iflag' must be a bitflag object") end) @@ -255,7 +255,7 @@ describe("Terminal:", function() flags.oflag = 0 assert.has.error(function() system.tcsetattr(io.stdin, system.TCSANOW, flags) - end, "bad argument #3 to 'tcsetattr' (table expected, got number)") + end, "bad argument #3, field 'oflag' must be a bitflag object") end) @@ -264,7 +264,7 @@ describe("Terminal:", function() flags.lflag = 0 assert.has.error(function() system.tcsetattr(io.stdin, system.TCSANOW, flags) - end, "bad argument #3 to 'tcsetattr' (table expected, got number)") + end, "bad argument #3, field 'lflag' must be a bitflag object") end) end) diff --git a/src/bitflags.c b/src/bitflags.c index 39f8af0..e397918 100644 --- a/src/bitflags.c +++ b/src/bitflags.c @@ -46,6 +46,32 @@ LSBF_BITFLAG lsbf_checkbitflags(lua_State *L, int index) { return obj->flags; } +// Validates that the given index is a table containing a field 'fieldname' +// which is a bitflag object and returns its value. +// If the index is not a table or the field is not a bitflag object, a Lua +// error is raised. If the bitflag is not present, the default value is returned. +// The stack remains unchanged. +LSBF_BITFLAG lsbf_checkbitflagsfield(lua_State *L, int index, const char *fieldname, LSBF_BITFLAG default_value) { + luaL_checktype(L, index, LUA_TTABLE); + lua_getfield(L, index, fieldname); + + // if null, return default value + if (lua_isnil(L, -1)) { + lua_pop(L, 1); + return default_value; + } + + // check to bitflags + LS_BitFlags *obj = luaL_testudata(L, -1, BITFLAGS_MT_NAME); + if (obj == NULL) { + lua_pop(L, 1); + return luaL_error(L, "bad argument #%d, field '%s' must be a bitflag object", index, fieldname); + } + LSBF_BITFLAG value = obj->flags; + lua_pop(L, 1); + return value; +} + /*** Creates a new bitflag object from the given value. @function system.bitflag diff --git a/src/bitflags.h b/src/bitflags.h index 0e47246..f16b041 100644 --- a/src/bitflags.h +++ b/src/bitflags.h @@ -14,6 +14,15 @@ // The value will be left on the stack. LSBF_BITFLAG lsbf_checkbitflags(lua_State *L, int index); + +// Validates that the given index is a table containing a field 'fieldname' +// which is a bitflag object and returns its value. +// If the index is not a table or the field is not a bitflag object, a Lua +// error is raised. If the bitflag is not present, the default value is returned. +// The stack remains unchanged. +LSBF_BITFLAG lsbf_checkbitflagsfield(lua_State *L, int index, const char *fieldname, LSBF_BITFLAG default_value); + + // Pushes a new bitflag object with the given value onto the stack. // Might raise a Lua error if memory allocation fails. void lsbf_pushbitflags(lua_State *L, LSBF_BITFLAG value); @@ -556,28 +556,13 @@ static int lst_tcsetattr(lua_State *L) int r, i; int fd = get_console_handle(L); // first is the console handle int act = luaL_checkinteger(L, 2); // second is the action to take - luaL_checktype(L, 3, LUA_TTABLE); // third is the termios table with fields r = tcgetattr(fd, &t); if (r == -1) return pusherror(L, NULL); - lua_getfield(L, 3, "iflag"); - if (!lua_isnil(L, -1)) { - t.c_iflag = lsbf_checkbitflags(L, -1); - } - lua_pop(L, 1); - - lua_getfield(L, 3, "oflag"); - if (!lua_isnil(L, -1)) { - t.c_oflag = lsbf_checkbitflags(L, -1); - } - lua_pop(L, 1); - - lua_getfield(L, 3, "lflag"); - if (!lua_isnil(L, -1)) { - t.c_lflag = lsbf_checkbitflags(L, -1); - } - lua_pop(L, 1); + t.c_iflag = lsbf_checkbitflagsfield(L, 3, "iflag", t.c_iflag); + t.c_oflag = lsbf_checkbitflagsfield(L, 3, "oflag", t.c_oflag); + t.c_lflag = lsbf_checkbitflagsfield(L, 3, "lflag", t.c_lflag); // Skipping the others for now @@ -596,6 +581,14 @@ static int lst_tcsetattr(lua_State *L) r = tcsetattr(fd, act, &t); if (r == -1) return pusherror(L, NULL); + +#else + // Windows does not have a tcsetattr function, but we check arguments anyway + get_console_handle(L, 1); // to validate args + luaL_checkinteger(L, 2); + lsbf_checkbitflagsfield(L, 3, "iflag", t.c_iflag); + lsbf_checkbitflagsfield(L, 3, "oflag", t.c_iflag); + lsbf_checkbitflagsfield(L, 3, "lflag", t.c_iflag); #endif lua_pushboolean(L, 1); |