From de9753f9c426ceda569028ed71e41043c875af93 Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin Date: Wed, 23 Oct 2013 09:45:49 +0200 Subject: [PATCH] Refactor error handling --- include/ucl.h | 17 ++++--- src/ucl_internal.h | 5 +- src/ucl_parser.c | 136 +++++++++++++++++++++++++---------------------------- src/ucl_util.c | 56 +++++++++++++--------- 4 files changed, 110 insertions(+), 104 deletions(-) diff --git a/include/ucl.h b/include/ucl.h index 37ec2e0..f0e4beb 100644 --- a/include/ucl.h +++ b/include/ucl.h @@ -624,7 +624,7 @@ ucl_object_keyl (ucl_object_t *obj, size_t *len) * @param err error pointer * @return true if macro has been parsed */ -typedef bool (*ucl_macro_handler) (const unsigned char *data, size_t len, void* ud, UT_string **err); +typedef bool (*ucl_macro_handler) (const unsigned char *data, size_t len, void* ud); /* Opaque parser */ struct ucl_parser; @@ -654,8 +654,7 @@ void ucl_parser_register_macro (struct ucl_parser *parser, const char *macro, * @param err if *err is NULL it is set to parser error * @return true if chunk has been added and false in case of error */ -bool ucl_parser_add_chunk (struct ucl_parser *parser, const unsigned char *data, - size_t len, UT_string **err); +bool ucl_parser_add_chunk (struct ucl_parser *parser, const unsigned char *data, size_t len); /** * Load and add data from a file @@ -664,8 +663,7 @@ bool ucl_parser_add_chunk (struct ucl_parser *parser, const unsigned char *data, * @param err if *err is NULL it is set to parser error * @return true if chunk has been added and false in case of error */ -bool ucl_parser_add_file (struct ucl_parser *parser, const char *filename, - UT_string **err); +bool ucl_parser_add_file (struct ucl_parser *parser, const char *filename); /** * Get a top object for a parser @@ -673,9 +671,14 @@ bool ucl_parser_add_file (struct ucl_parser *parser, const char *filename, * @param err if *err is NULL it is set to parser error * @return top parser object or NULL */ -ucl_object_t* ucl_parser_get_object (struct ucl_parser *parser, UT_string **err); +ucl_object_t* ucl_parser_get_object (struct ucl_parser *parser); /** + * Get the error string if failing + * @param parser parser object + */ +const char *ucl_parser_get_error(struct ucl_parser *parser); +/** * Free cl parser object * @param parser parser object */ @@ -725,6 +728,6 @@ unsigned char *ucl_object_emit (ucl_object_t *obj, enum ucl_emitter emit_type); * @param err if *err is NULL it is set to parser error * @return true if a key has been successfully added */ -bool ucl_pubkey_add (struct ucl_parser *parser, const unsigned char *key, size_t len, UT_string **err); +bool ucl_pubkey_add (struct ucl_parser *parser, const unsigned char *key, size_t len); #endif /* RCL_H_ */ diff --git a/src/ucl_internal.h b/src/ucl_internal.h index 97613c8..b5e5161 100644 --- a/src/ucl_internal.h +++ b/src/ucl_internal.h @@ -125,6 +125,7 @@ struct ucl_parser { struct ucl_stack *stack; struct ucl_chunk *chunks; struct ucl_pubkey *keys; + UT_string *err; }; /** @@ -141,7 +142,7 @@ size_t ucl_unescape_json_string (char *str, size_t len); * @param err error ptr * @return */ -bool ucl_include_handler (const unsigned char *data, size_t len, void* ud, UT_string **err); +bool ucl_include_handler (const unsigned char *data, size_t len, void* ud); /** * Handle includes macro @@ -151,7 +152,7 @@ bool ucl_include_handler (const unsigned char *data, size_t len, void* ud, UT_st * @param err error ptr * @return */ -bool ucl_includes_handler (const unsigned char *data, size_t len, void* ud, UT_string **err); +bool ucl_includes_handler (const unsigned char *data, size_t len, void* ud); size_t ucl_strlcpy (char *dst, const char *src, size_t siz); size_t ucl_strlcpy_unsafe (char *dst, const char *src, size_t siz); diff --git a/src/ucl_parser.c b/src/ucl_parser.c index 0c82dbb..3e42dd0 100644 --- a/src/ucl_parser.c +++ b/src/ucl_parser.c @@ -91,7 +91,7 @@ ucl_set_err (struct ucl_chunk *chunk, int code, const char *str, UT_string **err } static bool -ucl_skip_comments (struct ucl_parser *parser, UT_string **err) +ucl_skip_comments (struct ucl_parser *parser) { struct ucl_chunk *chunk = parser->chunks; const unsigned char *p; @@ -139,7 +139,7 @@ start: ucl_chunk_skipc (chunk, p); } if (comments_nested != 0) { - ucl_set_err (chunk, UCL_ENESTED, "comments nesting is invalid", err); + ucl_set_err (chunk, UCL_ENESTED, "comments nesting is invalid", &parser->err); return false; } } @@ -237,7 +237,7 @@ static inline size_t ucl_copy_or_store_ptr (struct ucl_parser *parser, const unsigned char *src, unsigned char **dst, const char **dst_const, size_t in_len, - bool need_unescape, bool need_lowercase, UT_string **err) + bool need_unescape, bool need_lowercase) { size_t ret = 0; @@ -245,7 +245,7 @@ ucl_copy_or_store_ptr (struct ucl_parser *parser, /* Copy string */ *dst = UCL_ALLOC (in_len + 1); if (*dst == NULL) { - ucl_set_err (parser->chunks, 0, "cannot allocate memory for a string", err); + ucl_set_err (parser->chunks, 0, "cannot allocate memory for a string", &parser->err); return false; } if (need_lowercase) { @@ -493,12 +493,11 @@ ucl_maybe_parse_number (ucl_object_t *obj, * Parse possible number * @param parser * @param chunk - * @param err * @return true if a number has been parsed */ static bool ucl_lex_number (struct ucl_parser *parser, - struct ucl_chunk *chunk, ucl_object_t *obj, UT_string **err) + struct ucl_chunk *chunk, ucl_object_t *obj) { const unsigned char *pos; int ret; @@ -512,7 +511,7 @@ ucl_lex_number (struct ucl_parser *parser, return true; } else if (ret == ERANGE) { - ucl_set_err (chunk, ERANGE, "numeric value out of range", err); + ucl_set_err (chunk, ERANGE, "numeric value out of range", &parser->err); } return false; @@ -522,12 +521,11 @@ ucl_lex_number (struct ucl_parser *parser, * Parse quoted string with possible escapes * @param parser * @param chunk - * @param err * @return true if a string has been parsed */ static bool ucl_lex_json_string (struct ucl_parser *parser, - struct ucl_chunk *chunk, bool *need_unescape, UT_string **err) + struct ucl_chunk *chunk, bool *need_unescape) { const unsigned char *p = chunk->pos; unsigned char c; @@ -538,10 +536,10 @@ ucl_lex_json_string (struct ucl_parser *parser, if (c < 0x1F) { /* Unmasked control character */ if (c == '\n') { - ucl_set_err (chunk, UCL_ESYNTAX, "unexpected newline", err); + ucl_set_err (chunk, UCL_ESYNTAX, "unexpected newline", &parser->err); } else { - ucl_set_err (chunk, UCL_ESYNTAX, "unexpected control character", err); + ucl_set_err (chunk, UCL_ESYNTAX, "unexpected control character", &parser->err); } return false; } @@ -549,7 +547,7 @@ ucl_lex_json_string (struct ucl_parser *parser, ucl_chunk_skipc (chunk, p); c = *p; if (p >= chunk->end) { - ucl_set_err (chunk, UCL_ESYNTAX, "unfinished escape character", err); + ucl_set_err (chunk, UCL_ESYNTAX, "unfinished escape character", &parser->err); return false; } else if (ucl_test_character (c, UCL_CHARACTER_ESCAPE)) { @@ -557,13 +555,13 @@ ucl_lex_json_string (struct ucl_parser *parser, ucl_chunk_skipc (chunk, p); for (i = 0; i < 4 && p < chunk->end; i ++) { if (!isxdigit (*p)) { - ucl_set_err (chunk, UCL_ESYNTAX, "invalid utf escape", err); + ucl_set_err (chunk, UCL_ESYNTAX, "invalid utf escape", &parser->err); return false; } ucl_chunk_skipc (chunk, p); } if (p >= chunk->end) { - ucl_set_err (chunk, UCL_ESYNTAX, "unfinished escape character", err); + ucl_set_err (chunk, UCL_ESYNTAX, "unfinished escape character", &parser->err); return false; } } @@ -572,7 +570,7 @@ ucl_lex_json_string (struct ucl_parser *parser, } } else { - ucl_set_err (chunk, UCL_ESYNTAX, "invalid escape character", err); + ucl_set_err (chunk, UCL_ESYNTAX, "invalid escape character", &parser->err); return false; } *need_unescape = true; @@ -585,7 +583,7 @@ ucl_lex_json_string (struct ucl_parser *parser, ucl_chunk_skipc (chunk, p); } - ucl_set_err (chunk, UCL_ESYNTAX, "no quote at the end of json string", err); + ucl_set_err (chunk, UCL_ESYNTAX, "no quote at the end of json string", &parser->err); return false; } @@ -593,12 +591,10 @@ ucl_lex_json_string (struct ucl_parser *parser, * Parse a key in an object * @param parser * @param chunk - * @param err * @return true if a key has been parsed */ static bool -ucl_parse_key (struct ucl_parser *parser, - struct ucl_chunk *chunk, UT_string **err) +ucl_parse_key (struct ucl_parser *parser, struct ucl_chunk *chunk) { const unsigned char *p, *c = NULL, *end; const char *key; @@ -621,7 +617,7 @@ ucl_parse_key (struct ucl_parser *parser, */ if (c == NULL) { if (ucl_lex_is_comment (p[0], p[1])) { - if (!ucl_skip_comments (parser, err)) { + if (!ucl_skip_comments (parser)) { return false; } p = chunk->pos; @@ -639,7 +635,7 @@ ucl_parse_key (struct ucl_parser *parser, } else { /* Invalid identifier */ - ucl_set_err (chunk, UCL_ESYNTAX, "key must begin with a letter", err); + ucl_set_err (chunk, UCL_ESYNTAX, "key must begin with a letter", &parser->err); return false; } } @@ -654,13 +650,13 @@ ucl_parse_key (struct ucl_parser *parser, break; } else { - ucl_set_err (chunk, UCL_ESYNTAX, "invalid character in a key", err); + ucl_set_err (chunk, UCL_ESYNTAX, "invalid character in a key", &parser->err); return false; } } else { /* We need to parse json like quoted string */ - if (!ucl_lex_json_string (parser, chunk, &need_unescape, err)) { + if (!ucl_lex_json_string (parser, chunk, &need_unescape)) { return false; } end = chunk->pos - 1; @@ -671,7 +667,7 @@ ucl_parse_key (struct ucl_parser *parser, } if (p >= chunk->end) { - ucl_set_err (chunk, UCL_ESYNTAX, "unfinished key", err); + ucl_set_err (chunk, UCL_ESYNTAX, "unfinished key", &parser->err); return false; } @@ -686,7 +682,7 @@ ucl_parse_key (struct ucl_parser *parser, got_eq = true; } else { - ucl_set_err (chunk, UCL_ESYNTAX, "unexpected '=' character", err); + ucl_set_err (chunk, UCL_ESYNTAX, "unexpected '=' character", &parser->err); return false; } } @@ -696,13 +692,13 @@ ucl_parse_key (struct ucl_parser *parser, got_semicolon = true; } else { - ucl_set_err (chunk, UCL_ESYNTAX, "unexpected ':' character", err); + ucl_set_err (chunk, UCL_ESYNTAX, "unexpected ':' character", &parser->err); return false; } } else if (ucl_lex_is_comment (p[0], p[1])) { /* Check for comment */ - if (!ucl_skip_comments (parser, err)) { + if (!ucl_skip_comments (parser)) { return false; } p = chunk->pos; @@ -714,14 +710,14 @@ ucl_parse_key (struct ucl_parser *parser, } if (p >= chunk->end) { - ucl_set_err (chunk, UCL_ESYNTAX, "unfinished key", err); + ucl_set_err (chunk, UCL_ESYNTAX, "unfinished key", &parser->err); return false; } /* Create a new object */ nobj = ucl_object_new (); keylen = ucl_copy_or_store_ptr (parser, c, &nobj->trash_stack[UCL_TRASH_KEY], - &key, end - c, need_unescape, parser->flags & UCL_FLAG_KEY_LOWERCASE, err); + &key, end - c, need_unescape, parser->flags & UCL_FLAG_KEY_LOWERCASE); if (keylen == 0) { return false; } @@ -747,12 +743,11 @@ ucl_parse_key (struct ucl_parser *parser, * Parse a cl string * @param parser * @param chunk - * @param err * @return true if a key has been parsed */ static bool ucl_parse_string_value (struct ucl_parser *parser, - struct ucl_chunk *chunk, UT_string **err) + struct ucl_chunk *chunk) { const unsigned char *p; enum { @@ -798,7 +793,7 @@ ucl_parse_string_value (struct ucl_parser *parser, } if (p >= chunk->end) { - ucl_set_err (chunk, UCL_ESYNTAX, "unfinished value", err); + ucl_set_err (chunk, UCL_ESYNTAX, "unfinished value", &parser->err); return false; } @@ -811,13 +806,12 @@ ucl_parse_string_value (struct ucl_parser *parser, * @param chunk * @param term * @param term_len - * @param err * @return size of multiline string or 0 in case of error */ static int ucl_parse_multiline_string (struct ucl_parser *parser, struct ucl_chunk *chunk, const unsigned char *term, - int term_len, unsigned char const **beg, UT_string **err) + int term_len, unsigned char const **beg) { const unsigned char *p, *c; bool newline = false; @@ -857,11 +851,10 @@ ucl_parse_multiline_string (struct ucl_parser *parser, * Handle value data * @param parser * @param chunk - * @param err * @return */ static bool -ucl_parse_value (struct ucl_parser *parser, struct ucl_chunk *chunk, UT_string **err) +ucl_parse_value (struct ucl_parser *parser, struct ucl_chunk *chunk) { const unsigned char *p, *c; struct ucl_stack *st; @@ -891,13 +884,13 @@ ucl_parse_value (struct ucl_parser *parser, struct ucl_chunk *chunk, UT_string * switch (*p) { case '"': ucl_chunk_skipc (chunk, p); - if (!ucl_lex_json_string (parser, chunk, &need_unescape, err)) { + if (!ucl_lex_json_string (parser, chunk, &need_unescape)) { return false; } str_len = chunk->pos - c - 2; obj->type = UCL_STRING; if ((str_len = ucl_copy_or_store_ptr (parser, c + 1, &obj->trash_stack[UCL_TRASH_VALUE], - &obj->value.sv, str_len, need_unescape, false, err)) == 0) { + &obj->value.sv, str_len, need_unescape, false)) == 0) { return false; } obj->len = str_len; @@ -949,13 +942,13 @@ ucl_parse_value (struct ucl_parser *parser, struct ucl_chunk *chunk, UT_string * chunk->column = 0; chunk->line ++; if ((str_len = ucl_parse_multiline_string (parser, chunk, c, - p - c, &c, err)) == 0) { - ucl_set_err (chunk, UCL_ESYNTAX, "unterminated multiline value", err); + p - c, &c)) == 0) { + ucl_set_err (chunk, UCL_ESYNTAX, "unterminated multiline value", &parser->err); return false; } obj->type = UCL_STRING; if ((str_len = ucl_copy_or_store_ptr (parser, c, &obj->trash_stack[UCL_TRASH_VALUE], - &obj->value.sv, str_len - 1, false, false, err)) == 0) { + &obj->value.sv, str_len - 1, false, false)) == 0) { return false; } obj->len = str_len; @@ -972,7 +965,7 @@ ucl_parse_value (struct ucl_parser *parser, struct ucl_chunk *chunk, UT_string * while (p < chunk->end && ucl_test_character (*p, UCL_CHARACTER_WHITESPACE_UNSAFE)) { ucl_chunk_skipc (chunk, p); } - if (!ucl_skip_comments (parser, err)) { + if (!ucl_skip_comments (parser)) { return false; } p = chunk->pos; @@ -980,11 +973,11 @@ ucl_parse_value (struct ucl_parser *parser, struct ucl_chunk *chunk, UT_string * } /* Parse atom */ if (ucl_test_character (*p, UCL_CHARACTER_VALUE_DIGIT_START)) { - if (!ucl_lex_number (parser, chunk, obj, err)) { + if (!ucl_lex_number (parser, chunk, obj)) { if (parser->state == UCL_STATE_ERROR) { return false; } - if (!ucl_parse_string_value (parser, chunk, err)) { + if (!ucl_parse_string_value (parser, chunk)) { return false; } if (!ucl_maybe_parse_boolean (obj, c, chunk->pos - c)) { @@ -996,12 +989,12 @@ ucl_parse_value (struct ucl_parser *parser, struct ucl_chunk *chunk, UT_string * } str_len = chunk->pos - c - stripped_spaces; if (str_len <= 0) { - ucl_set_err (chunk, 0, "string value must not be empty", err); + ucl_set_err (chunk, 0, "string value must not be empty", &parser->err); return false; } obj->type = UCL_STRING; if ((str_len = ucl_copy_or_store_ptr (parser, c, &obj->trash_stack[UCL_TRASH_VALUE], - &obj->value.sv, str_len, false, false, err)) == 0) { + &obj->value.sv, str_len, false, false)) == 0) { return false; } obj->len = str_len; @@ -1015,7 +1008,7 @@ ucl_parse_value (struct ucl_parser *parser, struct ucl_chunk *chunk, UT_string * } } else { - if (!ucl_parse_string_value (parser, chunk, err)) { + if (!ucl_parse_string_value (parser, chunk)) { return false; } if (!ucl_maybe_parse_boolean (obj, c, chunk->pos - c)) { @@ -1028,12 +1021,12 @@ ucl_parse_value (struct ucl_parser *parser, struct ucl_chunk *chunk, UT_string * } str_len = chunk->pos - c - stripped_spaces; if (str_len <= 0) { - ucl_set_err (chunk, 0, "string value must not be empty", err); + ucl_set_err (chunk, 0, "string value must not be empty", &parser->err); return false; } obj->type = UCL_STRING; if ((str_len = ucl_copy_or_store_ptr (parser, c, &obj->trash_stack[UCL_TRASH_VALUE], - &obj->value.sv, str_len, false, false, err)) == 0) { + &obj->value.sv, str_len, false, false)) == 0) { return false; } obj->len = str_len; @@ -1053,11 +1046,10 @@ ucl_parse_value (struct ucl_parser *parser, struct ucl_chunk *chunk, UT_string * * Handle after value data * @param parser * @param chunk - * @param err * @return */ static bool -ucl_parse_after_value (struct ucl_parser *parser, struct ucl_chunk *chunk, UT_string **err) +ucl_parse_after_value (struct ucl_parser *parser, struct ucl_chunk *chunk) { const unsigned char *p; bool got_sep = false; @@ -1072,7 +1064,7 @@ ucl_parse_after_value (struct ucl_parser *parser, struct ucl_chunk *chunk, UT_st } else if (ucl_lex_is_comment (p[0], p[1])) { /* Skip comment */ - if (!ucl_skip_comments (parser, err)) { + if (!ucl_skip_comments (parser)) { return false; } /* Treat comment as a separator */ @@ -1082,7 +1074,7 @@ ucl_parse_after_value (struct ucl_parser *parser, struct ucl_chunk *chunk, UT_st else if (ucl_test_character (*p, UCL_CHARACTER_VALUE_END)) { if (*p == '}' || *p == ']') { if (parser->stack == NULL) { - ucl_set_err (chunk, UCL_ESYNTAX, "unexpected } detected", err); + ucl_set_err (chunk, UCL_ESYNTAX, "unexpected } detected", &parser->err); return false; } if ((*p == '}' && parser->stack->obj->type == UCL_OBJECT) || @@ -1094,7 +1086,7 @@ ucl_parse_after_value (struct ucl_parser *parser, struct ucl_chunk *chunk, UT_st UCL_FREE (sizeof (struct ucl_stack), st); } else { - ucl_set_err (chunk, UCL_ESYNTAX, "unexpected terminating symbol detected", err); + ucl_set_err (chunk, UCL_ESYNTAX, "unexpected terminating symbol detected", &parser->err); return false; } @@ -1116,7 +1108,7 @@ ucl_parse_after_value (struct ucl_parser *parser, struct ucl_chunk *chunk, UT_st else { /* Anything else */ if (!got_sep) { - ucl_set_err (chunk, UCL_ESYNTAX, "delimiter is missing", err); + ucl_set_err (chunk, UCL_ESYNTAX, "delimiter is missing", &parser->err); return false; } return true; @@ -1130,13 +1122,12 @@ ucl_parse_after_value (struct ucl_parser *parser, struct ucl_chunk *chunk, UT_st * Handle macro data * @param parser * @param chunk - * @param err * @return */ static bool ucl_parse_macro_value (struct ucl_parser *parser, struct ucl_chunk *chunk, struct ucl_macro *macro, - unsigned char const **macro_start, size_t *macro_len, UT_string **err) + unsigned char const **macro_start, size_t *macro_len) { const unsigned char *p, *c; bool need_unescape = false; @@ -1148,7 +1139,7 @@ ucl_parse_macro_value (struct ucl_parser *parser, /* We have macro value encoded in quotes */ c = p; ucl_chunk_skipc (chunk, p); - if (!ucl_lex_json_string (parser, chunk, &need_unescape, err)) { + if (!ucl_lex_json_string (parser, chunk, &need_unescape)) { return false; } @@ -1209,11 +1200,10 @@ ucl_parse_macro_value (struct ucl_parser *parser, * @param parser parser structure * @param data the pointer to the beginning of a chunk * @param len the length of a chunk - * @param err if *err is NULL it is set to parser error * @return true if chunk has been parsed and false in case of error */ static bool -ucl_state_machine (struct ucl_parser *parser, UT_string **err) +ucl_state_machine (struct ucl_parser *parser) { ucl_object_t *obj; struct ucl_chunk *chunk = parser->chunks; @@ -1231,7 +1221,7 @@ ucl_state_machine (struct ucl_parser *parser, UT_string **err) * if we got [ or { correspondingly or can just treat new data as * a key of newly created object */ - if (!ucl_skip_comments (parser, err)) { + if (!ucl_skip_comments (parser)) { parser->prev_state = parser->state; parser->state = UCL_STATE_ERROR; return false; @@ -1268,7 +1258,7 @@ ucl_state_machine (struct ucl_parser *parser, UT_string **err) parser->state = UCL_STATE_AFTER_VALUE; continue; } - if (!ucl_parse_key (parser, chunk, err)) { + if (!ucl_parse_key (parser, chunk)) { parser->prev_state = parser->state; parser->state = UCL_STATE_ERROR; return false; @@ -1283,7 +1273,7 @@ ucl_state_machine (struct ucl_parser *parser, UT_string **err) break; case UCL_STATE_VALUE: /* We need to check what we do have */ - if (!ucl_parse_value (parser, chunk, err)) { + if (!ucl_parse_value (parser, chunk)) { parser->prev_state = parser->state; parser->state = UCL_STATE_ERROR; return false; @@ -1292,7 +1282,7 @@ ucl_state_machine (struct ucl_parser *parser, UT_string **err) p = chunk->pos; break; case UCL_STATE_AFTER_VALUE: - if (!ucl_parse_after_value (parser, chunk, err)) { + if (!ucl_parse_after_value (parser, chunk)) { parser->prev_state = parser->state; parser->state = UCL_STATE_ERROR; return false; @@ -1320,7 +1310,7 @@ ucl_state_machine (struct ucl_parser *parser, UT_string **err) /* We got macro name */ HASH_FIND (hh, parser->macroes, c, (p - c), macro); if (macro == NULL) { - ucl_set_err (chunk, UCL_EMACRO, "unknown macro", err); + ucl_set_err (chunk, UCL_EMACRO, "unknown macro", &parser->err); parser->state = UCL_STATE_ERROR; return false; } @@ -1329,7 +1319,7 @@ ucl_state_machine (struct ucl_parser *parser, UT_string **err) if (!ucl_test_character (*p, UCL_CHARACTER_WHITESPACE_UNSAFE)) { if (ucl_lex_is_comment (p[0], p[1])) { /* Skip comment */ - if (!ucl_skip_comments (parser, err)) { + if (!ucl_skip_comments (parser)) { return false; } p = chunk->pos; @@ -1343,20 +1333,20 @@ ucl_state_machine (struct ucl_parser *parser, UT_string **err) break; case UCL_STATE_MACRO: if (!ucl_parse_macro_value (parser, chunk, macro, - ¯o_start, ¯o_len, err)) { + ¯o_start, ¯o_len)) { parser->prev_state = parser->state; parser->state = UCL_STATE_ERROR; return false; } parser->state = parser->prev_state; - if (!macro->handler (macro_start, macro_len, macro->ud, err)) { + if (!macro->handler (macro_start, macro_len, macro->ud)) { return false; } p = chunk->pos; break; default: /* TODO: add all states */ - ucl_set_err (chunk, UCL_EMACRO, "internal error: parser is in an unknown state", err); + ucl_set_err (chunk, UCL_EMACRO, "internal error: parser is in an unknown state", &parser->err); parser->state = UCL_STATE_ERROR; return false; } @@ -1398,7 +1388,7 @@ ucl_parser_register_macro (struct ucl_parser *parser, const char *macro, bool ucl_parser_add_chunk (struct ucl_parser *parser, const unsigned char *data, - size_t len, UT_string **err) + size_t len) { struct ucl_chunk *chunk; @@ -1413,14 +1403,14 @@ ucl_parser_add_chunk (struct ucl_parser *parser, const unsigned char *data, LL_PREPEND (parser->chunks, chunk); parser->recursion ++; if (parser->recursion > UCL_MAX_RECURSION) { - ucl_create_err (err, "maximum include nesting limit is reached: %d", + ucl_create_err (&parser->err, "maximum include nesting limit is reached: %d", parser->recursion); return false; } - return ucl_state_machine (parser, err); + return ucl_state_machine (parser); } - ucl_create_err (err, "a parser is in an invalid state"); + ucl_create_err (&parser->err, "a parser is in an invalid state"); return false; } diff --git a/src/ucl_util.c b/src/ucl_util.c index 8c3da60..a6b4ffe 100644 --- a/src/ucl_util.c +++ b/src/ucl_util.c @@ -220,7 +220,7 @@ ucl_copy_value_trash (ucl_object_t *obj) } ucl_object_t* -ucl_parser_get_object (struct ucl_parser *parser, UT_string **err) +ucl_parser_get_object (struct ucl_parser *parser) { if (parser->state != UCL_STATE_INIT && parser->state != UCL_STATE_ERROR) { return ucl_object_ref (parser->top_obj); @@ -256,15 +256,28 @@ ucl_parser_free (struct ucl_parser *parser) UCL_FREE (sizeof (struct ucl_pubkey), key); } + if (parser->err != NULL) { + utstring_free(parser->err); + } + UCL_FREE (sizeof (struct ucl_parser), parser); } +const char * +ucl_parser_get_error(struct ucl_parser *parser) +{ + if (parser->err == NULL) + return NULL; + + return utstring_body(parser->err); +} + bool -ucl_pubkey_add (struct ucl_parser *parser, const unsigned char *key, size_t len, UT_string **err) +ucl_pubkey_add (struct ucl_parser *parser, const unsigned char *key, size_t len) { struct ucl_pubkey *nkey; #ifndef HAVE_OPENSSL - ucl_create_err (err, "cannot check signatures without openssl"); + ucl_create_err (&parser->err, "cannot check signatures without openssl"); return false; #else # if (OPENSSL_VERSION_NUMBER < 0x10000000L) @@ -279,7 +292,7 @@ ucl_pubkey_add (struct ucl_parser *parser, const unsigned char *key, size_t len, BIO_free (mem); if (nkey->key == NULL) { UCL_FREE (sizeof (struct ucl_pubkey), nkey); - ucl_create_err (err, "%s", + ucl_create_err (&parser->err, "%s", ERR_error_string (ERR_get_error (), NULL)); return false; } @@ -499,7 +512,7 @@ ucl_sig_check (const unsigned char *data, size_t datalen, */ static bool ucl_include_url (const unsigned char *data, size_t len, - struct ucl_parser *parser, bool check_signature, UT_string **err) + struct ucl_parser *parser, bool check_signature) { bool res; @@ -510,7 +523,7 @@ ucl_include_url (const unsigned char *data, size_t len, snprintf (urlbuf, sizeof (urlbuf), "%.*s", (int)len, data); - if (!ucl_fetch_url (urlbuf, &buf, &buflen, err)) { + if (!ucl_fetch_url (urlbuf, &buf, &buflen, &parser->err)) { return false; } @@ -522,7 +535,7 @@ ucl_include_url (const unsigned char *data, size_t len, return false; } if (!ucl_sig_check (buf, buflen, sigbuf, siglen, parser)) { - ucl_create_err (err, "cannot verify url %s: %s", + ucl_create_err (&parser->err, "cannot verify url %s: %s", urlbuf, ERR_error_string (ERR_get_error (), NULL)); munmap (sigbuf, siglen); @@ -532,7 +545,7 @@ ucl_include_url (const unsigned char *data, size_t len, #endif } - res = ucl_parser_add_chunk (parser, buf, buflen, err); + res = ucl_parser_add_chunk (parser, buf, buflen); if (res == true) { /* Remove chunk from the stack */ chunk = parser->chunks; @@ -556,7 +569,7 @@ ucl_include_url (const unsigned char *data, size_t len, */ static bool ucl_include_file (const unsigned char *data, size_t len, - struct ucl_parser *parser, bool check_signature, UT_string **err) + struct ucl_parser *parser, bool check_signature) { bool res; struct ucl_chunk *chunk; @@ -566,13 +579,13 @@ ucl_include_file (const unsigned char *data, size_t len, snprintf (filebuf, sizeof (filebuf), "%.*s", (int)len, data); if (realpath (filebuf, realbuf) == NULL) { - ucl_create_err (err, "cannot open file %s: %s", + ucl_create_err (&parser->err, "cannot open file %s: %s", filebuf, strerror (errno)); return false; } - if (!ucl_fetch_file (realbuf, &buf, &buflen, err)) { + if (!ucl_fetch_file (realbuf, &buf, &buflen, &parser->err)) { return false; } @@ -594,7 +607,7 @@ ucl_include_file (const unsigned char *data, size_t len, #endif } - res = ucl_parser_add_chunk (parser, buf, buflen, err); + res = ucl_parser_add_chunk (parser, buf, buflen); if (res == true) { /* Remove chunk from the stack */ chunk = parser->chunks; @@ -617,16 +630,16 @@ ucl_include_file (const unsigned char *data, size_t len, * @return */ bool -ucl_include_handler (const unsigned char *data, size_t len, void* ud, UT_string **err) +ucl_include_handler (const unsigned char *data, size_t len, void* ud) { struct ucl_parser *parser = ud; if (*data == '/' || *data == '.') { /* Try to load a file */ - return ucl_include_file (data, len, parser, false, err); + return ucl_include_file (data, len, parser, false); } - return ucl_include_url (data, len, parser, false, err); + return ucl_include_url (data, len, parser, false); } /** @@ -638,31 +651,30 @@ ucl_include_handler (const unsigned char *data, size_t len, void* ud, UT_string * @return */ bool -ucl_includes_handler (const unsigned char *data, size_t len, void* ud, UT_string **err) +ucl_includes_handler (const unsigned char *data, size_t len, void* ud) { struct ucl_parser *parser = ud; if (*data == '/' || *data == '.') { /* Try to load a file */ - return ucl_include_file (data, len, parser, true, err); + return ucl_include_file (data, len, parser, true); } - return ucl_include_url (data, len, parser, true, err); + return ucl_include_url (data, len, parser, true); } bool -ucl_parser_add_file (struct ucl_parser *parser, const char *filename, - UT_string **err) +ucl_parser_add_file (struct ucl_parser *parser, const char *filename) { unsigned char *buf; size_t len; bool ret; - if (!ucl_fetch_file (filename, &buf, &len, err)) { + if (!ucl_fetch_file (filename, &buf, &len, &parser->err)) { return false; } - ret = ucl_parser_add_chunk (parser, buf, len, err); + ret = ucl_parser_add_chunk (parser, buf, len); munmap (buf, len); -- 1.8.4