From d3148268857e01116d5d3c99ac0a43bc6a54b13c Mon Sep 17 00:00:00 2001 From: Robin Haberkorn Date: Wed, 29 Dec 2010 16:26:25 +0100 Subject: initial checkin (v0.1 release) --- src/uint.c | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 src/uint.c (limited to 'src/uint.c') diff --git a/src/uint.c b/src/uint.c new file mode 100644 index 0000000..1a0530b --- /dev/null +++ b/src/uint.c @@ -0,0 +1,128 @@ +/* + * LSPIPAT - LUA SPIPAT WRAPPER + * Copyright (C) 2010, Robin Haberkorn + * License: LGPL + * + * CORE: UNSIGNED INTEGER PRIMITIVES/CONSTRUCTORS + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "lspipat.h" + +static unsigned +uintFncHandler(void *global __attribute__((unused)), void *local) +{ + struct simplefncRefs *simplefnc = local; + lua_State *L = simplefnc->cb.L; + + int val; + + lua_rawgeti(L, LUA_REGISTRYINDEX, simplefnc->cb.function); + lua_rawgeti(L, LUA_REGISTRYINDEX, simplefnc->cb.cookie); +#if 0 + lua_rawgeti(L, LUA_REGISTRYINDEX, *(int *)global); +#endif + + lua_call(L, 1, 1); + + if (lua_isnil(L, -1)) { + lua_pop(L, 1); + return 0; /* default value */ + } + + if (!lua_isnumber(L, -1)) { + lua_pop(L, 1); + L_ERROR(L_RETURN); /* FIXME: is it safe to raise errors? */ + } + + val = lua_tointeger(L, -1); + lua_pop(L, 1); + if (val < 0) + L_ERROR(L_RETURN); + + return (unsigned)val; +} + +struct uintPrimitive { + struct pat *(*uint)(unsigned); + struct pat *(*fnc)(unsigned (*)(void *, void *), void *); +}; + +static int +genericUIntPrimitive(lua_State *L, struct uintPrimitive spipat) +{ + int top = lua_gettop(L); + PATTERN_WRAPPER *new; + + if (!(new = lua_newuserdata(L, sizeof(PATTERN_WRAPPER)))) + L_ERROR(L_ALLOC); + memset(new, 0, sizeof(PATTERN_WRAPPER)); + + switch (lua_type(L, 1)) { + case LUA_TNONE: + case LUA_TNIL: + case LUA_TNUMBER: + case LUA_TSTRING: { + int val; + + luaL_argcheck(L, top < 2, top, L_NUMBER); + val = luaL_optint(L, 1, 0); + luaL_argcheck(L, val >= 0, 1, L_VALUE); + + new->pattern = spipat.uint((unsigned)val); + break; + } + case LUA_TFUNCTION: { + struct simplefncRefs *simplefnc; + + luaL_argcheck(L, top == 1 || top == 2, top, L_NUMBER); + + lua_insert(L, 1); /* move wrapper to bottom */ + if (top == 1) + lua_pushnil(L); /* cookie will be LUA_REFNIL */ + + new->type = PATTERN_SIMPLEFNC; + + simplefnc = &new->u.simplefnc; + simplefnc->cb.L = L; + simplefnc->cb.cookie = luaL_ref(L, LUA_REGISTRYINDEX); + simplefnc->cb.function = luaL_ref(L, LUA_REGISTRYINDEX); + /* wrapper at top again */ + + new->pattern = spipat.fnc(uintFncHandler, simplefnc); + break; + } + default: + return luaL_argerror(L, 1, L_TYPE); + } + + if (!new->pattern) + L_ERROR(L_ALLOC); + + luaL_getmetatable(L, PATTERN_MT); + lua_setmetatable(L, -2); + + return 1; +} + +#define STDUINTPRIM(LFNC, SPIFNC) \ + LUA_SIG(LFNC) \ + { \ + return genericUIntPrimitive(L, (struct uintPrimitive) { \ + .uint = SPIFNC, \ + .fnc = SPIFNC##_fnc \ + }); \ + } + +STDUINTPRIM(l_primitive_len, spipat_len) +STDUINTPRIM(l_primitive_pos, spipat_pos) +STDUINTPRIM(l_primitive_rpos, spipat_rpos) +STDUINTPRIM(l_primitive_rtab, spipat_rtab) +STDUINTPRIM(l_primitive_tab, spipat_tab) + +#undef STDUINTPRIM -- cgit v1.2.3