personal/stbuehler/wip
parent
2537bb9d82
commit
2f7359b14c
21 changed files with 689 additions and 130 deletions
@ -0,0 +1,54 @@ |
||||
|
||||
#include "actions_lua.h" |
||||
|
||||
#include <lualib.h> |
||||
#include <lauxlib.h> |
||||
|
||||
#define LUA_ACTION "action*" |
||||
|
||||
action* lua_get_action(lua_State *L, int ndx) { |
||||
if (!lua_isuserdata(L, ndx)) return NULL; |
||||
if (!lua_getmetatable(L, ndx)) return NULL; |
||||
luaL_getmetatable(L, LUA_ACTION); |
||||
if (lua_isnil(L, -1) || lua_isnil(L, -2) || !lua_equal(L, -1, -2)) { |
||||
lua_pop(L, 2); |
||||
return NULL; |
||||
} |
||||
lua_pop(L, 2); |
||||
return *(action**) lua_touserdata(L, ndx); |
||||
} |
||||
|
||||
static int lua_action_gc(lua_State *L) { |
||||
server *srv; |
||||
action **a = (action**) luaL_checkudata(L, 1, LUA_ACTION); |
||||
if (!a || !*a) return 0; |
||||
|
||||
srv = (server*) lua_touserdata(L, lua_upvalueindex(1)); |
||||
action_release(srv, *a); |
||||
return 0; |
||||
} |
||||
|
||||
int lua_push_action(server *srv, lua_State *L, action *a) { |
||||
action **pa; |
||||
|
||||
pa = (action**) lua_newuserdata(L, sizeof(action*)); |
||||
action_acquire(a); |
||||
*pa = a; |
||||
|
||||
if (luaL_newmetatable(L, LUA_ACTION)) { |
||||
lua_pushlightuserdata(L, srv); |
||||
lua_pushcclosure(L, lua_action_gc, 1); |
||||
lua_setfield(L, -2, "__gc"); |
||||
} |
||||
|
||||
lua_setmetatable(L, -2); |
||||
return 1; |
||||
} |
||||
|
||||
action_list* lua_get_actionlist(lua_State *L) { |
||||
action *a; |
||||
if (lua_isnil(L, -1)) return NULL; |
||||
a = lua_get_action(L, 1); |
||||
if (!a) return NULL; |
||||
return action_list_from_action(a); |
||||
} |
@ -0,0 +1,11 @@ |
||||
#ifndef _LIGHTTPD_ACTIONS_LUA_H_ |
||||
#define _LIGHTTPD_ACTIONS_LUA_H_ |
||||
|
||||
#include "actions.h" |
||||
#include <lua.h> |
||||
|
||||
action* lua_get_action(lua_State *L, int ndx); |
||||
int lua_push_action(server *srv, lua_State *L, action *a); |
||||
action_list* lua_get_actionlist(lua_State *L); |
||||
|
||||
#endif |
@ -0,0 +1,46 @@ |
||||
|
||||
#include "condition_lua.h" |
||||
|
||||
#include <lualib.h> |
||||
#include <lauxlib.h> |
||||
|
||||
#define LUA_CONDITION "condition*" |
||||
|
||||
condition* lua_get_condition(lua_State *L, int ndx) { |
||||
if (!lua_isuserdata(L, ndx)) return NULL; |
||||
if (!lua_getmetatable(L, ndx)) return NULL; |
||||
luaL_getmetatable(L, LUA_CONDITION); |
||||
if (lua_isnil(L, -1) || lua_isnil(L, -2) || !lua_equal(L, -1, -2)) { |
||||
lua_pop(L, 2); |
||||
return NULL; |
||||
} |
||||
lua_pop(L, 2); |
||||
return *(condition**) lua_touserdata(L, ndx); |
||||
} |
||||
|
||||
static int lua_condition_gc(lua_State *L) { |
||||
server *srv; |
||||
condition **c = (condition**) luaL_checkudata(L, 1, LUA_CONDITION); |
||||
if (!c || !*c) return 0; |
||||
|
||||
srv = (server*) lua_touserdata(L, lua_upvalueindex(1)); |
||||
condition_release(srv, *c); |
||||
return 0; |
||||
} |
||||
|
||||
int lua_push_condition(server *srv, lua_State *L, condition *c) { |
||||
condition **pc; |
||||
|
||||
pc = (condition**) lua_newuserdata(L, sizeof(condition*)); |
||||
condition_acquire(c); |
||||
*pc = c; |
||||
|
||||
if (luaL_newmetatable(L, LUA_CONDITION)) { |
||||
lua_pushlightuserdata(L, srv); |
||||
lua_pushcclosure(L, lua_condition_gc, 1); |
||||
lua_setfield(L, -2, "__gc"); |
||||
} |
||||
|
||||
lua_setmetatable(L, -2); |
||||
return 1; |
||||
} |
@ -0,0 +1,10 @@ |
||||
#ifndef _LIGHTTPD_CONDITION_LUA_H_ |
||||
#define _LIGHTTPD_CONDITION_LUA_H_ |
||||
|
||||
#include "condition.h" |
||||
#include <lua.h> |
||||
|
||||
condition* lua_get_condition(lua_State *L, int ndx); |
||||
int lua_push_condition(server *srv, lua_State *L, condition *c); |
||||
|
||||
#endif |
@ -0,0 +1,220 @@ |
||||
|
||||
#include "base.h" |
||||
#include "options_lua.h" |
||||
#include "actions_lua.h" |
||||
|
||||
#include <lualib.h> |
||||
#include <lauxlib.h> |
||||
|
||||
typedef int (*LuaWrapper)(server *srv, lua_State *L, gpointer data); |
||||
|
||||
option* lua_params_to_option(server *srv, lua_State *L) { |
||||
option *opt, *subopt; |
||||
switch (lua_gettop(L)) { |
||||
case 0: |
||||
return NULL; |
||||
case 1: |
||||
return option_from_lua(srv, L); |
||||
default: |
||||
opt = option_new_list(); |
||||
while (lua_gettop(L) > 0) { |
||||
if (NULL == (subopt = option_from_lua(srv, L))) { |
||||
ERROR(srv, "%s", "Couldn't convert option to lua"); |
||||
option_free(opt); |
||||
return NULL; |
||||
} |
||||
g_array_append_val(opt->value.opt_list, subopt); |
||||
} |
||||
return opt; |
||||
} |
||||
return NULL; |
||||
} |
||||
|
||||
static int lua_str_hash_index(lua_State *L) { |
||||
server *srv; |
||||
GHashTable *ht; |
||||
LuaWrapper wrapper; |
||||
const char *key; |
||||
gpointer d; |
||||
|
||||
srv = (server*) lua_touserdata(L, lua_upvalueindex(1)); |
||||
ht = (GHashTable*) lua_touserdata(L, lua_upvalueindex(2)); |
||||
wrapper = (LuaWrapper)(intptr_t) lua_touserdata(L, lua_upvalueindex(3)); |
||||
key = luaL_checklstring(L, 2, NULL); |
||||
|
||||
if (key && NULL != (d = g_hash_table_lookup(ht, key))) { |
||||
lua_pop(L, lua_gettop(L)); |
||||
return wrapper(srv, L, d); |
||||
} |
||||
|
||||
lua_pop(L, lua_gettop(L)); |
||||
lua_pushnil(L); |
||||
return 1; |
||||
} |
||||
|
||||
/* Creates a table on the lua stack */ |
||||
static gboolean publish_str_hash(server *srv, lua_State *L, GHashTable *ht, LuaWrapper wrapper) { |
||||
lua_newtable(L); /* { } */ |
||||
lua_newtable(L); /* metatable */ |
||||
|
||||
lua_pushlightuserdata(L, srv); |
||||
lua_pushlightuserdata(L, ht); |
||||
lua_pushlightuserdata(L, (void*)(intptr_t)wrapper); |
||||
lua_pushcclosure(L, lua_str_hash_index, 3); |
||||
|
||||
lua_setfield(L, -2, "__index"); |
||||
lua_setmetatable(L, -2); |
||||
return TRUE; |
||||
} |
||||
|
||||
static int handle_server_action(lua_State *L) { |
||||
server *srv; |
||||
server_action *sa; |
||||
option *opt; |
||||
action *a; |
||||
|
||||
srv = (server*) lua_touserdata(L, lua_upvalueindex(1)); |
||||
sa = (server_action*) lua_touserdata(L, lua_upvalueindex(2)); |
||||
|
||||
opt = lua_params_to_option(srv, L); |
||||
|
||||
TRACE(srv, "%s", "Creating action"); |
||||
|
||||
if (NULL == (a = sa->create_action(srv, sa->p, opt))) { |
||||
lua_pushstring(L, "creating action failed"); |
||||
lua_error(L); |
||||
} |
||||
|
||||
return lua_push_action(srv, L, a); |
||||
} |
||||
|
||||
static int wrap_server_action(server *srv, lua_State *L, gpointer sa) { |
||||
lua_pushlightuserdata(L, srv); |
||||
lua_pushlightuserdata(L, sa); |
||||
lua_pushcclosure(L, handle_server_action, 2); |
||||
return 1; |
||||
} |
||||
|
||||
static int handle_server_setup(lua_State *L) { |
||||
server *srv; |
||||
server_setup *ss; |
||||
option *opt; |
||||
|
||||
srv = (server*) lua_touserdata(L, lua_upvalueindex(1)); |
||||
ss = (server_setup*) lua_touserdata(L, lua_upvalueindex(2)); |
||||
|
||||
opt = lua_params_to_option(srv, L); |
||||
|
||||
TRACE(srv, "%s", "Calling setup"); |
||||
|
||||
if (!ss->setup(srv, ss->p, opt)) { |
||||
lua_pushstring(L, "setup failed"); |
||||
lua_error(L); |
||||
} |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static int wrap_server_setup(server *srv, lua_State *L, gpointer ss) { |
||||
lua_pushlightuserdata(L, srv); |
||||
lua_pushlightuserdata(L, ss); |
||||
lua_pushcclosure(L, handle_server_setup, 2); |
||||
return 1; |
||||
} |
||||
|
||||
static action* action_from_lua(server *srv, lua_State *L) { |
||||
const gchar *optname; |
||||
option *value; |
||||
action *a; |
||||
|
||||
optname = luaL_checklstring(L, -2, NULL); |
||||
if (!optname) { |
||||
lua_pushstring(L, "wrong config argument, expected string"); |
||||
lua_error(L); |
||||
} |
||||
value = option_from_lua(srv, L); |
||||
if (!value) { |
||||
lua_pushstring(L, "missing config value"); |
||||
lua_error(L); |
||||
} |
||||
a = action_new_setting(srv, optname, value); |
||||
if (!a) { |
||||
option_free(value); |
||||
lua_pushstring(L, "couldn't create action from setting"); |
||||
lua_error(L); |
||||
} |
||||
return a; |
||||
} |
||||
|
||||
static int handle_option(lua_State *L) { |
||||
server *srv; |
||||
action *a, *suba; |
||||
|
||||
srv = (server*) lua_touserdata(L, lua_upvalueindex(1)); |
||||
switch (lua_gettop(L)) { |
||||
case 1: |
||||
if (!lua_istable(L, 1)) { |
||||
lua_pushstring(L, "wrong config argument, expected table"); |
||||
lua_error(L); |
||||
} |
||||
a = action_new_list(); |
||||
lua_push_action(srv, L, a); |
||||
lua_insert(L, 1); |
||||
lua_pushnil(L); |
||||
while (lua_next(L, 2) != 0) { |
||||
suba = action_from_lua(srv, L); |
||||
g_array_append_val(a->value.list->actions, suba); |
||||
lua_pop(L, 1); |
||||
} |
||||
lua_pop(L, 1); |
||||
return 1; |
||||
case 2: |
||||
a = action_from_lua(srv, L); |
||||
return lua_push_action(srv, L, a); |
||||
default: |
||||
lua_pushstring(L, "wrong count of arguments to config()"); |
||||
lua_error(L); |
||||
} |
||||
return 0; |
||||
} |
||||
|
||||
gboolean config_lua_load(server *srv, const gchar *filename) { |
||||
lua_State *L; |
||||
|
||||
L = luaL_newstate(); |
||||
luaL_openlibs(L); |
||||
|
||||
if (0 != luaL_loadfile(L, filename)) { |
||||
ERROR(srv, "Loading script '%s' failed: %s", filename, lua_tostring(L, -1)); |
||||
return FALSE; |
||||
} |
||||
|
||||
TRACE(srv, "Loaded config script '%s'", filename); |
||||
|
||||
publish_str_hash(srv, L, srv->setups, wrap_server_setup); |
||||
lua_setfield(L, LUA_GLOBALSINDEX, "setup"); |
||||
|
||||
publish_str_hash(srv, L, srv->actions, wrap_server_action); |
||||
lua_setfield(L, LUA_GLOBALSINDEX, "action"); |
||||
|
||||
lua_pushlightuserdata(L, srv); |
||||
lua_pushcclosure(L, handle_option, 1); |
||||
lua_setfield(L, LUA_GLOBALSINDEX, "option"); |
||||
|
||||
|
||||
if (lua_pcall(L, 0, 1, 0)) { |
||||
ERROR(srv, "lua_pcall(): %s", lua_tostring(L, -1)); |
||||
return FALSE; |
||||
} |
||||
|
||||
lua_pop(L, 1); /* pop the ret-value */ |
||||
|
||||
lua_getfield(L, LUA_GLOBALSINDEX, "action"); |
||||
srv->mainactionlist = lua_get_actionlist(L); |
||||
lua_pop(L, 1); |
||||
|
||||
assert(lua_gettop(L) == 0); |
||||
|
||||
lua_close(L); |
||||
return TRUE; |
||||
} |
Loading…
Reference in new issue