From 05b7837070d928d9dc96e854d3ca39ec86929c29 Mon Sep 17 00:00:00 2001 From: Enno Rehling Date: Fri, 10 Nov 2017 07:56:56 +0100 Subject: [PATCH] fix parser to keep a reference to the order it is parsing. make push/popstate not crash. pass unit tests. --- src/kernel/order.c | 7 ++++++- src/kernel/orderdb.c | 5 +++++ src/kernel/orderdb.h | 1 + src/study.c | 2 +- src/util/parser.c | 22 ++++++++++++++++++---- src/util/parser.h | 1 + 6 files changed, 32 insertions(+), 6 deletions(-) diff --git a/src/kernel/order.c b/src/kernel/order.c index 51cefd791..c4571cea1 100644 --- a/src/kernel/order.c +++ b/src/kernel/order.c @@ -523,8 +523,13 @@ keyword_t init_order(const struct order *ord, const struct locale *lang) init_tokens_str(skillname(sk, lang)); } else { + const char *str; parser_od = odata_load(ord->id); - init_tokens_str(OD_STRING(parser_od)); + if (parser_od) { + odata_addref(parser_od); + } + str = OD_STRING(parser_od); + init_tokens_ex(str, parser_od, odata_release); } return kwd; } diff --git a/src/kernel/orderdb.c b/src/kernel/orderdb.c index a20bcf1e7..ee23993e6 100644 --- a/src/kernel/orderdb.c +++ b/src/kernel/orderdb.c @@ -31,6 +31,11 @@ void odata_release(order_data * od) } } +void odata_addref(order_data *od) +{ + ++od->_refcount; +} + order_data *odata_load(int id) { return db_load_order(id); diff --git a/src/kernel/orderdb.h b/src/kernel/orderdb.h index d25fcb3cf..800732c5e 100644 --- a/src/kernel/orderdb.h +++ b/src/kernel/orderdb.h @@ -14,6 +14,7 @@ extern "C" { void odata_create(order_data **pdata, size_t len, const char *str); void odata_release(order_data * od); + void odata_addref(order_data *od); order_data *odata_load(int id); int odata_save(order_data *od); diff --git a/src/study.c b/src/study.c index a80fa932f..9264f9060 100644 --- a/src/study.c +++ b/src/study.c @@ -371,7 +371,7 @@ int teach_cmd(unit * teacher, struct order *ord) token = getstrtoken(); /* Beginne die Fehlermeldung */ - if (token && isparam(token, teacher->faction->locale, P_TEMP)) { + if (isparam(token, teacher->faction->locale, P_TEMP)) { token = getstrtoken(); sprintf(tbuf, "%s %s", LOC(teacher->faction->locale, parameters[P_TEMP]), token); diff --git a/src/util/parser.c b/src/util/parser.c index 46a9d3a28..5a322005f 100644 --- a/src/util/parser.c +++ b/src/util/parser.c @@ -16,6 +16,8 @@ typedef struct parser_state { const char *current_token; struct parser_state *next; + void *data; + void(*dtor)(void *); } parser_state; static parser_state *states; @@ -50,17 +52,26 @@ static int eatwhitespace_c(const char **str_p) return ret; } -void init_tokens_str(const char *initstr) +void init_tokens_ex(const char *initstr, void *data, void (*dtor)(void *)) { if (states == NULL) { - states = malloc(sizeof(parser_state)); + states = calloc(1, sizeof(parser_state)); } + else if (states->dtor) { + states->dtor(states->data); + } + states->dtor = dtor; + states->data = data; states->current_token = initstr; } +void init_tokens_str(const char *initstr) { + init_tokens_ex(initstr, NULL, NULL); +} + void parser_pushstate(void) { - parser_state *new_state = malloc(sizeof(parser_state)); + parser_state *new_state = calloc(1, sizeof(parser_state)); new_state->current_token = NULL; new_state->next = states; states = new_state; @@ -69,6 +80,9 @@ void parser_pushstate(void) void parser_popstate(void) { parser_state *new_state = states->next; + if (states->dtor) { + states->dtor(states->data); + } free(states); states = new_state; } @@ -254,7 +268,7 @@ unsigned int atoip(const char *s) int n; assert(s); - n = (s[0] >='0' && s[0]<='9'); + n = (s[0] >= '0' && s[0] <= '9'); n = n ? atoi(s) : 0; if (n < 0) diff --git a/src/util/parser.h b/src/util/parser.h index 0c8306931..52fdbc4f4 100644 --- a/src/util/parser.h +++ b/src/util/parser.h @@ -18,6 +18,7 @@ extern "C" { #endif + void init_tokens_ex(const char *initstr, void *data, void(*dtor)(void *)); void init_tokens_str(const char *initstr); /* initialize token parsing */ void skip_token(void); const char *parse_token_depr(const char **str);