diff options
Diffstat (limited to 'src/lcurses/_helpers.c')
-rw-r--r-- | src/lcurses/_helpers.c | 210 |
1 files changed, 210 insertions, 0 deletions
diff --git a/src/lcurses/_helpers.c b/src/lcurses/_helpers.c new file mode 100644 index 0000000..d229d15 --- /dev/null +++ b/src/lcurses/_helpers.c @@ -0,0 +1,210 @@ +/* + * POSIX library for Lua 5.1, 5.2 & 5.3. + * (c) Gary V. Vaughan <gary@vaughan.pe>, 2013-2017 + * (c) Reuben Thomas <rrt@sc3d.org> 2010-2013 + * (c) Natanael Copa <natanael.copa@gmail.com> 2008-2010 + * Clean up and bug fixes by Leo Razoumov <slonik.az@gmail.com> 2006-10-11 + * Luiz Henrique de Figueiredo <lhf@tecgraf.puc-rio.br> 07 Apr 2006 23:17:49 + * Based on original by Claudio Terra for Lua 3.x. + * With contributions by Roberto Ierusalimschy. + * With documentation from Steve Donovan 2012 + */ + +#ifndef LCURSES__HELPERS_C +#define LCURSES__HELPERS_C 1 + +#include <errno.h> +#include <grp.h> +#include <pwd.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include <unistd.h> /* for _POSIX_VERSION */ + +#include <ncurses.h> +#include <term.h> + +/* NetBSD's default curses implementation is not quite complete. This + disables those missing functions unless linked to ncurses instead. */ +#if defined NCURSES_VERSION || !defined __NetBSD__ +# define LCURSES_POSIX_COMPLIANT 1 +#endif + +#include "../lua.h" +#include "../lualib.h" +#include "../lauxlib.h" + +#if LUA_VERSION_NUM < 503 +# define lua_isinteger lua_isnumber +# if LUA_VERSION_NUM == 501 +# include "compat-5.2.c" +# endif +#endif + +#if LUA_VERSION_NUM == 502 || LUA_VERSION_NUM == 503 +# define lua_objlen lua_rawlen +# define lua_strlen lua_rawlen +# define luaL_openlib(L,n,l,nup) luaL_setfuncs((L),(l),(nup)) +# define luaL_register(L,n,l) (luaL_newlib(L,l)) +#endif + +#ifndef STREQ +# define STREQ(a, b) (strcmp (a, b) == 0) +#endif + +/* Mark unused parameters required only to match a function type + specification. */ +#ifdef __GNUC__ +# define LCURSES_UNUSED(x) UNUSED_ ## x __attribute__((__unused__)) +#else +# define LCURSES_UNUSED(x) UNUSED_ ## x +#endif + +/* LCURSES_STMT_BEG/END are used to create macros that expand to a + single compound statement in a portable way. */ +#if defined __GNUC__ && !defined __STRICT_ANSI__ && !defined __cplusplus +# define LCURSES_STMT_BEG (void)( +# define LCURSES_STMT_END ) +#else +# if (defined sun || defined __sun__) +# define LCURSES_STMT_BEG if (1) +# define LCURSES_STMT_END else (void)0 +# else +# define LCURSES_STMT_BEG do +# define LCURSES_STMT_END while (0) +# endif +#endif + + +/* The extra indirection to these macros is required so that if the + arguments are themselves macros, they will get expanded too. */ +#define LCURSES__SPLICE(_s, _t) _s##_t +#define LCURSES_SPLICE(_s, _t) LCURSES__SPLICE(_s, _t) + +#define LCURSES__STR(_s) #_s +#define LCURSES_STR(_s) LCURSES__STR(_s) + +/* The +1 is to step over the leading '_' that is required to prevent + premature expansion of MENTRY arguments if we didn't add it. */ +#define LCURSES__STR_1(_s) (#_s + 1) +#define LCURSES_STR_1(_s) LCURSES__STR_1(_s) + +#define LCURSES_CONST(_f) LCURSES_STMT_BEG { \ + lua_pushinteger(L, _f); \ + lua_setfield(L, -2, #_f); \ + } LCURSES_STMT_END + +#define LCURSES_FUNC(_s) {LCURSES_STR_1(_s), (_s)} + +#define pushokresult(b) pushboolresult((int) (b) == OK) + +#ifndef errno +extern int errno; +#endif + + +/* ========================= * + * Bad argument diagnostics. * + * ========================= */ + + +static int +argtypeerror(lua_State *L, int narg, const char *expected) +{ + const char *got = luaL_typename(L, narg); + return luaL_argerror(L, narg, + lua_pushfstring(L, "%s expected, got %s", expected, got)); +} + +static lua_Integer +checkinteger(lua_State *L, int narg, const char *expected) +{ + lua_Integer d = lua_tointeger(L, narg); + if (d == 0 && !lua_isinteger(L, narg)) + argtypeerror(L, narg, expected); + return d; +} + +static int +checkint(lua_State *L, int narg) +{ + return (int)checkinteger(L, narg, "int"); +} + + +static chtype +checkch(lua_State *L, int narg) +{ + if (lua_isnumber(L, narg)) + return (chtype)checkint(L, narg); + if (lua_isstring(L, narg)) + return *lua_tostring(L, narg); + + return argtypeerror(L, narg, "int or char"); +} + + +static chtype +optch(lua_State *L, int narg, chtype def) +{ + if (lua_isnoneornil(L, narg)) + return def; + if (lua_isnumber(L, narg) || lua_isstring(L, narg)) + return checkch(L, narg); + return argtypeerror(L, narg, "int or char or nil"); +} + + +static int +optint(lua_State *L, int narg, lua_Integer def) +{ + if (lua_isnoneornil(L, narg)) + return (int) def; + return (int)checkinteger(L, narg, "int or nil"); +} + +#define pushboolresult(b) (lua_pushboolean(L, (b)), 1) + +#define pushintresult(n) (lua_pushinteger(L, (n)), 1) + +#define pushstringresult(s) (lua_pushstring(L, (s)), 1) + + + +/* ================== * + * Utility functions. * + * ================== */ + +#define pushintegerfield(k,v) LCURSES_STMT_BEG { \ + lua_pushinteger(L, (lua_Integer) v); lua_setfield(L, -2, k); \ +} LCURSES_STMT_END + +#define pushnumberfield(k,v) LCURSES_STMT_BEG { \ + lua_pushnumber(L, (lua_Number) v); lua_setfield(L, -2, k); \ +} LCURSES_STMT_END + +#define pushstringfield(k,v) LCURSES_STMT_BEG { \ + if (v) { \ + lua_pushstring(L, (const char *) v); \ + lua_setfield(L, -2, k); \ + } \ +} LCURSES_STMT_END + +#define pushliteralfield(k,v) LCURSES_STMT_BEG { \ + if (v) { \ + lua_pushliteral(L, v); \ + lua_setfield(L, -2, k); \ + } \ +} LCURSES_STMT_END + +#define settypemetatable(t) LCURSES_STMT_BEG { \ + if (luaL_newmetatable(L, t) == 1) \ + pushliteralfield("_type", t); \ + lua_setmetatable(L, -2); \ +} LCURSES_STMT_END + +#define setintegerfield(_p, _n) pushintegerfield(LCURSES_STR(_n), _p->_n) +#define setnumberfield(_p, _n) pushnumberfield(LCURSES_STR(_n), _p->_n) +#define setstringfield(_p, _n) pushstringfield(LCURSES_STR(_n), _p->_n) + +#endif /*LCURSES__HELPERS_C*/ |