small config parser and log changes
parent
a9cbec1046
commit
5e700e79e1
|
@ -8,6 +8,9 @@ struct config_parser_context_t;
|
|||
typedef struct config_parser_context_t config_parser_context_t;
|
||||
|
||||
|
||||
/* returns a new config parser stack with the first context in it */
|
||||
GList *config_parser_init(server *srv);
|
||||
|
||||
/* loads a file into memory and parses it */
|
||||
gboolean config_parser_file(server *srv, GList *ctx_stack, const gchar *path);
|
||||
/* launched a command through the shell and parses the stdout it returns */
|
||||
|
@ -15,8 +18,8 @@ gboolean config_parser_shell(server *srv,GList *ctx_stack, const gchar *command)
|
|||
/* parses a buffer pointed to by the previously allocated config_parser_data struct */
|
||||
gboolean config_parser_buffer(server *srv, GList *ctx_stack);
|
||||
|
||||
config_parser_context_t *config_parser_context_new();
|
||||
void config_parser_context_free(config_parser_context_t *ctx, gboolean free_queues);
|
||||
config_parser_context_t *config_parser_context_new(server *srv, GList *ctx_stack);
|
||||
void config_parser_context_free(server *srv, config_parser_context_t *ctx, gboolean free_queues);
|
||||
|
||||
struct config_parser_context_t {
|
||||
/* ragel vars */
|
||||
|
@ -32,7 +35,7 @@ struct config_parser_context_t {
|
|||
comp_operator_t op;
|
||||
|
||||
GQueue *action_list_stack; /* first entry is current action list */
|
||||
GQueue *option_stack; /* stack for options */
|
||||
GQueue *option_stack; /* stack of option* */
|
||||
|
||||
/* information about currenty parsed file */
|
||||
gchar *filename;
|
||||
|
|
|
@ -184,22 +184,42 @@
|
|||
g_queue_push_head(ctx->option_stack, o);
|
||||
}
|
||||
|
||||
action actionref {
|
||||
/* varname is on the stack */
|
||||
}
|
||||
|
||||
# statements
|
||||
action assignment {
|
||||
option *val, *name;
|
||||
action *a;
|
||||
action_list *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);
|
||||
/*
|
||||
al = g_queue_peek_head(ctx->action_list_stack);
|
||||
|
||||
a = action_new_setting(srv, name->value.opt_string->str, val);
|
||||
|
||||
if (a == NULL)
|
||||
return FALSE;
|
||||
|
||||
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);
|
||||
|
||||
option_free(name);
|
||||
}
|
||||
|
||||
action function {
|
||||
/* similar to assignment */
|
||||
option *val, *name;
|
||||
action *a;
|
||||
action_list *al;
|
||||
|
||||
/* top of the stack is the value, then the varname as string option */
|
||||
val = g_queue_pop_head(ctx->option_stack);
|
||||
|
@ -219,6 +239,8 @@
|
|||
}
|
||||
else {
|
||||
/* TODO */
|
||||
al = g_queue_peek_head(ctx->action_list_stack);
|
||||
UNUSED(a);
|
||||
}
|
||||
|
||||
g_print("got function: %s %s; in line %zd\n", name->value.opt_string->str, option_type_string(val->type), ctx->line);
|
||||
|
@ -235,13 +257,38 @@
|
|||
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);
|
||||
}
|
||||
|
||||
action action_block {
|
||||
action action_block_start {
|
||||
option *o;
|
||||
action_list *al;
|
||||
|
||||
o = g_queue_pop_head(ctx->option_stack);
|
||||
assert(o->type == OPTION_STRING);
|
||||
|
||||
g_print("action block %s in line %zd\n", o->value.opt_string->str, ctx->line);
|
||||
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")) {
|
||||
_printf("entered setup block in line %zd\n", ctx->line);
|
||||
ctx->in_setup_block = TRUE;
|
||||
}
|
||||
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();
|
||||
g_queue_push_head(ctx->action_list_stack, al);
|
||||
}
|
||||
}
|
||||
|
||||
action action_block_end {
|
||||
if (ctx->in_setup_block) {
|
||||
ctx->in_setup_block = FALSE;
|
||||
}
|
||||
else {
|
||||
/* pop action list stack */
|
||||
g_queue_pop_head(ctx->action_list_stack);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -268,7 +315,7 @@
|
|||
|
||||
# advanced types
|
||||
varname = ( alpha ( alnum | [._\-] )* ) >mark %varname;
|
||||
actionref = ( varname );
|
||||
actionref = ( varname ) %actionref;
|
||||
list = ( '(' >list_start );
|
||||
hash = ( '[' >hash_start );
|
||||
keyvalue = ( string ws* '=>' ws* >keyvalue_start );
|
||||
|
@ -281,7 +328,7 @@
|
|||
assignment = ( varname ws* '=' ws* value ';' ) %assignment;
|
||||
function = ( varname ws+ value ';' ) %function;
|
||||
condition = ( varname ws* operator ws* value noise* block ) %condition;
|
||||
action_block = ( varname ws* block ) %action_block;
|
||||
action_block = ( varname ws* block >action_block_start ) %action_block_end;
|
||||
|
||||
statement = ( assignment | function | condition | action_block );
|
||||
|
||||
|
@ -296,9 +343,18 @@
|
|||
|
||||
%% write data;
|
||||
|
||||
config_parser_context_t *config_parser_context_new(GList *ctx_stack) {
|
||||
|
||||
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);
|
||||
return g_list_append(NULL, ctx);
|
||||
}
|
||||
|
||||
config_parser_context_t *config_parser_context_new(server *srv, GList *ctx_stack) {
|
||||
config_parser_context_t *ctx;
|
||||
|
||||
UNUSED(srv);
|
||||
|
||||
ctx = g_slice_new0(config_parser_context_t);
|
||||
|
||||
ctx->line = 1;
|
||||
|
@ -320,13 +376,23 @@ config_parser_context_t *config_parser_context_new(GList *ctx_stack) {
|
|||
return ctx;
|
||||
}
|
||||
|
||||
void config_parser_context_free(config_parser_context_t *ctx, gboolean free_queues)
|
||||
void config_parser_context_free(server *srv, config_parser_context_t *ctx, gboolean free_queues)
|
||||
{
|
||||
g_free(ctx->stack);
|
||||
|
||||
if (free_queues) {
|
||||
g_assert_cmpuint(ctx->action_list_stack->length, ==, 0);
|
||||
g_assert_cmpuint(ctx->option_stack->length, ==, 0);
|
||||
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);
|
||||
}
|
||||
|
||||
if (g_queue_get_length(ctx->option_stack) > 0) {
|
||||
option *o;
|
||||
while ((o = g_queue_pop_head(ctx->option_stack)))
|
||||
option_free(o);
|
||||
}
|
||||
|
||||
g_queue_free(ctx->action_list_stack);
|
||||
g_queue_free(ctx->option_stack);
|
||||
}
|
||||
|
@ -339,14 +405,14 @@ gboolean config_parser_file(server *srv, GList *ctx_stack, const gchar *path) {
|
|||
gboolean res;
|
||||
GError *err = NULL;
|
||||
|
||||
ctx = config_parser_context_new(ctx_stack);
|
||||
ctx = config_parser_context_new(srv, ctx_stack);
|
||||
ctx->filename = (gchar*) path;
|
||||
|
||||
if (!g_file_get_contents(path, &ctx->ptr, &ctx->len, &err))
|
||||
{
|
||||
/* could not read file */
|
||||
log_warning(srv, NULL, "could not read config file \"%s\". reason: \"%s\" (%d)", path, err->message, err->code);
|
||||
config_parser_context_free(ctx, FALSE);
|
||||
config_parser_context_free(srv, ctx, TRUE);
|
||||
g_error_free(err);
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -364,7 +430,7 @@ gboolean config_parser_file(server *srv, GList *ctx_stack, const gchar *path) {
|
|||
|
||||
/* have to free the buffer on our own */
|
||||
g_free(ctx->ptr);
|
||||
config_parser_context_free(ctx, FALSE);
|
||||
config_parser_context_free(srv, ctx, FALSE);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -378,13 +444,13 @@ gboolean config_parser_shell(server *srv, GList *ctx_stack, const gchar *command
|
|||
config_parser_context_t *ctx;
|
||||
GError *err = NULL;
|
||||
|
||||
ctx = config_parser_context_new(ctx_stack);
|
||||
ctx = config_parser_context_new(srv, ctx_stack);
|
||||
ctx->filename = (gchar*) command;
|
||||
|
||||
if (!g_spawn_command_line_sync(command, &_stdout, &_stderr, &status, &err))
|
||||
{
|
||||
log_warning(srv, NULL, "error launching shell command \"%s\": %s (%d)", command, err->message, err->code);
|
||||
config_parser_context_free(ctx, FALSE);
|
||||
config_parser_context_free(srv, ctx, TRUE);
|
||||
g_error_free(err);
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -395,7 +461,7 @@ gboolean config_parser_shell(server *srv, GList *ctx_stack, const gchar *command
|
|||
log_debug(srv, NULL, "stdout:\n-----\n%s\n-----\nstderr:\n-----\n%s\n-----", _stdout, _stderr);
|
||||
g_free(_stdout);
|
||||
g_free(_stderr);
|
||||
config_parser_context_free(ctx, FALSE);
|
||||
config_parser_context_free(srv, ctx, FALSE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -413,7 +479,7 @@ gboolean config_parser_shell(server *srv, GList *ctx_stack, const gchar *command
|
|||
|
||||
g_free(_stdout);
|
||||
g_free(_stderr);
|
||||
config_parser_context_free(ctx, FALSE);
|
||||
config_parser_context_free(srv, ctx, FALSE);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -69,16 +69,17 @@ int main(int argc, char *argv[]) {
|
|||
g_get_current_time(&start);
|
||||
|
||||
/* standard config frontend */
|
||||
config_parser_context_t *ctx = config_parser_context_new(NULL);
|
||||
GList *ctx_stack = g_list_append(NULL, ctx);
|
||||
GList *ctx_stack = config_parser_init(srv);
|
||||
config_parser_context_t *ctx = (config_parser_context_t*) ctx_stack->data;
|
||||
if (!config_parser_file(srv, ctx_stack, config_path)) {
|
||||
for (guint i = 0; i < g_queue_get_length(ctx->action_list_stack); i++) { /* TODO */ }
|
||||
for (guint i = 0; i < g_queue_get_length(ctx->option_stack); i++) { option_free(g_queue_peek_nth(ctx->option_stack, i)); }
|
||||
config_parser_context_free(ctx, TRUE);
|
||||
config_parser_context_free(srv, ctx, FALSE);
|
||||
log_thread_start(srv);
|
||||
g_atomic_int_set(&srv->exiting, TRUE);
|
||||
log_thread_wakeup(srv);
|
||||
g_thread_join(srv->log_thread);
|
||||
server_free(srv);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -88,7 +89,7 @@ int main(int argc, char *argv[]) {
|
|||
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);
|
||||
g_print("option_stack: %u action_list_stack: %u\n", g_queue_get_length(ctx->option_stack), g_queue_get_length(ctx->action_list_stack));
|
||||
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 {
|
||||
#ifdef HAVE_LUA_H
|
||||
|
|
|
@ -256,7 +256,7 @@ void log_free(server *srv, log_t *log) {
|
|||
void log_init(server *srv) {
|
||||
GString *str;
|
||||
|
||||
srv->logs = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, (GDestroyNotify) log_free);
|
||||
srv->logs = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
|
||||
srv->log_queue = g_async_queue_new();
|
||||
srv->log_mutex = g_mutex_new();
|
||||
|
||||
|
|
10
src/server.c
10
src/server.c
|
@ -21,6 +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();
|
||||
|
||||
return srv;
|
||||
}
|
||||
|
@ -35,8 +36,17 @@ void server_free(server* srv) {
|
|||
g_hash_table_destroy(srv->plugins);
|
||||
g_mutex_free(srv->mutex);
|
||||
|
||||
action_list_release(srv, srv->mainactionlist);
|
||||
|
||||
/* free logs */
|
||||
GHashTableIter iter;
|
||||
gpointer k, v;
|
||||
g_hash_table_iter_init(&iter, srv->logs);
|
||||
while (g_hash_table_iter_next(&iter, &k, &v)) {
|
||||
log_free(srv, v);
|
||||
}
|
||||
g_hash_table_destroy(srv->logs);
|
||||
|
||||
g_mutex_free(srv->log_mutex);
|
||||
g_async_queue_unref(srv->log_queue);
|
||||
|
||||
|
|
Loading…
Reference in New Issue