Browse Source

Renamed option -> value, some other minor/related renames; added option_value as

datatype for the value of options (union for ptr/gin64)
personal/stbuehler/wip
Stefan Bühler 14 years ago
parent
commit
091f122aad
  1. 3
      src/CMakeLists.txt
  2. 48
      src/actions.c
  3. 2
      src/actions.h
  4. 78
      src/condition.c
  5. 2
      src/condition.h
  6. 2
      src/condition_lua.c
  7. 34
      src/config_lua.c
  8. 2
      src/config_parser.h
  9. 390
      src/config_parser.rl
  10. 22
      src/connection.c
  11. 2
      src/connection.h
  12. 24
      src/http_headers.c
  13. 4
      src/log.c
  14. 283
      src/options.c
  15. 76
      src/options.h
  16. 61
      src/plugin.c
  17. 28
      src/plugin.h
  18. 203
      src/plugin_core.c
  19. 2
      src/response.c
  20. 6
      src/server.c
  21. 6
      src/server.h
  22. 232
      src/value.c
  23. 58
      src/value.h
  24. 48
      src/value_lua.c
  25. 4
      src/value_lua.h

3
src/CMakeLists.txt

@ -289,6 +289,7 @@ SET(COMMON_SRC
sys-socket.c
url_parser.c
utils.c
value.c
worker.c
plugin_core.c
@ -299,7 +300,7 @@ SET(COMMON_SRC ${COMMON_SRC}
actions_lua.c
condition_lua.c
config_lua.c
options_lua.c
value_lua.c
)
ENDIF(WITH_LUA)

48
src/actions.c

@ -18,23 +18,23 @@ void action_release(server *srv, action *a) {
if (g_atomic_int_dec_and_test(&a->refcount)) {
switch (a->type) {
case ACTION_TSETTING:
release_option(srv, &a->value.setting);
release_option(srv, &a->data.setting);
break;
case ACTION_TFUNCTION:
if (a->value.function.free) {
a->value.function.free(srv, a->value.function.param);
if (a->data.function.free) {
a->data.function.free(srv, a->data.function.param);
}
break;
case ACTION_TCONDITION:
condition_release(srv, a->value.condition.cond);
action_release(srv, a->value.condition.target);
action_release(srv, a->value.condition.target_else);
condition_release(srv, a->data.condition.cond);
action_release(srv, a->data.condition.target);
action_release(srv, a->data.condition.target_else);
break;
case ACTION_TLIST:
for (i = a->value.list->len; i-- > 0; ) {
action_release(srv, g_array_index(a->value.list, action*, i));
for (i = a->data.list->len; i-- > 0; ) {
action_release(srv, g_array_index(a->data.list, action*, i));
}
g_array_free(a->value.list, TRUE);
g_array_free(a->data.list, TRUE);
break;
}
g_slice_free(action, a);
@ -51,7 +51,7 @@ action *action_new_setting(option_set setting) {
a->refcount = 1;
a->type = ACTION_TSETTING;
a->value.setting = setting;
a->data.setting = setting;
return a;
}
@ -62,9 +62,9 @@ action *action_new_function(ActionFunc func, ActionFree ffree, gpointer param) {
a = g_slice_new(action);
a->refcount = 1;
a->type = ACTION_TFUNCTION;
a->value.function.func = func;
a->value.function.free = ffree;
a->value.function.param = param;
a->data.function.func = func;
a->data.function.free = ffree;
a->data.function.param = param;
return a;
}
@ -75,7 +75,7 @@ action *action_new_list() {
a = g_slice_new(action);
a->refcount = 1;
a->type = ACTION_TLIST;
a->value.list = g_array_new(FALSE, TRUE, sizeof(action *));
a->data.list = g_array_new(FALSE, TRUE, sizeof(action *));
return a;
}
@ -86,9 +86,9 @@ action *action_new_condition(condition *cond, action *target, action *target_els
a = g_slice_new(action);
a->refcount = 1;
a->type = ACTION_TCONDITION;
a->value.condition.cond = cond;
a->value.condition.target = target;
a->value.condition.target_else = target_else;
a->data.condition.cond = cond;
a->data.condition.target = target;
a->data.condition.target_else = target_else;
return a;
}
@ -139,7 +139,7 @@ static void action_stack_pop(server *srv, action_stack *as) {
static action* action_stack_element_action(action_stack_element *ase) {
action *a = ase->act;
if (a->type == ACTION_TLIST) {
return ase->pos < a->value.list->len ? g_array_index(a->value.list, action*, ase->pos) : NULL;
return ase->pos < a->data.list->len ? g_array_index(a->data.list, action*, ase->pos) : NULL;
} else {
return ase->pos == 0 ? a : NULL;
}
@ -162,10 +162,10 @@ action_result action_execute(connection *con) {
switch (a->type) {
case ACTION_TSETTING:
con->options[a->value.setting.ndx] = a->value.setting.value;
con->options[a->data.setting.ndx] = a->data.setting.value;
break;
case ACTION_TFUNCTION:
res = a->value.function.func(con, a->value.function.param);
res = a->data.function.func(con, a->data.function.param);
switch (res) {
case ACTION_GO_ON:
case ACTION_FINISHED:
@ -178,11 +178,11 @@ action_result action_execute(connection *con) {
}
break;
case ACTION_TCONDITION:
if (condition_check(con, a->value.condition.cond)) {
action_enter(con, a->value.condition.target);
if (condition_check(con, a->data.condition.cond)) {
action_enter(con, a->data.condition.target);
}
else if (a->value.condition.target_else) {
action_enter(con, a->value.condition.target_else);
else if (a->data.condition.target_else) {
action_enter(con, a->data.condition.target_else);
}
break;
case ACTION_TLIST:

2
src/actions.h

@ -59,7 +59,7 @@ struct action {
action_func function;
GArray* list; /** array of (action*) */
} value;
} data;
};
/* no new/free function, so just use the struct direct (i.e. not a pointer) */

78
src/condition.c

@ -160,7 +160,7 @@ condition* condition_new_int(server *srv, comp_operator_t op, condition_lvalue *
case CONFIG_COND_LT:
case CONFIG_COND_LE:
c = condition_new(op, lvalue);
c->rvalue.type = COND_VALUE_INT;
c->rvalue.type = COND_VALUE_NUMBER;
c->rvalue.i = i;
return c;
}
@ -174,7 +174,7 @@ condition* condition_new_int(server *srv, comp_operator_t op, condition_lvalue *
static void condition_free(condition *c) {
condition_lvalue_release(c->lvalue);
switch (c->rvalue.type) {
case COND_VALUE_INT:
case COND_VALUE_NUMBER:
/* nothing to free */
break;
case COND_VALUE_STRING:
@ -250,70 +250,70 @@ const char* cond_lvalue_to_string(cond_lvalue_t t) {
/* COND_VALUE_STRING and COND_VALUE_REGEXP only */
static gboolean condition_check_eval_string(connection *con, condition *cond) {
const char *value = "";
const char *val = "";
gboolean result = FALSE;
switch (cond->lvalue->type) {
case COMP_REQUEST_LOCALIP:
value = con->local_addr_str->str;
val = con->local_addr_str->str;
break;
case COMP_REQUEST_REMOTEIP:
value = con->remote_addr_str->str;
val = con->remote_addr_str->str;
break;
case COMP_REQUEST_PATH:
value = con->request.uri.path->str;
val = con->request.uri.path->str;
break;
case COMP_REQUEST_HOST:
value = con->request.uri.host->str;
val = con->request.uri.host->str;
break;
case COMP_REQUEST_SCHEME:
value = con->is_ssl ? "https" : "http";
val = con->is_ssl ? "https" : "http";
break;
case COMP_REQUEST_QUERY_STRING:
value = con->request.uri.query->str;
val = con->request.uri.query->str;
break;
case COMP_REQUEST_METHOD:
value = con->request.http_method_str->str;
val = con->request.http_method_str->str;
break;
case COMP_PHYSICAL_PATH:
value = con->physical.path->str;
val = con->physical.path->str;
break;
case COMP_PHYSICAL_PATH_EXISTS:
/* TODO: physical path exists */
break;
case COMP_REQUEST_HEADER:
http_header_get_fast(con->wrk->tmp_str, con->request.headers, GSTR_LEN(cond->lvalue->key));
value = con->wrk->tmp_str->str;
val = con->wrk->tmp_str->str;
break;
case COMP_PHYSICAL_SIZE:
/* TODO: physical size */
g_string_printf(con->wrk->tmp_str, "%"L_GOFFSET_FORMAT, (goffset) 0);
value = con->wrk->tmp_str->str;
val = con->wrk->tmp_str->str;
break;
case COMP_REQUEST_CONTENT_LENGTH:
g_string_printf(con->wrk->tmp_str, "%"L_GOFFSET_FORMAT, con->request.content_length);
value = con->wrk->tmp_str->str;
val = con->wrk->tmp_str->str;
break;
}
switch (cond->op) {
case CONFIG_COND_EQ:
result = g_str_equal(value, cond->rvalue.string->str);
result = g_str_equal(val, cond->rvalue.string->str);
break;
case CONFIG_COND_NE:
result = g_str_equal(value, cond->rvalue.string->str);
result = g_str_equal(val, cond->rvalue.string->str);
break;
case CONFIG_COND_PREFIX:
result = g_str_has_prefix(value, cond->rvalue.string->str);
result = g_str_has_prefix(val, cond->rvalue.string->str);
break;
case CONFIG_COND_NOPREFIX:
result = !g_str_has_prefix(value, cond->rvalue.string->str);
result = !g_str_has_prefix(val, cond->rvalue.string->str);
break;
case CONFIG_COND_SUFFIX:
result = g_str_has_suffix(value, cond->rvalue.string->str);
result = g_str_has_suffix(val, cond->rvalue.string->str);
break;
case CONFIG_COND_NOSUFFIX:
result = !g_str_has_suffix(value, cond->rvalue.string->str);
result = !g_str_has_suffix(val, cond->rvalue.string->str);
break;
case CONFIG_COND_MATCH:
case CONFIG_COND_NOMATCH:
@ -339,32 +339,32 @@ static gboolean condition_check_eval_string(connection *con, condition *cond) {
static gboolean condition_check_eval_int(connection *con, condition *cond) {
gint64 value;
gint64 val;
switch (cond->lvalue->type) {
case COMP_REQUEST_CONTENT_LENGTH:
value = con->request.content_length;
val = con->request.content_length;
case COMP_PHYSICAL_SIZE:
value = con->physical.size;
val = con->physical.size;
break;
default:
CON_ERROR(con, "couldn't get int value for '%s', using -1", cond_lvalue_to_string(cond->lvalue->type));
value = -1;
val = -1;
}
if (value > 0) switch (cond->op) {
if (val > 0) switch (cond->op) {
case CONFIG_COND_EQ: /** == */
return (value == cond->rvalue.i);
return (val == cond->rvalue.i);
case CONFIG_COND_NE: /** != */
return (value != cond->rvalue.i);
return (val != cond->rvalue.i);
case CONFIG_COND_LT: /** < */
return (value < cond->rvalue.i);
return (val < cond->rvalue.i);
case CONFIG_COND_LE: /** <= */
return (value <= cond->rvalue.i);
return (val <= cond->rvalue.i);
case CONFIG_COND_GT: /** > */
return (value > cond->rvalue.i);
return (val > cond->rvalue.i);
case CONFIG_COND_GE: /** >= */
return (value >= cond->rvalue.i);
return (val >= cond->rvalue.i);
case CONFIG_COND_PREFIX:
case CONFIG_COND_NOPREFIX:
case CONFIG_COND_SUFFIX:
@ -424,10 +424,10 @@ static gboolean ip_in_net(condition_rvalue *target, condition_rvalue *network) {
/* CONFIG_COND_IP and CONFIG_COND_NOTIP only */
static gboolean condition_check_eval_ip(connection *con, condition *cond) {
condition_rvalue ipval;
const char *value = NULL;
const char *val = NULL;
gboolean result = FALSE;
ipval.type = COND_VALUE_INT;
ipval.type = COND_VALUE_NUMBER;
switch (cond->lvalue->type) {
case COMP_REQUEST_LOCALIP:
@ -443,13 +443,13 @@ static gboolean condition_check_eval_ip(connection *con, condition *cond) {
return (cond->op == CONFIG_COND_NOTIP);
break;
case COMP_REQUEST_HOST:
value = con->request.uri.host->str;
val = con->request.uri.host->str;
break;
case COMP_REQUEST_SCHEME:
CON_ERROR(con, "%s", "Cannot parse request.scheme as ip");
return (cond->op == CONFIG_COND_NOTIP);
case COMP_REQUEST_QUERY_STRING:
value = con->request.uri.query->str;
val = con->request.uri.query->str;
break;
case COMP_REQUEST_METHOD:
CON_ERROR(con, "%s", "Cannot request.method as ip");
@ -462,7 +462,7 @@ static gboolean condition_check_eval_ip(connection *con, condition *cond) {
break;
case COMP_REQUEST_HEADER:
http_header_get_fast(con->wrk->tmp_str, con->request.headers, GSTR_LEN(cond->lvalue->key));
value = con->wrk->tmp_str->str;
val = con->wrk->tmp_str->str;
break;
case COMP_PHYSICAL_SIZE:
case COMP_REQUEST_CONTENT_LENGTH:
@ -471,8 +471,8 @@ static gboolean condition_check_eval_ip(connection *con, condition *cond) {
break;
}
if (ipval.type == COND_VALUE_INT) {
if (!value || !condition_parse_ip(&ipval, value))
if (ipval.type == COND_VALUE_NUMBER) {
if (!val || !condition_parse_ip(&ipval, val))
return (cond->op == CONFIG_COND_NOTIP);
}
@ -507,7 +507,7 @@ gboolean condition_check(connection *con, condition *cond) {
case COND_VALUE_REGEXP:
#endif
return condition_check_eval_string(con, cond);
case COND_VALUE_INT:
case COND_VALUE_NUMBER:
return condition_check_eval_int(con, cond);
case COND_VALUE_SOCKET_IPV4:
case COND_VALUE_SOCKET_IPV6:

2
src/condition.h

@ -71,7 +71,7 @@ struct condition_lvalue {
};
typedef enum {
COND_VALUE_INT,
COND_VALUE_NUMBER,
COND_VALUE_STRING,
#ifdef HAVE_PCRE_H
COND_VALUE_REGEXP,

2
src/condition_lua.c

@ -1,6 +1,6 @@
#include "condition_lua.h"
#include "options_lua.h"
#include "value_lua.h"
#include <lualib.h>
#include <lauxlib.h>

34
src/config_lua.c

@ -1,7 +1,7 @@
#include "config_lua.h"
#include "condition_lua.h"
#include "options_lua.h"
#include "value_lua.h"
#include "actions_lua.h"
#include <lualib.h>
@ -9,25 +9,25 @@
typedef int (*LuaWrapper)(server *srv, lua_State *L, gpointer data);
static option* lua_params_to_option(server *srv, lua_State *L) {
option *opt, *subopt;
static value* lua_params_to_value(server *srv, lua_State *L) {
value *val, *subval;
switch (lua_gettop(L)) {
case 0:
return NULL;
case 1:
return option_from_lua(srv, L);
return value_from_lua(srv, L);
default:
opt = option_new_list();
g_array_set_size(opt->value.opt_list, lua_gettop(L));
val = value_new_list();
g_array_set_size(val->data.list, lua_gettop(L));
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);
if (NULL == (subval = value_from_lua(srv, L))) {
ERROR(srv, "%s", "Couldn't convert value from lua");
value_free(val);
return NULL;
}
g_array_index(opt->value.opt_list, option*, lua_gettop(L)) = subopt;
g_array_index(val->data.list, value*, lua_gettop(L)) = subval;
}
return opt;
return val;
}
return NULL;
}
@ -72,17 +72,17 @@ static gboolean publish_str_hash(server *srv, lua_State *L, GHashTable *ht, LuaW
static int handle_server_action(lua_State *L) {
server *srv;
server_action *sa;
option *opt;
value *val;
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);
val = lua_params_to_value(srv, L);
/* TRACE(srv, "%s", "Creating action"); */
if (NULL == (a = sa->create_action(srv, sa->p, opt))) {
if (NULL == (a = sa->create_action(srv, sa->p, val))) {
lua_pushstring(L, "creating action failed");
lua_error(L);
}
@ -100,16 +100,16 @@ static int wrap_server_action(server *srv, lua_State *L, gpointer sa) {
static int handle_server_setup(lua_State *L) {
server *srv;
server_setup *ss;
option *opt;
value *val;
srv = (server*) lua_touserdata(L, lua_upvalueindex(1));
ss = (server_setup*) lua_touserdata(L, lua_upvalueindex(2));
opt = lua_params_to_option(srv, L);
val = lua_params_to_value(srv, L);
TRACE(srv, "%s", "Calling setup");
if (!ss->setup(srv, ss->p, opt)) {
if (!ss->setup(srv, ss->p, val)) {
lua_pushstring(L, "setup failed");
lua_error(L);
}

2
src/config_parser.h

@ -49,7 +49,7 @@ struct config_parser_context_t {
GHashTable *uservars; /* var.foo */
GQueue *action_list_stack; /* first entry is current action list */
GQueue *option_stack; /* stack of option* */
GQueue *option_stack; /* stack of value* */
GQueue *condition_stack; /* stack of condition* */
/* information about currenty parsed file */

390
src/config_parser.rl

@ -36,65 +36,65 @@
# basic types
action boolean {
option *o;
value *o;
o = option_new_bool(*ctx->mark == 't' ? TRUE : FALSE);
o = value_new_bool(*ctx->mark == 't' ? TRUE : FALSE);
g_queue_push_head(ctx->option_stack, o);
_printf("got boolean %s in line %zd\n", *ctx->mark == 't' ? "true" : "false", ctx->line);
}
action integer {
option *o;
value *o;
guint i = 0;
for (gchar *c = ctx->mark; c < fpc; c++)
i = i * 10 + *c - 48;
o = option_new_int(i);
/* push option onto stack */
o = value_new_number(i);
/* push value onto stack */
g_queue_push_head(ctx->option_stack, o);
_printf("got integer %d in line %zd\n", i, ctx->line);
}
action integer_suffix {
option *o;
value *o;
GString *str;
o = g_queue_peek_head(ctx->option_stack);
str = g_string_new_len(ctx->mark, fpc - ctx->mark);
if (g_str_equal(str->str, "kbyte")) o->value.opt_int *= 1024;
else if (g_str_equal(str->str, "mbyte")) o->value.opt_int *= 1024 * 1024;
else if (g_str_equal(str->str, "gbyte")) o->value.opt_int *= 1024 * 1024 * 1024;
if (g_str_equal(str->str, "kbyte")) o->data.number *= 1024;
else if (g_str_equal(str->str, "mbyte")) o->data.number *= 1024 * 1024;
else if (g_str_equal(str->str, "gbyte")) o->data.number *= 1024 * 1024 * 1024;
else if (g_str_equal(str->str, "kbit")) o->value.opt_int *= 1000;
else if (g_str_equal(str->str, "mbit")) o->value.opt_int *= 1000 * 1000;
else if (g_str_equal(str->str, "gbit")) o->value.opt_int *= 1000 * 1000 * 1000;
else if (g_str_equal(str->str, "kbit")) o->data.number *= 1000;
else if (g_str_equal(str->str, "mbit")) o->data.number *= 1000 * 1000;
else if (g_str_equal(str->str, "gbit")) o->data.number *= 1000 * 1000 * 1000;
else if (g_str_equal(str->str, "min")) o->value.opt_int *= 60;
else if (g_str_equal(str->str, "hours")) o->value.opt_int *= 60 * 60;
else if (g_str_equal(str->str, "days")) o->value.opt_int *= 60 * 60 * 24;
else if (g_str_equal(str->str, "min")) o->data.number *= 60;
else if (g_str_equal(str->str, "hours")) o->data.number *= 60 * 60;
else if (g_str_equal(str->str, "days")) o->data.number *= 60 * 60 * 24;
g_string_free(str, TRUE);
_printf("got int with suffix: %d\n", o->value.opt_int);
_printf("got int with suffix: %d\n", o->data.number);
/* make sure there was no overflow that led to negative numbers */
if (o->value.opt_int < 0) {
if (o->data.number < 0) {
log_warning(srv, NULL, "integer value overflowed in line %zd of %s", ctx->line, ctx->filename);
return FALSE;
}
}
action string {
option *o;
value *o;
GString *str;
str = g_string_new_len(ctx->mark+1, fpc - ctx->mark - 2);
o = option_new_string(str);
o = value_new_string(str);
g_queue_push_head(ctx->option_stack, o);
_printf("got string %s", "");
@ -104,27 +104,27 @@
# advanced types
action list_start {
option *o;
value *o;
/* create new list option and put it on stack, list entries are put in it by getting the previous option from the stack */
o = option_new_list();
/* create new list value and put it on stack, list entries are put in it by getting the previous value from the stack */
o = value_new_list();
g_queue_push_head(ctx->option_stack, o);
fcall list_scanner;
}
action list_push {
option *o, *l;
value *o, *l;
/* pop current option from stack and append it to the new top of the stack option (the list) */
/* pop current value from stack and append it to the new top of the stack value (the list) */
o = g_queue_pop_head(ctx->option_stack);
l = g_queue_peek_head(ctx->option_stack);
assert(l->type == OPTION_LIST);
assert(l->type == VALUE_LIST);
g_array_append_val(l->value.opt_list, o);
g_array_append_val(l->data.list, o);
_printf("list_push %s\n", option_type_string(o->type));
_printf("list_push %s\n", value_type_string(o->type));
}
action list_end {
@ -132,31 +132,31 @@
}
action hash_start {
option *o;
value *o;
/* create new hash option and put it on stack, if a key-value pair is encountered, get it by walking 2 steps back the stack */
o = option_new_hash();
/* create new hash value and put it on stack, if a key-value pair is encountered, get it by walking 2 steps back the stack */
o = value_new_hash();
g_queue_push_head(ctx->option_stack, o);
fcall hash_scanner;
}
action hash_push {
option *k, *v, *h; /* key value hashtable */
value *k, *v, *h; /* key value hashtable */
GString *str;
v = g_queue_pop_head(ctx->option_stack);
k = g_queue_pop_head(ctx->option_stack);
h = g_queue_peek_head(ctx->option_stack);
/* duplicate key so option can be free'd */
str = g_string_new_len(k->value.opt_string->str, k->value.opt_string->len);
/* duplicate key so value can be free'd */
str = g_string_new_len(k->data.string->str, k->data.string->len);
g_hash_table_insert(h->value.opt_hash, str, v);
g_hash_table_insert(h->data.hash, str, v);
_printf("hash_push: %s: %s => %s\n", option_type_string(k->type), option_type_string(v->type), option_type_string(h->type));
_printf("hash_push: %s: %s => %s\n", value_type_string(k->type), value_type_string(v->type), value_type_string(h->type));
option_free(k);
value_free(k);
}
action hash_end {
@ -178,18 +178,18 @@
}
action keyvalue_end {
option *k, *v, *l;
value *k, *v, *l;
/* we have a key and a value on the stack; convert them to a list with 2 elements */
v = g_queue_pop_head(ctx->option_stack);
k = g_queue_pop_head(ctx->option_stack);
l = option_new_list();
l = value_new_list();
g_array_append_val(l->value.opt_list, k);
g_array_append_val(l->value.opt_list, v);
g_array_append_val(l->list, k);
g_array_append_val(l->list, v);
_printf("key-value pair: %s => %s in line %zd\n", option_type_string(k->type), option_type_string(v->type), ctx->line);
_printf("key-value pair: %s => %s in line %zd\n", value_type_string(k->type), value_type_string(v->type), ctx->line);
/* push list on the stack */
g_queue_push_head(ctx->option_stack, l);
@ -200,7 +200,7 @@
}
action value {
option *o;
value *o;
o = g_queue_peek_head(ctx->option_stack);
@ -212,18 +212,18 @@
guint i = 0;
gboolean negative = FALSE;
if (o->type != OPTION_STRING) {
log_error(srv, NULL, "can only cast strings to integers, %s given", option_type_string(o->type));
if (o->type != VALUE_STRING) {
log_error(srv, NULL, "can only cast strings to integers, %s given", value_type_string(o->type));
return FALSE;
}
if (o->value.opt_string->str[0] == '-') {
if (o->data.string->str[0] == '-') {
negative = TRUE;
i++;
}
for (; i < o->value.opt_string->len; i++) {
gchar c = o->value.opt_string->str[i];
for (; i < o->data.string->len; i++) {
gchar c = o->data.string->str[i];
if (c < '0' || c > '9') {
log_error(srv, NULL, "%s", "cast(int) parameter doesn't look like a numerical string");
return FALSE;
@ -234,29 +234,29 @@
if (negative)
x *= -1;
g_string_free(o->value.opt_string, TRUE);
o->value.opt_int = x;
o->type = OPTION_INT;
g_string_free(o->data.string, TRUE);
o->data.number = x;
o->type = VALUE_NUMBER;
}
else if (ctx->cast == CFG_PARSER_CAST_STR) {
/* cast integer to string */
GString *str;
if (o->type != OPTION_INT) {
log_error(srv, NULL, "can only cast integers to strings, %s given", option_type_string(o->type));
if (o->type != VALUE_NUMBER) {
log_error(srv, NULL, "can only cast integers to strings, %s given", value_type_string(o->type));
return FALSE;
}
str = g_string_sized_new(0);
g_string_printf(str, "%d", o->value.opt_int);
o->value.opt_string = str;
o->type = OPTION_STRING;
g_string_printf(str, "%" G_GINT64_FORMAT, o->data.number);
o->data.string = str;
o->type = VALUE_STRING;
}
ctx->cast = CFG_PARSER_CAST_NONE;
}
_printf("value (%s) in line %zd\n", option_type_string(o->type), ctx->line);
_printf("value (%s) in line %zd\n", value_type_string(o->type), ctx->line);
}
action value_statement_start {
@ -274,7 +274,7 @@
action value_statement {
/* value (+|-|*|/) value */
/* compute new value out of the two */
option *l, *r, *o;
value *l, *r, *o;
gboolean free_l, free_r;
free_l = free_r = TRUE;
@ -288,58 +288,58 @@
/* value => value */
free_l = FALSE;
free_r = FALSE;
o = option_new_list();
g_array_append_val(o->value.opt_list, l);
g_array_append_val(o->value.opt_list, r);
o = value_new_list();
g_array_append_val(o->data.list, l);
g_array_append_val(o->data.list, r);
}
else if (l->type == OPTION_INT && r->type == OPTION_INT) {
else if (l->type == VALUE_NUMBER && r->type == VALUE_NUMBER) {
switch (ctx->value_op) {
case '+': o = option_new_int(l->value.opt_int + r->value.opt_int); break;
case '-': o = option_new_int(l->value.opt_int - r->value.opt_int); break;
case '*': o = option_new_int(l->value.opt_int * r->value.opt_int); break;
case '/': o = option_new_int(l->value.opt_int / r->value.opt_int); break;
case '+': o = value_new_number(l->data.number + r->data.number); break;
case '-': o = value_new_number(l->data.number - r->data.number); break;
case '*': o = value_new_number(l->data.number * r->data.number); break;
case '/': o = value_new_number(l->data.number / r->data.number); break;
}
}
else if (l->type == OPTION_STRING) {
else if (l->type == VALUE_STRING) {
o = l;
free_l = FALSE;
if (r->type == OPTION_STRING && ctx->value_op == '+') {
if (r->type == VALUE_STRING && ctx->value_op == '+') {
/* str + str */
o->value.opt_string = g_string_append_len(o->value.opt_string, r->value.opt_string->str, r->value.opt_string->len);
o->data.string = g_string_append_len(o->data.string, r->data.string->str, r->data.string->len);
}
else if (r->type == OPTION_INT && ctx->value_op == '+') {
else if (r->type == VALUE_NUMBER && ctx->value_op == '+') {
/* str + int */
g_string_append_printf(o->value.opt_string, "%d", r->value.opt_int);
g_string_append_printf(o->data.string, "%" G_GINT64_FORMAT, r->data.number);
}
else if (r->type == OPTION_INT && ctx->value_op == '*') {
else if (r->type == VALUE_NUMBER && ctx->value_op == '*') {
/* str * int */
if (r->value.opt_int < 0) {
log_error(srv, NULL, "string multiplication with negative number (%d)?", r->value.opt_int);
if (r->data.number < 0) {
log_error(srv, NULL, "string multiplication with negative number (%" G_GINT64_FORMAT ")?", r->data.number);
return FALSE;
}
else if (r->value.opt_int == 0) {
o->value.opt_string = g_string_truncate(o->value.opt_string, 0);
else if (r->data.number == 0) {
o->data.string = g_string_truncate(o->data.string, 0);
}
else {
GString *str;
str = g_string_new_len(l->value.opt_string->str, l->value.opt_string->len);
for (gint i = 1; i < r->value.opt_int; i++)
o->value.opt_string = g_string_append_len(o->value.opt_string, str->str, str->len);
str = g_string_new_len(l->data.string->str, l->data.string->len);
for (gint i = 1; i < r->data.number; i++)
o->data.string = g_string_append_len(o->data.string, str->str, str->len);
g_string_free(str, TRUE);
}
}
else
o = NULL;
}
else if (l->type == OPTION_LIST) {
else if (l->type == VALUE_LIST) {
if (ctx->value_op == '+') {
/* append r to the end of l */
free_l = FALSE; /* use l as the new o */
free_r = FALSE; /* r gets appended to o */
o = l;
g_array_append_val(l->value.opt_list, r);
g_array_append_val(l->data.list, r);
}
else if (ctx->value_op == '*') {
/* merge l and r */
@ -348,110 +348,110 @@
//o = l;
//a = g_array_sized_new(FALSE, FALSE, sizeof(option*), r->value.opt_list->len);
//a = g_array_append_vals(a, r->value.opt_list->data, r->value.opt_list->len); /* copy old list from r to a */
//o->value.opt_list = g_array_append_vals(o->value.opt_list, a->data, a->len); /* append data from a to o */
//a = g_array_sized_new(FALSE, FALSE, sizeof(value*), r->list->len);
//a = g_array_append_vals(a, r->list->data, r->list->len); /* copy old list from r to a */
//o->list = g_array_append_vals(o->list, a->data, a->len); /* append data from a to o */
//g_array_free(a, FALSE); /* free a but not the data because it is now in o */
if (r->type == OPTION_LIST) {
if (r->type == VALUE_LIST) {
/* merge lists */
free_l = FALSE;
g_array_append_vals(l->value.opt_list, r->value.opt_list->data, r->value.opt_list->len);
r->type = OPTION_NONE;
g_array_append_vals(l->data.list, r->data.list->data, r->data.list->len);
r->type = VALUE_NONE;
o = l;
}
}
}
else if (l->type == OPTION_HASH && r->type == OPTION_HASH && ctx->value_op == '+') {
else if (l->type == VALUE_HASH && r->type == VALUE_HASH && ctx->value_op == '+') {
/* merge hashtables */
GHashTableIter iter;
gpointer key, value;
gpointer key, val;
free_l = FALSE; /* keep l, it's the new o */
o = l;
g_hash_table_iter_init(&iter, r->value.opt_hash);
while (g_hash_table_iter_next(&iter, &key, &value)) {
g_hash_table_insert(o->value.opt_hash, key, value);
g_hash_table_iter_init(&iter, r->data.hash);
while (g_hash_table_iter_next(&iter, &key, &val)) {
g_hash_table_insert(o->data.hash, key, val);
g_hash_table_iter_steal(&iter); /* steal key->value so it doesn't get deleted when destroying r */
}
}
if (o == NULL) {
log_warning(srv, NULL, "erronous value statement: %s %c %s in line %zd\n",
option_type_string(l->type), ctx->value_op,
option_type_string(r->type), ctx->line);
value_type_string(l->type), ctx->value_op,
value_type_string(r->type), ctx->line);
return FALSE;
}
_printf("value statement: %s %c%s %s => %s in line %zd\n",
option_type_string(l->type),
value_type_string(l->type),
ctx->value_op,
ctx->value_op == '=' ? ">" : "",
option_type_string(r->type),
option_type_string(o->type),
value_type_string(r->type),
value_type_string(o->type),
ctx->line);
if (free_l)
option_free(l);
value_free(l);
if (free_r)
option_free(r);
value_free(r);
g_queue_push_head(ctx->option_stack, o);
}
action varname {
/* varname, push it as string option onto the stack */
option *o;
/* varname, push it as string value onto the stack */
value *o;
GString *str;
str = g_string_new_len(ctx->mark, fpc - ctx->mark);
o = option_new_string(str);
o = value_new_string(str);
g_queue_push_head(ctx->option_stack, o);
}
action actionref {
/* varname is on the stack */
option *o, *r, *t;
value *o, *r, *t;
o = g_queue_pop_head(ctx->option_stack);
/* action refs starting with "var." are user defined variables */
if (g_str_has_prefix(o->value.opt_string->str, "var.")) {
/* look up var in hashtable, copy and push option onto stack */
t = g_hash_table_lookup(ctx->uservars, o->value.opt_string);
if (g_str_has_prefix(o->data.string->str, "var.")) {
/* look up var in hashtable, copy and push value onto stack */
t = g_hash_table_lookup(ctx->uservars, o->data.string);
if (t == NULL) {
log_warning(srv, NULL, "unknown variable '%s'", o->value.opt_string->str);
log_warning(srv, NULL, "unknown variable '%s'", o->data.string->str);
return FALSE;
}
r = option_copy(t);
r = value_copy(t);
}
else if (g_str_has_prefix(o->value.opt_string->str, "env.")) {
/* look up string in environment, push option onto stack */
gchar *env = getenv(o->value.opt_string->str + 4);
else if (g_str_has_prefix(o->data.string->str, "env.")) {
/* look up string in environment, push value onto stack */
gchar *env = getenv(o->data.string->str + 4);
if (env == NULL) {
log_error(srv, NULL, "unknown environment variable: %s", o->value.opt_string->str + 4);
log_error(srv, NULL, "unknown environment variable: %s", o->data.string->str + 4);
return FALSE;
}
r = option_new_string(g_string_new(env));
r = value_new_string(g_string_new(env));
}
else {
/* real action, lookup hashtable and create new action option */
/* real action, lookup hashtable and create new action value */
action *a;
a = g_hash_table_lookup(ctx->action_blocks, o->value.opt_string);
a = g_hash_table_lookup(ctx->action_blocks, o->data.string);
if (a == NULL) {
log_warning(srv, NULL, "unknown action block referenced: %s", o->value.opt_string->str);
log_warning(srv, NULL, "unknown action block referenced: %s", o->data.string->str);
return FALSE;
}
r = option_new_action(srv, a);
r = value_new_action(srv, a);
}
g_queue_push_head(ctx->option_stack, r);
option_free(o);
value_free(o);
}
action operator {
@ -477,111 +477,111 @@
# statements
action assignment {
option *val, *name;
value *val, *name;
action *a, *al;
/* top of the stack is the value, then the varname as string option */
/* top of the stack is the value, then the varname as string value */
val = g_queue_pop_head(ctx->option_stack);
name = g_queue_pop_head(ctx->option_stack);
assert(name->type == OPTION_STRING);
assert(name->type == VALUE_STRING);
_printf("got assignment: %s = %s; in line %zd\n", name->value.opt_string->str, option_type_string(val->type), ctx->line);
_printf("got assignment: %s = %s; in line %zd\n", name->string->str, value_type_string(val->type), ctx->line);
if (ctx->in_setup_block) {
/* in setup { } block => set default values for options */
/* todo name */
}
else if (g_str_has_prefix(name->value.opt_string->str, "var.")) {
else if (g_str_has_prefix(name->data.string->str, "var.")) {
/* assignment vor user defined variable, insert into hashtable */
g_hash_table_insert(ctx->uservars, name->value.opt_string, val);
g_hash_table_insert(ctx->uservars, name->data.string, val);
}
else {
/* normal assignment */
a = option_action(srv, name->value.opt_string->str, val);
a = option_action(srv, name->data.string->str, val);
if (a == NULL)
return FALSE;
al = g_queue_peek_head(ctx->action_list_stack);
g_array_append_val(al->value.list, a);
option_free(name);
g_array_append_val(al->data.list, a);
value_free(name);
}
}
action function_noparam {
option *name;
value *name;
action *a, *al;
name = g_queue_pop_head(ctx->option_stack);
assert(name->type == OPTION_STRING);
assert(name->type == VALUE_STRING);
_printf("got function: %s; in line %zd\n", name->value.opt_string->str, ctx->line);
_printf("got function: %s; in line %zd\n", name->string->str, ctx->line);
if (g_str_equal(name->value.opt_string->str, "break")) {
if (g_str_equal(name->data.string->str, "break")) {
}
else if (g_str_equal(name->value.opt_string->str, "__halt")) {
else if (g_str_equal(name->data.string->str, "__halt")) {
}
else {
if (ctx->in_setup_block) {
/* we are in the setup { } block, call setups and don't append to action list */
if (!call_setup(srv, name->value.opt_string->str, NULL)) {
if (!call_setup(srv, name->data.string->str, NULL)) {
return FALSE;
}
}
else {
al = g_queue_peek_head(ctx->action_list_stack);
a = create_action(srv, name->value.opt_string->str, NULL);
a = create_action(srv, name->data.string->str, NULL);
if (a == NULL)
return FALSE;
g_array_append_val(al->value.list, a);
g_array_append_val(al->data.list, a);
}
}
}
action function_param {
/* similar to assignment */
option *val, *name;
value *val, *name;
action *a, *al;
/* top of the stack is the value, then the varname as string option */
/* top of the stack is the value, then the varname as string value */
val = g_queue_pop_head(ctx->option_stack);
name = g_queue_pop_head(ctx->option_stack);
assert(name->type == OPTION_STRING);
assert(name->type == VALUE_STRING);
_printf("got function: %s %s; in line %zd\n", name->value.opt_string->str, option_type_string(val->type), ctx->line);
_printf("got function: %s %s; in line %zd\n", name->string->str, value_type_string(val->type), ctx->line);
if (g_str_equal(name->value.opt_string->str, "include")) {
if (val->type != OPTION_STRING) {
log_warning(srv, NULL, "include directive takes a string as parameter, %s given", option_type_string(val->type));
if (g_str_equal(name->data.string->str, "include")) {
if (val->type != VALUE_STRING) {
log_warning(srv, NULL, "include directive takes a string as parameter, %s given", value_type_string(val->type));
return FALSE;
}
if (!config_parser_file(srv, ctx_stack, val->value.opt_string->str))
if (!config_parser_file(srv, ctx_stack, val->data.string->str))
return FALSE;
option_free(val);
value_free(val);
}
else if (g_str_equal(name->value.opt_string->str, "include_shell")) {
if (val->type != OPTION_STRING) {
log_warning(srv, NULL, "include_shell directive takes a string as parameter, %s given", option_type_string(val->type));
else if (g_str_equal(name->data.string->str, "include_shell")) {
if (val->type != VALUE_STRING) {
log_warning(srv, NULL, "include_shell directive takes a string as parameter, %s given", value_type_string(val->type));
return FALSE;
}
if (!config_parser_shell(srv, ctx_stack, val->value.opt_string->str))
if (!config_parser_shell(srv, ctx_stack, val->data.string->str))
return FALSE;
option_free(val);
value_free(val);
}
/* internal functions */
else if (g_str_has_prefix(name->value.opt_string->str, "__")) {
if (g_str_equal(name->value.opt_string->str + 2, "print")) {
GString *tmpstr = option_to_string(val);
g_printerr("%s:%zd type: %s, value: %s\n", ctx->filename, ctx->line, option_type_string(val->type), tmpstr->str);
else if (g_str_has_prefix(name->data.string->str, "__")) {
if (g_str_equal(name->data.string->str + 2, "print")) {
GString *tmpstr = value_to_string(val);
g_printerr("%s:%zd type: %s, value: %s\n", ctx->filename, ctx->line, value_type_string(val->type), tmpstr->str);
g_string_free(tmpstr, TRUE);
}
}
@ -590,27 +590,27 @@
/* TODO */
if (ctx->in_setup_block) {
/* we are in the setup { } block, call setups and don't append to action list */
if (!call_setup(srv, name->value.opt_string->str, val)) {
if (!call_setup(srv, name->data.string->str, val)) {
return FALSE;
}
}
else {
al = g_queue_peek_head(ctx->action_list_stack);
a = create_action(srv, name->value.opt_string->str, val);
a = create_action(srv, name->data.string->str, val);
if (a == NULL)
return FALSE;
g_array_append_val(al->value.list, a);
g_array_append_val(al->data.list, a);
}
}
option_free(name);
value_free(name);
}
action condition_start {
/* stack: value, varname OR value, key, varname */
option *v, *n, *k;
value *v, *n, *k;
gchar *str;
condition *cond;
condition_lvalue *lvalue;
@ -622,12 +622,12 @@
k = NULL;
n = g_queue_pop_head(ctx->option_stack);
assert(n->type == OPTION_STRING);
assert(n->type == VALUE_STRING);
_printf("got condition: %s:%s %s %s in line %zd\n", n->value.opt_string->str, ctx->condition_with_key ? k->value.opt_string->str : "", comp_op_to_string(ctx->op), option_type_string(v->type), ctx->line);
_printf("got condition: %s:%s %s %s in line %zd\n", n->string->str, ctx->condition_with_key ? k->string->str : "", comp_op_to_string(ctx->op), value_type_string(v->type), ctx->line);
/* create condition lvalue */
str = n->value.opt_string->str;
str = n->data.string->str;
if (g_str_has_prefix(str, "req")) {
str += 3;
@ -636,7 +636,7 @@
else if (g_str_has_prefix(str, "uest."))
str += 5;
else {
log_warning(srv, NULL, "unkown lvalue for condition: %s", n->value.opt_string->str);
log_warning(srv, NULL, "unkown lvalue for condition: %s", n->data.string->str);
return FALSE;
}
@ -655,10 +655,10 @@
log_warning(srv, NULL, "%s", "header conditional needs a key");
return FALSE;
}
lvalue = condition_lvalue_new(COMP_REQUEST_HEADER, k->value.opt_string);
lvalue = condition_lvalue_new(COMP_REQUEST_HEADER, k->data.string);
}
else {
log_warning(srv, NULL, "unkown lvalue for condition: %s", n->value.opt_string->str);
log_warning(srv, NULL, "unkown lvalue for condition: %s", n->data.string->str);
return FALSE;
}
}
@ -669,7 +669,7 @@
else if (g_str_has_prefix(str, "ical."))
str += 5;
else {
log_warning(srv, NULL, "unkown lvalue for condition: %s", n->value.opt_string->str);
log_warning(srv, NULL, "unkown lvalue for condition: %s", n->data.string->str);
return FALSE;
}
@ -680,20 +680,20 @@
else if (g_str_equal(str, "size"))
lvalue = condition_lvalue_new(COMP_PHYSICAL_SIZE, NULL);
else {
log_warning(srv, NULL, "unkown lvalue for condition: %s", n->value.opt_string->str);
log_warning(srv, NULL, "unkown lvalue for condition: %s", n->data.string->str);
return FALSE;
}
}
else {
log_warning(srv, NULL, "unkown lvalue for condition: %s", n->value.opt_string->str);
log_warning(srv, NULL, "unkown lvalue for condition: %s", n->data.string->str);
return FALSE;
}
if (v->type == OPTION_STRING) {
cond = condition_new_string(srv, ctx->op, lvalue, v->value.opt_string);
if (v->type == VALUE_STRING) {
cond = condition_new_string(srv, ctx->op, lvalue, v->data.string);
}
else if (v->type == OPTION_INT)
cond = condition_new_int(srv, ctx->op, lvalue, (gint64) v->value.opt_int);
else if (v->type == VALUE_NUMBER)
cond = condition_new_int(srv, ctx->op, lvalue, (gint64) v->data.number);
else {
cond = NULL;
}
@ -720,7 +720,7 @@
al = g_queue_pop_head(ctx->action_list_stack);
a = action_new_condition(cond, al, NULL);
al = g_queue_peek_head(ctx->action_list_stack);
g_array_append_val(al->value.list, a);
g_array_append_val(al->data.list, a);
}
action condition_key {
@ -746,14 +746,14 @@
target = g_queue_pop_head(ctx->action_list_stack);
al = g_queue_peek_head(ctx->action_list_stack);
cond = g_array_index(al->value.list, action*, al->value.list->len - 1); /* last action in the list is our condition */
cond = g_array_index(al->data.list, action*, al->data.list->len - 1); /* last action in the list is our condition */
while (cond->value.condition.target_else) {
while (cond->data.condition.target_else) {
/* condition has already an else statement, try the target */
cond = cond->value.condition.target_else;
cond = cond->data.condition.target_else;
}
cond->value.condition.target_else = target;
cond->data.condition.target_else = target;
_printf("got else_nocond_end in line %zd\n", ctx->line);
}
@ -770,53 +770,53 @@
action *prev, *cur, *al;
al = g_queue_peek_head(ctx->action_list_stack);
cur = g_array_index(al->value.list, action*, al->value.list->len - 1); /* last element of the action list */
prev = g_array_index(al->value.list, action*, al->value.list->len - 2);
cur = g_array_index(al->data.list, action*, al->data.list->len - 1); /* last element of the action list */
prev = g_array_index(al->data.list, action*, al->data.list->len - 2);
assert(cur->type == ACTION_TCONDITION);
assert(prev->type == ACTION_TCONDITION);
while (prev->value.condition.target_else) {
while (prev->data.condition.target_else) {
/* condition has already an else statement, try the target */
prev = prev->value.condition.target_else;
prev = prev->data.condition.target_else;
}
prev->value.condition.target_else = cur;
g_array_remove_index(al->value.list, al->value.list->len - 1);
prev->data.condition.target_else = cur;
g_array_remove_index(al->data.list, al->data.list->len - 1);
_printf("got else_cond_end in line %zd\n", ctx->line);
}
action action_block_start {
option *o;
value *o;
action *al;
o = g_queue_pop_head(ctx->option_stack);
assert(o->type == OPTION_STRING);
assert(o->type == VALUE_STRING);
if (ctx->in_setup_block) {
/* no block inside the setup block allowed */
assert(NULL); /* TODO */
}
if (g_str_equal(o->value.opt_string->str, "setup")) {
if (g_str_equal(o->data.string->str, "setup")) {
_printf("entered setup block in line %zd\n", ctx->line);
ctx->in_setup_block = TRUE;
}
else {
GString *str;
_printf("action block %s in line %zd\n", o->value.opt_string->str, ctx->line);
_printf("action block %s in line %zd\n", o->string->str, ctx->line);
/* create new action list and put it on the stack */
al = action_new_list();
g_queue_push_head(ctx->action_list_stack, al);
/* insert into hashtable for later lookups */
str = g_string_new_len(o->value.opt_string->str, o->value.opt_string->len);
str = g_string_new_len(o->data.string->str, o->data.string->len);
g_hash_table_insert(ctx->action_blocks, str, al);
}
option_free(o);
value_free(o);
}
action action_block_end {
@ -907,7 +907,7 @@ GList *config_parser_init(server* srv) {
void config_parser_finish(server *srv, GList *ctx_stack) {
config_parser_context_t *ctx;
GHashTableIter iter;
gpointer key, value;
gpointer key, val;
_printf("ctx_stack size: %u\n", g_list_length(ctx_stack));
@ -920,7 +920,7 @@ void config_parser_finish(server *srv, GList *ctx_stack) {
g_hash_table_iter_init(&iter, ctx->action_blocks);
while (g_hash_table_iter_next(&iter, &key, &value)) {
while (g_hash_table_iter_next(&iter, &key, &val)) {
g_hash_table_iter_steal(&iter);
g_string_free(key, TRUE);
}
@ -931,7 +931,7 @@ void config_parser_finish(server *srv, GList *ctx_stack) {
g_hash_table_iter_init(&iter, ctx->uservars);
while (g_hash_table_iter_next(&iter, &key, &value)) {
while (g_hash_table_iter_next(&iter, &key, &val)) {
g_hash_table_iter_steal(&iter);
g_string_free(key, TRUE);
}
@ -969,13 +969,13 @@ config_parser_context_t *config_parser_context_new(server *srv, GList *ctx_stack
}
else {
GString *str;
option *o;
value *o;
ctx->action_blocks = g_hash_table_new_full((GHashFunc) g_string_hash, (GEqualFunc) g_string_equal, NULL, NULL);
ctx->uservars = g_hash_table_new_full((GHashFunc) g_string_hash, (GEqualFunc) g_string_equal, NULL, NULL);
/* initialize var.PID */
/* TODO: what if pid_t is not a 32bit integer? */
o = option_new_int(getpid());
o = value_new_number(getpid());
str = g_string_new_len(CONST_STR_LEN("var.PID"));
g_hash_table_insert(ctx->uservars, str, o);
@ -983,7 +983,7 @@ config_parser_context_t *config_parser_context_new(server *srv, GList *ctx_stack
str = g_string_sized_new(1024);
if (NULL != getcwd(str->str, 1023)) {
g_string_set_size(str, strlen(str->str));
o = option_new_string(str);