Skip to content

Commit

Permalink
fix #65
Browse files Browse the repository at this point in the history
  • Loading branch information
Sergey Lvov committed May 6, 2016
1 parent c9efd94 commit 81b7dbb
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 75 deletions.
149 changes: 74 additions & 75 deletions tempesta_fw/cfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
* - Improve efficiency: too many memory allocations and data copying.
*
* Copyright (C) 2014 NatSys Lab. ([email protected]).
* Copyright (C) 2015 Tempesta Technologies, Inc.
* Copyright (C) 2015-2016 Tempesta Technologies, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -110,6 +110,50 @@
* but they have to be NULL-terminated, so we have to allocate space and copy
* them. Helpers below facilitate that.
*/
typedef enum {
TOKEN_NA = 0,
TOKEN_LBRACE,
TOKEN_RBRACE,
TOKEN_EQSIGN,
TOKEN_SEMICOLON,
TOKEN_LITERAL,
_TOKEN_COUNT,
} token_t;

typedef struct {
const char *in; /* The whole input buffer. */
const char *pos; /* Current position in the @in buffer. */
int line; /* Current line. */

/* Current FSM state is saved to here. */
const void *fsm_s; /* Pointer to label (GCC extension). */
const char *fsm_ss; /* Label name as string (for debugging). */

/* Currently/previously processed character. */
char c;
char prev_c;

/* Currently/previously processed token.
* The language is context-sensitive, so we need to store all these
* previous tokens and literals to parse it without peek()'ing. */
token_t t;
token_t prev_t;

/* Literal value (not NULL only when @t == TOKEN_LITERAL). */
const char *lit;
const char *prev_lit;

/* Length of @lit (the @lit is not terminated). */
int lit_len;
int prev_lit_len;

int err; /* The latest error code. */

/* Currently parsed entry. Accumulates literals as values/attributes.
* When current entry is done, a TfwCfgSpec->handler is called and a new
* entry is started. */
TfwCfgEntry e;
} TfwCfgParserState;

static const char *
alloc_and_copy_literal(const char *src, size_t len)
Expand All @@ -125,8 +169,7 @@ alloc_and_copy_literal(const char *src, size_t len)
TFW_ERR("can't allocate memory\n");
return NULL;
}

/* Copy the string eating escaping backslashes. */
/* Copy the string eating escaping backslashes. */
/* FIXME: the logic looks like a tiny FSM,
* so perhaps it should be included to the TFSM. */
src_end = src + len;
Expand All @@ -145,10 +188,17 @@ alloc_and_copy_literal(const char *src, size_t len)
++src_pos;
}
*dst_pos = '\0';

return dst;
}

static inline void
print_parse_error(const TfwCfgParserState *ps)
{

TFW_ERR("configuration parsing error str:%d;w:%s\n", ps->e.line + 1 , ps->e.name);
}


/**
* Check name of an attribute or name
*
Expand Down Expand Up @@ -304,49 +354,7 @@ entry_add_attr(TfwCfgEntry *e, const char *key_src, size_t key_len,
* characters respectively).
*/

typedef enum {
TOKEN_NA = 0,
TOKEN_LBRACE,
TOKEN_RBRACE,
TOKEN_EQSIGN,
TOKEN_SEMICOLON,
TOKEN_LITERAL,
_TOKEN_COUNT,
} token_t;

typedef struct {
const char *in; /* The whole input buffer. */
const char *pos; /* Current position in the @in buffer. */

/* Current FSM state is saved to here. */
const void *fsm_s; /* Pointer to label (GCC extension). */
const char *fsm_ss; /* Label name as string (for debugging). */

/* Currently/previously processed character. */
char c;
char prev_c;

/* Currently/previously processed token.
* The language is context-sensitive, so we need to store all these
* previous tokens and literals to parse it without peek()'ing. */
token_t t;
token_t prev_t;

/* Literal value (not NULL only when @t == TOKEN_LITERAL). */
const char *lit;
const char *prev_lit;

/* Length of @lit (the @lit is not terminated). */
int lit_len;
int prev_lit_len;

int err; /* The latest error code. */

/* Currently parsed entry. Accumulates literals as values/attributes.
* When current entry is done, a TfwCfgSpec->handler is called and a new
* entry is started. */
TfwCfgEntry e;
} TfwCfgParserState;

