From 031b7bf7df02d75b87a59d016c55faedb8263d93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20B=C3=BChler?= Date: Sat, 28 Jun 2008 20:37:28 +0200 Subject: [PATCH] 2nd commit ;-) --- src/base.c | 17 ++++++ src/base.h | 10 ++++ src/options.c | 66 ++++++++++++++++++++++ src/options.h | 10 +++- src/options_lua.c | 138 ++++++++++++++++++++++++++++++++++++++++++++++ src/options_lua.h | 16 ++++++ src/plugin.h | 25 ++++++--- src/server.c | 16 ++++++ src/wscript | 7 ++- 9 files changed, 295 insertions(+), 10 deletions(-) create mode 100644 src/base.c create mode 100644 src/options.c create mode 100644 src/options_lua.c create mode 100644 src/options_lua.h diff --git a/src/base.c b/src/base.c new file mode 100644 index 0000000..a6dc715 --- /dev/null +++ b/src/base.c @@ -0,0 +1,17 @@ + +#include "base.h" + +static server_option* find_option(server *srv, const char *key) { + return (server_option*) g_hash_table_lookup(srv->options, key); +} + +gboolean parse_option(server *srv, const char *key, option *opt, option_mark *mark) { + server_option *sopt; + + if (!srv || !key || !mark) return FALSE; + + sopt = find_option(srv, key); + if (!sopt) return FALSE; + + return FALSE; +} diff --git a/src/base.h b/src/base.h index 8c5fcbf..d894f8d 100644 --- a/src/base.h +++ b/src/base.h @@ -11,4 +11,14 @@ typedef struct server server; struct connection; typedef struct connection connection; +#include "plugin.h" + +struct server { + GHashTable *plugins; + + size_t option_count; + GHashTable *options; + gpointer *option_def_values; +}; + #endif diff --git a/src/options.c b/src/options.c new file mode 100644 index 0000000..8024865 --- /dev/null +++ b/src/options.c @@ -0,0 +1,66 @@ + +#include "options.h" + +option* option_new_bool(gboolean val) { + option *opt = g_slice_new0(option); + opt->value.opt_bool = val; + return opt; +} + +option* option_new_int(gint val) { + option *opt = g_slice_new0(option); + opt->value.opt_int = val; + return opt; +} + +option* option_new_string(GString *val) { + option *opt = g_slice_new0(option); + opt->value.opt_string = val; + return opt; +} + +option* option_new_list() { + option *opt = g_slice_new0(option); + opt->value.opt_list = g_array_new(FALSE, TRUE, sizeof(option*)); + return opt; +} + +void _option_hash_free_key(gpointer data) { + g_string_free((GString*) data, TRUE); +} + +void _option_hash_free_value(gpointer data) { + option_free((option*) data); +} + +option* option_new_hash() { + option *opt = g_slice_new0(option); + opt->value.opt_hash = g_hash_table_new_full( + (GHashFunc) g_string_hash, (GEqualFunc) g_string_equal, + _option_hash_free_key, _option_hash_free_value); + return opt; +} + + +void option_free(option* opt) { + if (!opt) return; + + switch (opt->type) { + case OPTION_NONE: + case OPTION_BOOLEAN: + case OPTION_INT: + /* Nothing to free */ + break; + case OPTION_STRING: + g_string_free(opt->value.opt_string, TRUE); + break; + case OPTION_LIST: + /* TODO */ + break; + case OPTION_HASH: + /* TODO */ + break; + } + opt->type = OPTION_NONE; + g_slice_free(option, opt); +} diff --git a/src/options.h b/src/options.h index 92b5085..2640c1b 100644 --- a/src/options.h +++ b/src/options.h @@ -9,6 +9,7 @@ typedef struct option option; struct option_mark; typedef struct option_mark option_mark; +#include "base.h" struct option { option_type type; @@ -19,7 +20,7 @@ struct option { /* array of option */ GArray *opt_list; /* hash GString => option */ - GHash *opt_hash; + GHashTable *opt_hash; } value; }; @@ -28,4 +29,11 @@ struct option_mark { gpointer value; }; +LI_API option* option_new_bool(gboolean val); +LI_API option* option_new_int(gint val); +LI_API option* option_new_string(GString *val); +LI_API option* option_new_list(); +LI_API option* option_new_hash(); +LI_API void option_free(option* opt); + #endif diff --git a/src/options_lua.c b/src/options_lua.c new file mode 100644 index 0000000..ad367b1 --- /dev/null +++ b/src/options_lua.c @@ -0,0 +1,138 @@ + +#include "options_lua.h" +#include "log.h" + +/* replace a negative stack index with a positive one, + * so that you don't need to care about push/pop + */ +static int lua_fixindex(lua_State *L, int ndx) { + int top; + if (ndx < 0 && ndx >= -(top = lua_gettop(L))) + ndx = top + ndx + 1; + return ndx; +} + +static option* option_from_lua_table(lua_State *L, int ndx) { + option *opt = NULL, *sub_option; + GArray *list = NULL; + GHashTable *hash = NULL; + int ikey; + GString *skey; + + ndx = lua_fixindex(L, ndx); + lua_pushnil(L); + while (lua_next(L, ndx) != 0) { + switch (lua_type(L, -2)) { + case LUA_TNUMBER: + if (hash) goto mixerror; + if (!list) { + opt = option_new_list(); + list = opt->value.opt_list; + } + ikey = lua_tointeger(L, -2); + if (ikey < 0) { + ERROR("Invalid key < 0: %i - skipping entry", ikey); + lua_pop(L, 1); + continue; + } + sub_option = option_from_lua(L); + if (!sub_option) continue; + if ((size_t) ikey >= list->len) { + g_array_set_size(list, ikey + 1); + } + g_array_index(list, option*, ikey) = sub_option; + break; + + case LUA_TSTRING: + if (list) goto mixerror; + if (!hash) { + opt = option_new_hash(); + hash = opt->value.opt_hash; + } + skey = lua_togstring(L, -2); + if (g_hash_table_lookup(hash, skey)) { + ERROR("Key already exists in hash: '%s' - skipping entry", skey->str); + lua_pop(L, 1); + continue; + } + sub_option = option_from_lua(L); + if (!sub_option) { + g_string_free(skey, TRUE); + continue; + } + g_hash_table_insert(hash, skey, sub_option); + break; + + default: + ERROR("Unexpted key type in table: %s (%i) - skipping entry", lua_typename(L, -1), lua_type(L, -1)); + lua_pop(L, 1); + break; + } + } + + return opt; + +mixerror: + ERROR("%s", "Cannot mix list with hash; skipping remaining part of table"); + lua_pop(L, 2); + return opt; +} + + +option* option_from_lua(lua_State *L) { + option *opt; + + switch (lua_type(L, -1)) { + case LUA_TNIL: + lua_pop(L, 1); + return NULL; + + case LUA_TBOOLEAN: + opt = option_new_bool(lua_toboolean(L, -1)); + lua_pop(L, 1); + return opt; + + case LUA_TNUMBER: + opt = option_new_int(lua_tointeger(L, -1)); + lua_pop(L, 1); + return opt; + + case LUA_TSTRING: + opt = option_new_string(lua_togstring(L, -1)); + lua_pop(L, 1); + return opt; + + case LUA_TTABLE: + opt = option_from_lua_table(L, -1); + lua_pop(L, 1); + return opt; + + case LUA_TLIGHTUSERDATA: + case LUA_TFUNCTION: + case LUA_TUSERDATA: + case LUA_TTHREAD: + case LUA_TNONE: + default: + ERROR("Unexpected lua type: %s (%i)", lua_typename(L, -1), lua_type(L, -1)); + lua_pop(L, 1); + return NULL; + } +} + +GString* lua_togstring(lua_State *L, int ndx) { + const char *buf; + size_t len = 0; + GString *str = NULL; + + if (lua_type(L, ndx) == LUA_TSTRING) { + buf = lua_tolstring(L, ndx, &len); + if (buf) str = g_string_new_len(buf, len); + } else { + lua_pushvalue(L, ndx); + buf = lua_tolstring(L, -1, &len); + if (buf) str = g_string_new_len(buf, len); + lua_pop(L, 1); + } + + return str; +} diff --git a/src/options_lua.h b/src/options_lua.h new file mode 100644 index 0000000..723883a --- /dev/null +++ b/src/options_lua.h @@ -0,0 +1,16 @@ +#ifndef _LIGHTTPD_OPTIONS_LUA_H_ +#define _LIGHTTPD_OPTIONS_LUA_H_ + +#include "options.h" + +#include + +/* converts the top of the stack into an option + * and pops the value + * returns NULL if it couldn't convert the value (still pops it) + */ +LI_API option* option_from_lua(lua_State *L); + +LI_API GString* lua_togstring(lua_State *L, int ndx); + +#endif diff --git a/src/plugin.h b/src/plugin.h index b50b2af..073c5eb 100644 --- a/src/plugin.h +++ b/src/plugin.h @@ -1,8 +1,5 @@ -#ifndef _PLUGIN_H_ -#define _PLUGIN_H_ - -#include "base.h" -#include "option.h" +#ifndef _LIGHTTPD_PLUGIN_H_ +#define _LIGHTTPD_PLUGIN_H_ struct plugin; typedef struct plugin plugin; @@ -10,6 +7,9 @@ typedef struct plugin plugin; struct module_option; typedef struct module_option module_option; +struct server_option; +typedef struct server_option server_option; + #define INIT_FUNC(x) \ LI_EXPORT void * x(server *srv, plugin *) @@ -17,14 +17,15 @@ typedef struct module_option module_option; size_t id; \ ssize_t option_base_ndx +#include "base.h" +#include "options.h" + struct plugin { size_t version; GString *name; /* name of the plugin */ void *(* init) (server *srv, plugin *p); - /* the plugin must free the _content_ of the option */ - option_mark *(* parse_option) (server *src, void *p_d, size_t option_ndx, option *option); gpointer data; @@ -41,8 +42,18 @@ struct module_option { struct server_option { plugin *p; + + /* the plugin must free the _content_ of the option + * opt is zero to get the global default value if nothing is specified + * save result in value + */ + gboolean (* parse_option) (server *srv, void *p_d, size_t ndx, option *opt, gpointer *value); + void (* free_option) (server *srv, void *p_d, size_t ndx, gpointer value); + size_t index, module_index; option_type type; }; +LI_API gboolean parse_option(server *srv, const char *key, option *opt, option_mark *mark); + #endif diff --git a/src/server.c b/src/server.c index f6f6080..0083568 100644 --- a/src/server.c +++ b/src/server.c @@ -1,6 +1,22 @@ +#include "base.h" #include "log.h" +static server* server_new() { + server* srv = g_slice_new0(server); + srv->plugins = g_hash_table_new(g_str_hash, g_str_equal); + srv->options = g_hash_table_new(g_str_hash, g_str_equal); + return srv; +} + +static void server_free(server* srv) { + if (!srv) return; + /* TODO */ + g_slice_free(server, srv); +} + + + int main() { TRACE("%s", "Test!"); return 0; diff --git a/src/wscript b/src/wscript index 1b85ea3..bf10078 100644 --- a/src/wscript +++ b/src/wscript @@ -7,11 +7,14 @@ import Params common_uselib = 'glib ' common_source=''' + base.c chunks.c log.c + options.c + options_lua.c sys-files.c + sys-socket.c ''' -# sys-socket.c main_source = ''' server.c @@ -68,7 +71,7 @@ def build(bld): main.name = 'lighttpd' main.source = common_source + main_source main.target='lighttpd' + env['APPEND'] - main.uselib += 'lighty dl openssl pcre ' + common_uselib + main.uselib += 'lighty dl openssl pcre lua glib ' + common_uselib #lighty_mod(bld, 'mod_access', 'mod_access.c') #lighty_mod(bld, 'mod_alias', 'mod_alias.c')