diff options
author | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2010-12-29 16:26:25 +0100 |
---|---|---|
committer | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2010-12-29 16:26:25 +0100 |
commit | d3148268857e01116d5d3c99ac0a43bc6a54b13c (patch) | |
tree | 6ae273025ef73942c0ac748e715a7f281a6af114 /src/call.c | |
download | lspipat-d3148268857e01116d5d3c99ac0a43bc6a54b13c.tar.gz |
Diffstat (limited to 'src/call.c')
-rw-r--r-- | src/call.c | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/src/call.c b/src/call.c new file mode 100644 index 0000000..818ebdb --- /dev/null +++ b/src/call.c @@ -0,0 +1,86 @@ +/* + * LSPIPAT - LUA SPIPAT WRAPPER + * Copyright (C) 2010, Robin Haberkorn + * License: LGPL + * + * CORE: CALL OPERATIONS + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <string.h> + +#include "lspipat.h" + +static void +callFncHandler(VString matched, void *global __attribute__((unused)), void *local) +{ + struct callRefs *call = local; + lua_State *L = call->cb.L; + + lua_rawgeti(L, LUA_REGISTRYINDEX, call->cb.function); + lua_pushlstring(L, matched.ptr, matched.len); + lua_rawgeti(L, LUA_REGISTRYINDEX, call->cb.cookie); +#if 0 + lua_rawgeti(L, LUA_REGISTRYINDEX, *(int *)global); +#endif + + lua_call(L, 2, 0); +} + +struct callOperator { + struct pat *(*call)(struct pat *, void (*)(VString, void *, void *), void *); +}; + + /* TODO: local cookie support, this would also allow helper functions for assignment to global variables */ + /* at least one parameter is a pattern, the lvalue has to be it */ +static int +genericCallOperator(lua_State *L, struct callOperator spipat) +{ + PATTERN_WRAPPER *new; + struct callRefs *call; + + PATTERN_WRAPPER *lvalue = luaL_checkudata(L, 1, PATTERN_MT); + if (!lvalue->pattern) + L_ERROR(L_FREED); + if (!lua_isfunction(L, 2)) + L_ERROR(L_TYPE); + + if (!(new = lua_newuserdata(L, sizeof(PATTERN_WRAPPER)))) + L_ERROR(L_ALLOC); + memset(new, 0, sizeof(PATTERN_WRAPPER)); + lua_insert(L, 1); /* move wrapper below lvalue */ + + new->type = PATTERN_CALL; + + call = &new->u.call; + call->cb.L = L; + call->cb.cookie = LUA_REFNIL; + call->cb.function = luaL_ref(L, LUA_REGISTRYINDEX); + call->pattern = luaL_ref(L, LUA_REGISTRYINDEX); + /* wrapper at top again */ + + new->pattern = spipat.call(lvalue->pattern, callFncHandler, call); + if (!new->pattern) + L_ERROR(L_ALLOC); + + luaL_getmetatable(L, PATTERN_MT); + lua_setmetatable(L, -2); + + return 1; +} + +#define STDCALLOP(LFNC, SPIFNC) \ + LUA_SIG(LFNC) \ + { \ + return genericCallOperator(L, (struct callOperator) { \ + .call = SPIFNC \ + }); \ + } + +STDCALLOP(l_op_call_immed, spipat_call_immed) +STDCALLOP(l_op_call_onmatch, spipat_call_onmatch) + +#undef STDCALLOP |