diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2018-06-04 11:11:20 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2018-06-04 11:11:20 +0300 |
commit | c3850a4d3f94436aab6b23020242bc99c71506ee (patch) | |
tree | 644cd582c39c833124d1d071a4b7738bac97428d /src | |
parent | 43a1c4ce04cf9301b88c8df31087fe84dcb7e232 (diff) | |
download | grecs-c3850a4d3f94436aab6b23020242bc99c71506ee.tar.gz grecs-c3850a4d3f94436aab6b23020242bc99c71506ee.tar.bz2 |
json: improve parser reentrability
* include/grecs/json.h (jsonlex_cleanup): New proto.
* src/json-lex.l (jsonlex_setup): Initialize parser state.
Initialize json_current_locus_point.file to a non-NULL value.
(jsonlex_cleanup): New function.
* src/json-gram.y (json_parse_string): Call jsonlex_cleanup before returning.
* src/diag.c (default_print_diag): Print the passed errcode argument,
instead of errno.
Diffstat (limited to 'src')
-rw-r--r-- | src/diag.c | 2 | ||||
-rw-r--r-- | src/json-gram.y | 1 | ||||
-rw-r--r-- | src/json-lex.l | 35 |
3 files changed, 25 insertions, 13 deletions
@@ -28,25 +28,25 @@ default_print_diag(grecs_locus_t const *locus, int err, int errcode, const char *msg) { fflush(stdout); if (locus) { YY_LOCATION_PRINT(stderr, *locus); fputc(':', stderr); fputc(' ', stderr); } if (!err) fprintf(stderr, "warning: "); fprintf(stderr, "%s", msg); if (errcode) - fprintf(stderr, ": %s", strerror(errno)); + fprintf(stderr, ": %s", strerror(errcode)); fputc('\n', stderr); } void (*grecs_print_diag_fun)(grecs_locus_t const *, int, int, const char *msg) = default_print_diag; void grecs_warning(grecs_locus_t const *locus, int errcode, const char *fmt, ...) { va_list ap; char *buf = NULL; diff --git a/src/json-gram.y b/src/json-gram.y index fe8996b..d5b0248 100644 --- a/src/json-gram.y +++ b/src/json-gram.y @@ -271,24 +271,25 @@ json_assoc_create() NULL, json_st_free); } struct json_value * json_parse_string(char const *input, size_t len) { jsonlex_setup(input, len); if (yyparse()) { /* FIXME: error recovery */ return NULL; } + jsonlex_cleanup(); return json_return_obj; } struct json_value * json_value_lookup(struct json_value *obj, const char *ident) { char *qbuf = NULL; size_t qlen = 0; while (obj && *ident) { char const *p; char *q; diff --git a/src/json-lex.l b/src/json-lex.l index 169cf32..4bbdedf 100644 --- a/src/json-lex.l +++ b/src/json-lex.l @@ -46,36 +46,24 @@ struct grecs_locus json_err_locus; } while(0) #define YY_USER_ACTION do { \ if (YYSTATE == 0) { \ yylloc.beg = json_current_locus_point; \ yylloc.beg.col++; \ } \ json_current_locus_point.col += yyleng; \ yylloc.end = json_current_locus_point; \ } while (0); void -jsonlex_setup(char const *s, size_t l) -{ - input_ptr = s; - input_size = l; - json_current_locus_point.file = NULL; - json_current_locus_point.line = 1; - json_current_locus_point.col = 0; - json_err_diag = NULL; - yy_flex_debug = 0; -} - -void jsonlex_diag(const char *s) { if (!json_err_diag) { json_err_diag = s; json_err_locus = yylloc; } } static int utf8_wctomb(char *u) { unsigned int wc = strtoul(u, NULL, 16); @@ -218,12 +206,35 @@ X [0-9a-fA-F] return T_ERR; } json_line_grow(&c, 1); } null { return T_NULL; } true { yylval.b = 1; return T_BOOL; } false { yylval.b = 0; return T_BOOL; } "{"|"}"|"["|"]"|":"|"," return yytext[0]; [ \t]* ; \n grecs_locus_point_advance_line(json_current_locus_point); . { jsonlex_diag("bogus character"); return T_ERR; } +%% +void +jsonlex_setup(char const *s, size_t l) +{ + input_ptr = s; + input_size = l; + json_current_locus_point.file = "input"; + json_current_locus_point.line = 1; + json_current_locus_point.col = 0; + json_err_diag = NULL; + yy_flex_debug = 0; + BEGIN(INITIAL); + yyrestart(NULL); +} + +void +jsonlex_cleanup(void) +{ + if (json_line_acc) { + grecs_txtacc_free(json_line_acc); + json_line_acc = NULL; + } +} |