merged from lp and enhanced config parser
This commit is contained in:
commit
c190daa908
137
src/actions.c
137
src/actions.c
|
@ -7,10 +7,43 @@ struct action_stack_element;
|
|||
typedef struct action_stack_element action_stack_element;
|
||||
|
||||
struct action_stack_element {
|
||||
action_list *list;
|
||||
action *act;
|
||||
guint pos;
|
||||
};
|
||||
|
||||
void action_release(server *srv, action *a) {
|
||||
guint i;
|
||||
assert(a->refcount > 0);
|
||||
if (!(--a->refcount)) {
|
||||
switch (a->type) {
|
||||
case ACTION_TSETTING:
|
||||
release_option(srv, &a->value.setting);
|
||||
break;
|
||||
case ACTION_TFUNCTION:
|
||||
if (a->value.function.free) {
|
||||
a->value.function.free(srv, a->value.function.param);
|
||||
}
|
||||
break;
|
||||
case ACTION_TCONDITION:
|
||||
condition_release(srv, a->value.condition.cond);
|
||||
action_release(srv, a->value.condition.target);
|
||||
break;
|
||||
case ACTION_TLIST:
|
||||
for (i = a->value.list->len; i-- > 0; ) {
|
||||
action_release(srv, g_array_index(a->value.list, action*, i));
|
||||
}
|
||||
g_array_free(a->value.list, TRUE);
|
||||
break;
|
||||
}
|
||||
g_slice_free(action, a);
|
||||
}
|
||||
}
|
||||
|
||||
void action_acquire(action *a) {
|
||||
assert(a->refcount > 0);
|
||||
a->refcount++;
|
||||
}
|
||||
|
||||
action *action_new_setting(server *srv, const gchar *name, option *value) {
|
||||
option_set setting;
|
||||
if (!parse_option(srv, name, value, &setting)) {
|
||||
|
@ -45,95 +78,27 @@ action *action_new_list() {
|
|||
a = g_slice_new(action);
|
||||
a->refcount = 1;
|
||||
a->type = ACTION_TLIST;
|
||||
a->value.list = action_list_new();
|
||||
a->value.list = g_array_new(FALSE, TRUE, sizeof(action *));
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
action *action_new_condition(condition *cond, action_list *al) {
|
||||
action *action_new_condition(condition *cond, action *target) {
|
||||
action *a;
|
||||
|
||||
a = g_slice_new(action);
|
||||
a->refcount = 1;
|
||||
a->type = ACTION_TCONDITION;
|
||||
a->value.condition.cond = cond;
|
||||
a->value.condition.target = al;
|
||||
a->value.condition.target = target;
|
||||
|
||||
return a;
|
||||
}
|
||||
void action_release(server *srv, action *a) {
|
||||
assert(a->refcount > 0);
|
||||
if (!(--a->refcount)) {
|
||||
switch (a->type) {
|
||||
case ACTION_TSETTING:
|
||||
release_option(srv, &a->value.setting);
|
||||
break;
|
||||
case ACTION_TFUNCTION:
|
||||
if (a->value.function.free) {
|
||||
a->value.function.free(srv, a->value.function.param);
|
||||
}
|
||||
break;
|
||||
case ACTION_TCONDITION:
|
||||
condition_release(srv, a->value.condition.cond);
|
||||
action_list_release(srv, a->value.condition.target);
|
||||
break;
|
||||
case ACTION_TLIST:
|
||||
action_list_release(srv, a->value.list);
|
||||
break;
|
||||
}
|
||||
g_slice_free(action, a);
|
||||
}
|
||||
}
|
||||
|
||||
void action_acquire(action *a) {
|
||||
assert(a->refcount > 0);
|
||||
a->refcount++;
|
||||
}
|
||||
|
||||
action_list *action_list_new() {
|
||||
action_list *al;
|
||||
|
||||
al = g_slice_new(action_list);
|
||||
al->refcount = 1;
|
||||
|
||||
al->actions = g_array_new(FALSE, TRUE, sizeof(action *));
|
||||
|
||||
return al;
|
||||
}
|
||||
|
||||
action_list *action_list_from_action(action *a) {
|
||||
action_list *al;
|
||||
if (a->type == ACTION_TLIST) {
|
||||
action_list_acquire(a->value.list);
|
||||
return a->value.list; /* action gets released from lua */
|
||||
}
|
||||
action_acquire(a);
|
||||
al = action_list_new();
|
||||
g_array_append_val(al->actions, a);
|
||||
return al;
|
||||
}
|
||||
|
||||
void action_list_release(server *srv, action_list *al) {
|
||||
assert(al->refcount > 0);
|
||||
if (!(--al->refcount)) {
|
||||
guint i;
|
||||
for (i = al->actions->len; i-- > 0; ) {
|
||||
action_release(srv, g_array_index(al->actions, action*, i));
|
||||
}
|
||||
g_array_free(al->actions, TRUE);
|
||||
g_slice_free(action_list, al);
|
||||
}
|
||||
}
|
||||
|
||||
void action_list_acquire(action_list *al) {
|
||||
assert(al->refcount > 0);
|
||||
al->refcount++;
|
||||
}
|
||||
|
||||
void action_stack_element_release(server *srv, action_stack_element *ase) {
|
||||
if (!ase || !ase->list) return;
|
||||
action_list_release(srv, ase->list);
|
||||
ase->list = NULL;
|
||||
if (!ase || !ase->act) return;
|
||||
action_release(srv, ase->act);
|
||||
ase->act = NULL;
|
||||
}
|
||||
|
||||
void action_stack_init(action_stack *as) {
|
||||
|
@ -154,12 +119,13 @@ void action_stack_clear(server *srv, action_stack *as) {
|
|||
action_stack_element_release(srv, &g_array_index(as->stack, action_stack_element, i));
|
||||
}
|
||||
g_array_free(as->stack, TRUE);
|
||||
as->stack = NULL;
|
||||
}
|
||||
|
||||
/** handle sublist now, remember current position (stack) */
|
||||
void action_enter(connection *con, action_list *al) {
|
||||
action_list_acquire(al);
|
||||
action_stack_element ase = { al, 0 };
|
||||
void action_enter(connection *con, action *a) {
|
||||
action_acquire(a);
|
||||
action_stack_element ase = { a, 0 };
|
||||
g_array_append_val(con->action_stack.stack, ase);
|
||||
}
|
||||
|
||||
|
@ -172,9 +138,13 @@ static void action_stack_pop(server *srv, action_stack *as) {
|
|||
g_array_set_size(as->stack, as->stack->len - 1);
|
||||
}
|
||||
|
||||
static action* action_stack_element_next(action_stack_element *ase) {
|
||||
action_list *al = ase->list;
|
||||
return ase->pos < al->actions->len ? g_array_index(al->actions, action*, ase->pos++) : NULL;
|
||||
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;
|
||||
} else {
|
||||
return ase->pos == 0 ? a : NULL;
|
||||
}
|
||||
}
|
||||
|
||||
action_result action_execute(server *srv, connection *con) {
|
||||
|
@ -184,7 +154,7 @@ action_result action_execute(server *srv, connection *con) {
|
|||
action_result res;
|
||||
|
||||
while (NULL != (ase = action_stack_top(as))) {
|
||||
a = action_stack_element_next(ase);
|
||||
a = action_stack_element_action(ase);
|
||||
if (!a) {
|
||||
action_stack_pop(srv, as);
|
||||
continue;
|
||||
|
@ -212,9 +182,10 @@ action_result action_execute(server *srv, connection *con) {
|
|||
}
|
||||
break;
|
||||
case ACTION_TLIST:
|
||||
action_enter(con, a->value.list);
|
||||
action_enter(con, a);
|
||||
break;
|
||||
}
|
||||
ase->pos++;
|
||||
}
|
||||
return ACTION_GO_ON;
|
||||
}
|
||||
|
|
|
@ -21,9 +21,6 @@ typedef enum {
|
|||
struct action;
|
||||
typedef struct action action;
|
||||
|
||||
struct action_list;
|
||||
typedef struct action_list action_list;
|
||||
|
||||
struct action_stack;
|
||||
typedef struct action_stack action_stack;
|
||||
|
||||
|
@ -46,12 +43,6 @@ typedef struct action_func action_func;
|
|||
#include "plugin.h"
|
||||
#include "options.h"
|
||||
|
||||
struct action_list {
|
||||
gint refcount;
|
||||
|
||||
GArray* actions; /** array of (action*) */
|
||||
};
|
||||
|
||||
struct action {
|
||||
gint refcount;
|
||||
action_type type;
|
||||
|
@ -61,27 +52,22 @@ struct action {
|
|||
|
||||
struct {
|
||||
condition *cond;
|
||||
action_list* target; /** action target to jump to if condition is fulfilled */
|
||||
action* target; /** action target to jump to if condition is fulfilled */
|
||||
} condition;
|
||||
|
||||
action_func function;
|
||||
|
||||
action_list *list;
|
||||
GArray* list; /** array of (action*) */
|
||||
} value;
|
||||
};
|
||||
|
||||
LI_API void action_list_release(server *srv, action_list *al);
|
||||
LI_API void action_list_acquire(action_list *al);
|
||||
LI_API action_list *action_list_new();
|
||||
LI_API action_list *action_list_from_action(action *a);
|
||||
|
||||
/* no new/free function, so just use the struct direct (i.e. not a pointer) */
|
||||
LI_API void action_stack_init(action_stack *as);
|
||||
LI_API void action_stack_reset(server *srv, action_stack *as);
|
||||
LI_API void action_stack_clear(server *srv, action_stack *as);
|
||||
|
||||
/** handle sublist now, remember current position (stack) */
|
||||
LI_API void action_enter(connection *con, action_list *al);
|
||||
LI_API void action_enter(connection *con, action *a);
|
||||
LI_API action_result action_execute(server *srv, connection *con);
|
||||
|
||||
|
||||
|
@ -91,7 +77,6 @@ LI_API void action_acquire(action *a);
|
|||
LI_API action *action_new_setting(server *srv, const gchar *name, option *value);
|
||||
LI_API action *action_new_function(ActionFunc func, ActionFree free, gpointer param);
|
||||
LI_API action *action_new_list();
|
||||
LI_API action *action_new_condition(condition *cond, action_list *al);
|
||||
/*LI_API action *action_new_condition_string(comp_key_t comp, comp_operator_t op, GString *str);
|
||||
LI_API action *action_new_condition_int(comp_key_t comp, comp_operator_t op, guint64 i);*/
|
||||
LI_API action *action_new_condition(condition *cond, action *target);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -44,11 +44,3 @@ int lua_push_action(server *srv, lua_State *L, action *a) {
|
|||
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);
|
||||
}
|
||||
|
|
|
@ -6,6 +6,5 @@
|
|||
|
||||
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
|
||||
|
|
|
@ -164,7 +164,7 @@ static int handle_option(lua_State *L) {
|
|||
lua_pushnil(L);
|
||||
while (lua_next(L, 2) != 0) {
|
||||
suba = action_from_lua(srv, L);
|
||||
g_array_append_val(a->value.list->actions, suba);
|
||||
g_array_append_val(a->value.list, suba);
|
||||
lua_pop(L, 1);
|
||||
}
|
||||
lua_pop(L, 1);
|
||||
|
@ -212,7 +212,7 @@ gboolean config_lua_load(server *srv, const gchar *filename) {
|
|||
lua_pop(L, 1); /* pop the ret-value */
|
||||
|
||||
lua_getfield(L, LUA_GLOBALSINDEX, "action");
|
||||
srv->mainactionlist = lua_get_actionlist(L);
|
||||
srv->mainaction = lua_get_action(L, -1);
|
||||
lua_pop(L, 1);
|
||||
|
||||
assert(lua_gettop(L) == 0);
|
||||
|
|
|
@ -33,6 +33,7 @@ struct config_parser_context_t {
|
|||
gboolean in_setup_block;
|
||||
|
||||
comp_operator_t op;
|
||||
gchar value_op;
|
||||
|
||||
GQueue *action_list_stack; /* first entry is current action list */
|
||||
GQueue *option_stack; /* stack of option* */
|
||||
|
|
|
@ -59,6 +59,34 @@
|
|||
}
|
||||
|
||||
action integer_suffix {
|
||||
option *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;
|
||||
|
||||
else if (g_str_equal(str->str, "kbit")) o->value.opt_int *= 1024;
|
||||
else if (g_str_equal(str->str, "mbit")) o->value.opt_int *= 1024 * 1024;
|
||||
else if (g_str_equal(str->str, "gbit")) o->value.opt_int *= 1024 * 1024 * 1024;
|
||||
|
||||
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;
|
||||
|
||||
g_string_free(str, TRUE);
|
||||
|
||||
_printf("got int with suffix: %d\n", o->value.opt_int);
|
||||
|
||||
/* make sure there was no overflow that led to negative numbers */
|
||||
if (o->value.opt_int < 0) {
|
||||
log_warning(srv, NULL, "integer value overflowed in line %zd of %s\n", ctx->line, ctx->filename);
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
action string {
|
||||
|
@ -96,7 +124,7 @@
|
|||
|
||||
g_array_append_val(l->value.opt_list, o);
|
||||
|
||||
_printf("list_push%s\n", "");
|
||||
_printf("list_push %s\n", option_type_string(o->type));
|
||||
}
|
||||
|
||||
action list_end {
|
||||
|
@ -143,7 +171,9 @@
|
|||
}
|
||||
|
||||
action keyvalue_start {
|
||||
fcall keyvalue_scanner;
|
||||
fpc--;
|
||||
|
||||
fcall value_scanner;
|
||||
}
|
||||
|
||||
action keyvalue_end {
|
||||
|
@ -153,8 +183,6 @@
|
|||
v = g_queue_pop_head(ctx->option_stack);
|
||||
k = g_queue_pop_head(ctx->option_stack);
|
||||
|
||||
assert(k->type == OPTION_STRING);
|
||||
|
||||
l = option_new_list();
|
||||
|
||||
g_array_append_val(l->value.opt_list, k);
|
||||
|
@ -163,6 +191,8 @@
|
|||
/* push list on the stack */
|
||||
g_queue_push_head(ctx->option_stack, l);
|
||||
|
||||
fpc--;
|
||||
|
||||
fret;
|
||||
}
|
||||
|
||||
|
@ -174,6 +204,99 @@
|
|||
*/
|
||||
}
|
||||
|
||||
action value_statement_op {
|
||||
ctx->value_op = *fpc;
|
||||
}
|
||||
|
||||
action value_statement {
|
||||
/* value (+|-|*|/) value */
|
||||
/* compute new value out of the two */
|
||||
option *l, *r, *o;
|
||||
gboolean free_l, free_r;
|
||||
|
||||
free_l = free_r = TRUE;
|
||||
|
||||
r = g_queue_pop_head(ctx->option_stack);
|
||||
l = g_queue_pop_head(ctx->option_stack);
|
||||
o = NULL;
|
||||
|
||||
|
||||
if (l->type == OPTION_INT && r->type == OPTION_INT) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
else if (l->type == OPTION_STRING) {
|
||||
GString *str;
|
||||
|
||||
if (r->type == OPTION_STRING && ctx->value_op == '+') {
|
||||
/* str + str */
|
||||
str = g_string_sized_new(l->value.opt_string->len + r->value.opt_string->len);
|
||||
str = g_string_append_len(str, l->value.opt_string->str, l->value.opt_string->len);
|
||||
str = g_string_append_len(str, r->value.opt_string->str, r->value.opt_string->len);
|
||||
o = option_new_string(str);
|
||||
}
|
||||
else if (r->type == OPTION_INT && ctx->value_op == '*') {
|
||||
/* str * int */
|
||||
str = g_string_sized_new(l->value.opt_string->len * r->value.opt_int);
|
||||
for (gint i = 0; i < r->value.opt_int; i++)
|
||||
str = g_string_append_len(str, l->value.opt_string->str, l->value.opt_string->len);
|
||||
o = option_new_string(str);
|
||||
}
|
||||
}
|
||||
else if (l->type == OPTION_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(o->value.opt_list, r);
|
||||
}
|
||||
else if (ctx->value_op == '*') {
|
||||
/* merge l and r */
|
||||
GArray *a;
|
||||
free_l = FALSE;
|
||||
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 */
|
||||
g_array_free(a, FALSE); /* free a but not the data because it is now in o */
|
||||
}
|
||||
}
|
||||
else if (l->type == OPTION_HASH && r->type == OPTION_HASH && ctx->value_op == '+') {
|
||||
/* merge hashtables */
|
||||
GHashTableIter iter;
|
||||
gpointer key, value;
|
||||
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_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);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
_printf("value statement: %s %c %s => %s in line %zd\n", option_type_string(l->type), ctx->value_op, option_type_string(r->type), option_type_string(o->type), ctx->line);
|
||||
|
||||
if (free_l)
|
||||
option_free(l);
|
||||
if (free_r)
|
||||
option_free(r);
|
||||
|
||||
g_queue_push_head(ctx->option_stack, o);
|
||||
}
|
||||
|
||||
action varname {
|
||||
/* varname, push it as string option onto the stack */
|
||||
option *o;
|
||||
|
@ -188,17 +311,36 @@
|
|||
/* varname is on the stack */
|
||||
}
|
||||
|
||||
action operator {
|
||||
if ((fpc - ctx->mark) == 1) {
|
||||
switch (*ctx->mark) {
|
||||
case '<': ctx->op = CONFIG_COND_LT; break;
|
||||
case '>': ctx->op = CONFIG_COND_GT; break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (*ctx->mark == '>' && *(ctx->mark+1) == '=') ctx->op = CONFIG_COND_GE;
|
||||
else if (*ctx->mark == '<' && *(ctx->mark+1) == '=') ctx->op = CONFIG_COND_LE;
|
||||
else if (*ctx->mark == '=' && *(ctx->mark+1) == '=') ctx->op = CONFIG_COND_EQ;
|
||||
else if (*ctx->mark == '!' && *(ctx->mark+1) == '=') ctx->op = CONFIG_COND_NE;
|
||||
else if (*ctx->mark == '=' && *(ctx->mark+1) == '~') ctx->op = CONFIG_COND_MATCH;
|
||||
else if (*ctx->mark == '!' && *(ctx->mark+1) == '~') ctx->op = CONFIG_COND_NOMATCH;
|
||||
}
|
||||
}
|
||||
|
||||
# statements
|
||||
action assignment {
|
||||
option *val, *name;
|
||||
action *a;
|
||||
action_list *al;
|
||||
action *a, *al;
|
||||
|
||||
/* top of the stack is the value, then the varname as string option */
|
||||
val = g_queue_pop_head(ctx->option_stack);
|
||||
name = g_queue_pop_head(ctx->option_stack);
|
||||
|
||||
assert(name->type == OPTION_STRING);
|
||||
|
||||
if (g_str_has_prefix(name->value.opt_string->str, "var.")) {
|
||||
}
|
||||
/*
|
||||
al = g_queue_peek_head(ctx->action_list_stack);
|
||||
|
||||
|
@ -210,7 +352,7 @@
|
|||
g_array_append_val(al->actions, a);
|
||||
*/
|
||||
UNUSED(a); UNUSED(al);
|
||||
g_print("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->value.opt_string->str, option_type_string(val->type), ctx->line);
|
||||
|
||||
option_free(name);
|
||||
}
|
||||
|
@ -218,8 +360,7 @@ UNUSED(a); UNUSED(al);
|
|||
action function {
|
||||
/* similar to assignment */
|
||||
option *val, *name;
|
||||
action *a;
|
||||
action_list *al;
|
||||
action *a, *al;
|
||||
|
||||
/* top of the stack is the value, then the varname as string option */
|
||||
val = g_queue_pop_head(ctx->option_stack);
|
||||
|
@ -243,10 +384,10 @@ UNUSED(a); UNUSED(al);
|
|||
UNUSED(a);
|
||||
}
|
||||
|
||||
g_print("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->value.opt_string->str, option_type_string(val->type), ctx->line);
|
||||
}
|
||||
|
||||
action condition {
|
||||
action condition_start {
|
||||
/* stack: value, varname */
|
||||
option *v, *n;
|
||||
|
||||
|
@ -254,12 +395,15 @@ UNUSED(a); UNUSED(al);
|
|||
n = g_queue_pop_head(ctx->option_stack);
|
||||
assert(n->type == OPTION_STRING);
|
||||
|
||||
g_print("got condition: %s %s %s in line %zd\n", n->value.opt_string->str, option_type_string(v->type), comp_op_to_string(ctx->op), ctx->line);
|
||||
_printf("got condition: %s %s %s in line %zd\n", n->value.opt_string->str, comp_op_to_string(ctx->op), option_type_string(v->type), ctx->line);
|
||||
}
|
||||
|
||||
action condition_end {
|
||||
}
|
||||
|
||||
action action_block_start {
|
||||
option *o;
|
||||
action_list *al;
|
||||
action *al;
|
||||
|
||||
o = g_queue_pop_head(ctx->option_stack);
|
||||
assert(o->type == OPTION_STRING);
|
||||
|
@ -276,7 +420,7 @@ UNUSED(a); UNUSED(al);
|
|||
else {
|
||||
_printf("action block %s in line %zd\n", o->value.opt_string->str, ctx->line);
|
||||
/* create new action list and put it on the stack */
|
||||
al = action_list_new();
|
||||
al = action_new_list();
|
||||
g_queue_push_head(ctx->action_list_stack, al);
|
||||
}
|
||||
}
|
||||
|
@ -294,13 +438,6 @@ UNUSED(a); UNUSED(al);
|
|||
|
||||
## definitions
|
||||
|
||||
# basic types
|
||||
boolean = ( 'true' | 'false' ) %boolean;
|
||||
integer = ( 0 | ( [1-9] [0-9]* ) ) %integer;
|
||||
integer_suffix_bytes = ( 'b' | 'kb' | 'mb' | 'gb' | 'tb' | 'pb' );
|
||||
integer_suffix_seconds = ( 's' | 'm' | 'h' | 'd' );
|
||||
string = ( '"' (any-'"')* '"' ) %string;
|
||||
|
||||
# misc stuff
|
||||
line_sane = ( '\n' ) >{ ctx->line++; };
|
||||
line_weird = ( '\r' ) >{ ctx->line++; };
|
||||
|
@ -313,27 +450,37 @@ UNUSED(a); UNUSED(al);
|
|||
comment = ( '#' (any - line)* line );
|
||||
block = ( '{' >block_start );
|
||||
|
||||
# basic types
|
||||
boolean = ( 'true' | 'false' ) %boolean;
|
||||
integer_suffix_bytes = ( 'byte' | 'kbyte' | 'mbyte' | 'gbyte' | 'tbyte' | 'pbyte' );
|
||||
integer_suffix_bits = ( 'bit' | 'kbit' | 'mbit' | 'gbit' );
|
||||
integer_suffix_seconds = ( 'sec' | 'min' | 'hours' | 'days' );
|
||||
integer_suffix = ( integer_suffix_bytes | integer_suffix_bits | integer_suffix_seconds ) >mark %integer_suffix;
|
||||
integer = ( 0 | ( [1-9] [0-9]* ) %integer (ws? integer_suffix)? );
|
||||
string = ( '"' (any-'"')* '"' ) %string;
|
||||
|
||||
# advanced types
|
||||
varname = ( alpha ( alnum | [._\-] )* ) >mark %varname;
|
||||
varname = ( (alpha ( alnum | [._] )*) - boolean ) >mark %varname;
|
||||
actionref = ( varname ) %actionref;
|
||||
list = ( '(' >list_start );
|
||||
hash = ( '[' >hash_start );
|
||||
keyvalue = ( string ws* '=>' ws* >keyvalue_start );
|
||||
keyvalue = ( (string | integer) ws* '=>' ws* (any - ws) >keyvalue_start );
|
||||
value = ( boolean | integer | string | list | hash | keyvalue | actionref ) >mark %value;
|
||||
value_statement = ( value (ws* ('+'|'-'|'*'|'/') >value_statement_op ws* value %value_statement)? );
|
||||
hash_elem = ( string >mark noise* ':' noise* value );
|
||||
|
||||
operator = ( '==' | '!=' | '<' | '<=' | '>' | '>=' | '=~' | '!~' );
|
||||
operator = ( '==' | '!=' | '<' | '<=' | '>' | '>=' | '=~' | '!~' ) >mark %operator;
|
||||
|
||||
# statements
|
||||
assignment = ( varname ws* '=' ws* value ';' ) %assignment;
|
||||
assignment = ( varname ws* '=' ws* value_statement ';' ) %assignment;
|
||||
function = ( varname ws+ value ';' ) %function;
|
||||
condition = ( varname ws* operator ws* value noise* block ) %condition;
|
||||
condition = ( varname ws* operator ws* value noise* block >condition_start ) %condition_end;
|
||||
action_block = ( varname ws* block >action_block_start ) %action_block_end;
|
||||
|
||||
statement = ( assignment | function | condition | action_block );
|
||||
|
||||
# scanner
|
||||
keyvalue_scanner := ( value any >{fpc--;} >keyvalue_end );
|
||||
value_scanner := ( value (any - value - ws) >keyvalue_end );
|
||||
block_scanner := ( (noise | comment | statement)* '}' >block_end );
|
||||
list_scanner := ( noise* (value %list_push (noise* ',' noise* value %list_push)*)? noise* ')' >list_end );
|
||||
hash_scanner := ( noise* (hash_elem %hash_push (noise* ',' noise* hash_elem %hash_push)*)? noise* ']' >hash_end );
|
||||
|
@ -346,7 +493,7 @@ UNUSED(a); UNUSED(al);
|
|||
|
||||
GList *config_parser_init(server* srv) {
|
||||
config_parser_context_t *ctx = config_parser_context_new(srv, NULL);
|
||||
g_queue_push_head(ctx->action_list_stack, srv->mainactionlist);
|
||||
g_queue_push_head(ctx->action_list_stack, srv->mainaction);
|
||||
return g_list_append(NULL, ctx);
|
||||
}
|
||||
|
||||
|
@ -382,9 +529,9 @@ void config_parser_context_free(server *srv, config_parser_context_t *ctx, gbool
|
|||
|
||||
if (free_queues) {
|
||||
if (g_queue_get_length(ctx->action_list_stack) > 0) {
|
||||
action_list *al;
|
||||
while ((al = g_queue_pop_head(ctx->action_list_stack)))
|
||||
action_list_release(srv, al);
|
||||
action *a;
|
||||
while ((a = g_queue_pop_head(ctx->action_list_stack)))
|
||||
action_release(srv, a);
|
||||
}
|
||||
|
||||
if (g_queue_get_length(ctx->option_stack) > 0) {
|
||||
|
|
|
@ -67,6 +67,7 @@ int main(int argc, char *argv[]) {
|
|||
GTimeVal start, end;
|
||||
gulong s, millis, micros;
|
||||
g_get_current_time(&start);
|
||||
guint64 d;
|
||||
|
||||
/* standard config frontend */
|
||||
GList *ctx_stack = config_parser_init(srv);
|
||||
|
@ -84,11 +85,13 @@ int main(int argc, char *argv[]) {
|
|||
}
|
||||
|
||||
g_get_current_time(&end);
|
||||
start.tv_usec = end.tv_usec - start.tv_usec;
|
||||
s = start.tv_sec = end.tv_sec - start.tv_sec;
|
||||
millis = start.tv_usec / 1000;
|
||||
micros = start.tv_usec % 1000;
|
||||
g_print("parsed config file in %zd seconds, %zd milliseconds, %zd microseconds\n", start.tv_sec, millis, micros);
|
||||
d = end.tv_sec - start.tv_sec;
|
||||
d *= 1000000;
|
||||
d += end.tv_usec - start.tv_usec;
|
||||
s = d / 1000000;
|
||||
millis = (d - s) / 1000;
|
||||
micros = (d - s - millis) %1000;
|
||||
g_print("parsed config file in %zd seconds, %zd milliseconds, %zd microseconds\n", s, millis, micros);
|
||||
g_print("option_stack: %u action_list_stack: %u (should be 0:1)\n", g_queue_get_length(ctx->option_stack), g_queue_get_length(ctx->action_list_stack));
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -21,7 +21,7 @@ static action* core_list(server *srv, plugin* p, option *opt) {
|
|||
}
|
||||
assert(srv == oa->value.opt_action.srv);
|
||||
action_acquire(oa->value.opt_action.action);
|
||||
g_array_append_val(a->value.list->actions, oa->value.opt_action.action);
|
||||
g_array_append_val(a->value.list, oa->value.opt_action.action);
|
||||
}
|
||||
option_free(opt);
|
||||
return a;
|
||||
|
@ -50,7 +50,7 @@ static action* core_when(server *srv, plugin* p, option *opt) {
|
|||
ERROR(srv, "expected condition as first parameter, got %s", option_type_string(opt->type));
|
||||
return NULL;
|
||||
}
|
||||
a = action_new_condition(opt_cond->value.opt_cond.cond, action_list_from_action(opt_act->value.opt_action.action));
|
||||
a = action_new_condition(opt_cond->value.opt_cond.cond, opt_act->value.opt_action.action);
|
||||
option_free(opt);
|
||||
return a;
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ server* server_new() {
|
|||
srv->actions = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, server_action_free);
|
||||
srv->setups = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, server_setup_free);
|
||||
srv->mutex = g_mutex_new();
|
||||
srv->mainactionlist = action_list_new();
|
||||
srv->mainaction = action_new_list();
|
||||
|
||||
return srv;
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ void server_free(server* srv) {
|
|||
g_hash_table_destroy(srv->plugins);
|
||||
g_mutex_free(srv->mutex);
|
||||
|
||||
action_list_release(srv, srv->mainactionlist);
|
||||
action_release(srv, srv->mainaction);
|
||||
|
||||
/* free logs */
|
||||
GHashTableIter iter;
|
||||
|
|
|
@ -14,7 +14,7 @@ struct server {
|
|||
GHashTable *setups; /**< const gchar* => server_setup* */
|
||||
|
||||
gpointer *option_def_values;
|
||||
struct action_list *mainactionlist;
|
||||
struct action *mainaction;
|
||||
|
||||
gboolean exiting;
|
||||
GMutex *mutex; /* general mutex for accessing the various members */
|
||||
|
|
Loading…
Reference in New Issue