/* Macros common for both TFSM and PFSM. */

Expand Down Expand Up @@ -374,11 +382,14 @@ do { \

/* Macros specific to TFSM. */

#define TFSM_MOVE(to_state) \
do { \
ps->prev_c = ps->c; \
ps->c = *(++ps->pos); \
#define TFSM_MOVE(to_state) \
do { \
ps->prev_c = ps->c; \
ps->c = *(++ps->pos); \
TFW_DBG3("tfsm move: '%c' -> '%c'\n", ps->prev_c, ps->c); \
if (ps->prev_c == '\n') { \
++ps->line; \
} \
FSM_JMP(to_state); \
} while (0)

Expand Down Expand Up @@ -600,6 +611,7 @@ parse_cfg_entry(TfwCfgParserState *ps)
TFW_DBG3("set name: %.*s\n", ps->lit_len, ps->lit);

ps->err = entry_set_name(&ps->e, ps->lit, ps->lit_len);
ps->e.line = ps->line;
FSM_COND_JMP(ps->err, PS_EXIT);

PFSM_MOVE(PS_VAL_OR_ATTR);
Expand Down Expand Up @@ -1107,13 +1119,13 @@ tfw_cfg_handle_children(TfwCfgSpec *cs, TfwCfgEntry *e)
while (ps->t && (ps->t != TOKEN_RBRACE)) {
parse_cfg_entry(ps);
if (ps->err) {
TFW_ERR("parser error\n");
print_parse_error(ps);
return ps->err;
}

matching_spec = spec_find(nested_specs, ps->e.name);
if (!matching_spec) {
TFW_ERR("don't know how to handle: %s\n", ps->e.name);
print_parse_error(ps);
return -EINVAL;
}

Expand Down Expand Up @@ -1365,17 +1377,6 @@ mod_stop(TfwCfgMod *mod)
mod->stop();
}

static void
print_parse_error(const TfwCfgParserState *ps)
{
const char *start = max((ps->pos - 80), ps->in);
int len = ps->pos - start;

TFW_ERR("configuration parsing error:\n"
"%.*s\n"
"^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n",
len, start);
}

/*
* Find configuration option specs by option name.
Expand Down Expand Up @@ -1413,9 +1414,9 @@ tfw_cfg_parse_mods_cfg(const char *cfg_text, struct list_head *mod_list)

do {
parse_cfg_entry(&ps);
if (ps.err) {
TFW_ERR("syntax error\n");
goto err;
if (ps.err){
print_parse_error(&ps);
return -EINVAL;
}
if (!ps.e.name)
break; /* EOF - nothing is parsed and no error. */
Expand All @@ -1426,25 +1427,23 @@ tfw_cfg_parse_mods_cfg(const char *cfg_text, struct list_head *mod_list)
break;
}
if (!matching_spec) {
TFW_ERR("don't know how to handle: '%s'\n", ps.e.name);
goto err;
print_parse_error(&ps);
return -EINVAL;
}

r = spec_handle_entry(matching_spec, &ps.e);
if (r)
goto err;
print_parse_error(&ps);

} while (ps.t);

MOD_FOR_EACH(mod, mod_list) {
r = spec_finish_handling(mod->specs);
if (r)
goto err;
}
print_parse_error(&ps);

}
return 0;
err:
print_parse_error(&ps);
return -EINVAL;
}
EXPORT_SYMBOL(tfw_cfg_parse_mods_cfg);

Expand All @@ -1466,7 +1465,7 @@ tfw_cfg_start_mods(const char *cfg_text, struct list_head *mod_list)
TFW_DBG2("parsing configuration and pushing it to modules...\n");
ret = tfw_cfg_parse_mods_cfg(cfg_text, mod_list);
if (ret) {
TFW_ERR("can't parse configuration data\n");
TFW_ERR("can't parse configuration data, %d\n", ret);
goto err_recover_cleanup;
}

Expand Down
1 change: 1 addition & 0 deletions tempesta_fw/cfg.h
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ typedef struct {
size_t val_n;
size_t attr_n;
const char *name;
int line;
const char *vals[TFW_CFG_ENTRY_VAL_MAX];
struct {
const char *key;
Expand Down

0 comments on commit 81b7dbb

Please sign in to comment.