config parser changes

personal/stbuehler/wip
Thomas Porzelt 14 years ago
parent d10756d047
commit aca2f46bf6
  1. 27
      src/config_parser.h
  2. 111
      src/config_parser.rl
  3. 4
      src/lighttpd.c
  4. 5
      src/options.c
  5. 1
      src/server.c
  6. 3
      src/server.h
  7. 13
      src/tests.c

@ -1,21 +1,32 @@
#include "condition.h"
struct config_parser_context_t;
typedef struct config_parser_context_t config_parser_context_t;
struct config_parser_data_t;
typedef struct config_parser_data_t config_parser_data_t;
struct config_parser_filestack_entry_t;
typedef struct config_parser_filestack_entry_t config_parser_filestack_entry_t;
/* initializes the config parser */
config_parser_context_t *config_parser_init();
/* loads a file into memory and parses it */
gboolean config_parser_file(server *srv, GList **cpd_stack, const gchar *path);
gboolean config_parser_file(server *srv, config_parser_context_t *ctx, const gchar *path);
/* launched a command through the shell and parses the stdout it returns */
gboolean config_parser_shell(server *srv, GList **cpd_stack, const gchar *command);
gboolean config_parser_shell(server *srv, config_parser_context_t *ctx, const gchar *command);
/* parses a buffer pointed to by the previously allocated config_parser_data struct */
gboolean config_parser_buffer(server *srv, GList **cpd_stack);
gboolean config_parser_buffer(server *srv, config_parser_context_t *ctx);
config_parser_data_t *config_parser_data_new();
void config_parser_data_free(config_parser_data_t *cpd);
struct config_parser_context_t {
GList *action_list_stack;
GList *stack;
};
struct config_parser_data_t {
/* information of currently parsed file */
gchar *filename;
@ -34,11 +45,19 @@ struct config_parser_data_t {
gchar *mark;
gchar *mark_var;
/* action list stack */
GList *action_list_stack;
/* current value */
enum { CONFP_BOOL, CONFP_INT, CONFP_STR, CONFP_LIST, CONFP_HASH } val_type;
enum { CONFP_BOOL, CONFP_INT, CONFP_STR, CONFP_LIST, CONFP_HASH } val_type, val_type_last;
GString *val_str;
gint val_int;
gboolean val_bool;
GArray *val_list;
GHashTable *val_hash;
option *opt;
/* operator */
comp_operator_t operator;

@ -1,12 +1,8 @@
#include <stdio.h>
#include <glib.h>
#include <assert.h>
#include <string.h>
#include "base.h"
#include "config_parser.h"
#if 1
#define _printf(fmt, ...) printf(fmt, __VA_ARGS__)
#define _printf(fmt, ...) g_print(fmt, __VA_ARGS__)
#else
#define _printf(fmt, ...) /* */
#endif
@ -45,12 +41,14 @@
cpd->val_bool = FALSE;
_printf("got boolean %s in line %zd of %s\n", cpd->val_bool ? "true" : "false", cpd->line, cpd->filename);
}
action string {
g_string_truncate(cpd->val_str, 0);
g_string_append_len(cpd->val_str, cpd->mark + 1, fpc - cpd->mark - 2);
cpd->val_type = CONFP_STR;
_printf("got string: \"%s\" in line %zd of %s\n", cpd->val_str->str, cpd->line, cpd->filename);
}
action integer
{
gchar *c;
@ -107,12 +105,54 @@
_printf("%c", (int)*c);
_printf(" (%d) in line %zd of %s\n", cpd->operator, cpd->line, cpd->filename);
}
action assignment { _printf("got assignment for var %s in line %zd of %s\n", cpd->varname->str, cpd->line, cpd->filename); }
action assignment {
action *a;
option *o;
action_list *al;
switch (cpd->val_type) {
case CONFP_BOOL:
o = option_new_bool(cpd->val_bool);
break;
case CONFP_INT:
o = option_new_int(cpd->val_int);
break;
case CONFP_STR:
o = option_new_string(cpd->val_str);
break;
case CONFP_LIST:
o = option_new_list();
g_array_free(o->value.opt_list, TRUE);
o->value.opt_list = cpd->val_list;
break;
case CONFP_HASH:
o = option_new_hash();
g_hash_table_destroy(o->value.opt_hash);
o->value.opt_hash = cpd->val_hash;
break;
}
a = action_new_setting(srv, cpd->varname, o);
if (a == NULL) {
option_free(o);
return FALSE;
}
al = ctx->action_list_stack->data;
g_array_append_val(al->actions, a);
_printf("got assignment for var %s in line %zd of %s\n", cpd->varname->str, cpd->line, cpd->filename);
}
action function {
if (g_str_equal(cpd->varname->str, "include") || g_str_equal(cpd->varname->str, "include_shell"))
break;
_printf("got function call to %s in line %zd of %s\n", cpd->varname->str, cpd->line, cpd->filename);
}
action condition { _printf("got condition for var %s in line %zd of %s\n", cpd->varname->str, cpd->line, cpd->filename); }
action fooblock { _printf("got fooblock in line %zd of %s\n", cpd->line, cpd->filename); }
@ -135,20 +175,20 @@
action incl {
_printf("including file %s in line %zd of %s\n", cpd->val_str->str, cpd->line, cpd->filename);
if (!config_parser_file(srv, cpd_stack, cpd->val_str->str))
if (!config_parser_file(srv, ctx, cpd->val_str->str))
return FALSE;
}
action incl_shell {
if (!config_parser_shell(srv, cpd_stack, cpd->val_str->str))
if (!config_parser_shell(srv, ctx, cpd->val_str->str))
return FALSE;
}
action done { _printf("done\n"); }
# tokens
boolean = ( 'true' | 'false' ) %boolean;
integer = ( 0 | ( [1-9] [0-9]* ) ) %integer;
string = ( '"' (any-'"')* '"' ) %string;
boolean = ( 'true' | 'false' ) >mark %boolean;
integer = ( 0 | ( [1-9] [0-9]* ) ) >mark %integer;
string = ( '"' (any-'"')* '"' ) >mark %string;
ws = ( ' ' | '\t' );
lineUnix = ( '\n' ) %line;
@ -160,7 +200,7 @@
comment = ( '#' (any - line)* line ) %comment;
value = ( boolean | integer | string ) >mark %value;
value = ( boolean | integer | string ) %value;
valuepair = ( string ws* '=>' ws* value ) %valuepair;
list = ( '(' ) >list_start;
@ -176,7 +216,9 @@
operator = ( '==' | '!=' | '=~' | '!~' | '<' | '<=' | '>' | '>=' ) >mark %operator;
assignment = ( varname ws* '=' ws* (value|valuepair|list|hash) ';' ) %assignment;
#assignment_bool = ( varname ws* '=' ws* boolean ';' ) %assignment_bool;
assignment = ( varname ws* '=' ws* ( value | list | hash) ';' ) %assignment;
#assignment = ( assignment_bool ) %assignment;
function = ( varname (ws+ (value|valuepair|list|hash))? ';' ) %function;
@ -204,6 +246,25 @@
%% write data;
config_parser_context_t *config_parser_init() {
config_parser_context_t *ctx;
action_list *al;
ctx = g_slice_new(config_parser_context_t);
ctx->stack = NULL;
al = action_list_new();
ctx->action_list_stack = g_list_prepend(NULL, al);
return ctx;
}
void config_parser_finish(config_parser_context_t *ctx) {
assert(ctx->stack == NULL);
g_slice_free(config_parser_context_t, ctx);
}
config_parser_data_t *config_parser_data_new() {
config_parser_data_t *cpd;
@ -232,7 +293,7 @@ void config_parser_data_free(config_parser_data_t *cpd)
g_slice_free(config_parser_data_t, cpd);
}
gboolean config_parser_file(server *srv, GList **cpd_stack, const gchar *path) {
gboolean config_parser_file(server *srv, config_parser_context_t *ctx, const gchar *path) {
gboolean res;
config_parser_data_t *cpd;
GError *err = NULL;
@ -251,12 +312,12 @@ gboolean config_parser_file(server *srv, GList **cpd_stack, const gchar *path) {
}
/* push on stack */
*cpd_stack = g_list_prepend(*cpd_stack, cpd);
ctx->stack = g_list_prepend(ctx->stack, cpd);
res = config_parser_buffer(srv, cpd_stack);
res = config_parser_buffer(srv, ctx);
/* pop from stack */
*cpd_stack = g_list_delete_link(*cpd_stack, *cpd_stack);
ctx->stack = g_list_delete_link(ctx->stack, ctx->stack);
/* have to free the buffer on our own */
g_free(cpd->ptr);
@ -265,7 +326,7 @@ gboolean config_parser_file(server *srv, GList **cpd_stack, const gchar *path) {
return res;
}
gboolean config_parser_shell(server *srv, GList **cpd_stack, const gchar *command)
gboolean config_parser_shell(server *srv, config_parser_context_t *ctx, const gchar *command)
{
gboolean res;
gchar* _stdout;
@ -300,9 +361,9 @@ gboolean config_parser_shell(server *srv, GList **cpd_stack, const gchar *comman
_printf("included shell output from \"%s\" (%zu bytes):\n%s\n", command, cpd->len, _stdout);
*cpd_stack = g_list_prepend(*cpd_stack, cpd);
res = config_parser_buffer(srv, cpd_stack);
*cpd_stack = g_list_delete_link(*cpd_stack, *cpd_stack);
ctx->stack = g_list_prepend(ctx->stack, cpd);
res = config_parser_buffer(srv, ctx);
ctx->stack = g_list_delete_link(ctx->stack, ctx->stack);
g_free(_stdout);
g_free(_stderr);
@ -311,12 +372,12 @@ gboolean config_parser_shell(server *srv, GList **cpd_stack, const gchar *comman
return res;
}
gboolean config_parser_buffer(server *srv, GList **cpd_stack)
gboolean config_parser_buffer(server *srv, config_parser_context_t *ctx)
{
config_parser_data_t *cpd;
/* get top of stack */
cpd = (*cpd_stack)->data;
cpd = ctx->stack->data;
cpd->p = cpd->ptr;
cpd->pe = cpd->ptr + cpd->len + 1; /* marks the end of the data to scan (+1 because of trailing \0 char) */
@ -328,7 +389,7 @@ gboolean config_parser_buffer(server *srv, GList **cpd_stack)
if (cpd->cs == config_parser_error || cpd->cs == config_parser_first_final)
{
/* parse error */
printf("parse error in line %zd of \"%s\" at character %c (0x%.2x)\n", cpd->line, cpd->filename, *cpd->p, *cpd->p);
g_printerr("parse error in line %zd of \"%s\" at character %c (0x%.2x)\n", cpd->line, cpd->filename, *cpd->p, *cpd->p);
return FALSE;
}

@ -54,8 +54,8 @@ int main(int argc, char *argv[]) {
if (!luaconfig) {
/* standard config frontend */
GList *cpd_stack = NULL;
if (!config_parser_file(srv, &cpd_stack, config_path)) {
config_parser_context_t *cp_ctx = config_parser_init();
if (!config_parser_file(srv, cp_ctx, config_path)) {
return 1;
}
}

@ -5,24 +5,28 @@
option* option_new_bool(gboolean val) {
option *opt = g_slice_new0(option);
opt->value.opt_bool = val;
opt->type = OPTION_BOOLEAN;
return opt;
}
option* option_new_int(gint val) {
option *opt = g_slice_new0(option);
opt->value.opt_int = val;
opt->type = OPTION_INT;
return opt;
}
option* option_new_string(GString *val) {
option *opt = g_slice_new0(option);
opt->value.opt_string = val;
opt->type = OPTION_STRING;
return opt;
}
option* option_new_list() {
option *opt = g_slice_new0(option);
opt->value.opt_list = g_array_new(FALSE, TRUE, sizeof(option*));
opt->type = OPTION_LIST;
return opt;
}
@ -39,6 +43,7 @@ option* option_new_hash() {
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);
opt->type = OPTION_HASH;
return opt;
}

@ -8,6 +8,7 @@ server* server_new() {
srv->plugins = g_hash_table_new(g_str_hash, g_str_equal);
srv->options = g_hash_table_new(g_str_hash, g_str_equal);
srv->mutex = g_mutex_new();
srv->actions = action_list_new();
return srv;
}

@ -1,11 +1,14 @@
#ifndef _LIGHTTPD_SERVER_H_
#define _LIGHTTPD_SERVER_H_
struct server {
guint version;
GHashTable *plugins;
struct action_list *actions;
size_t option_count;
GHashTable *options;
gpointer *option_def_values;

@ -34,22 +34,9 @@ int request_test() {
int main() {
server *srv;
GTimeVal start, end;
gboolean result;
srv = server_new();
/* config parser test */
GList *cpd_stack = NULL;
g_get_current_time(&start);
result = config_parser_file(srv, &cpd_stack, "../test.conf");
g_get_current_time(&end);
printf("parsed config in %ld seconds %ld milliseconds and %ld microseconds\n",
end.tv_sec - start.tv_sec,
(end.tv_usec - start.tv_usec) / 1000,
(end.tv_usec - start.tv_usec) % 1000
);
return request_test();
}

Loading…
Cancel
Save