summaryrefslogtreecommitdiffstats
path: root/contrib/libucl/src/ucl_parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/libucl/src/ucl_parser.c')
-rw-r--r--contrib/libucl/src/ucl_parser.c174
1 files changed, 123 insertions, 51 deletions
diff --git a/contrib/libucl/src/ucl_parser.c b/contrib/libucl/src/ucl_parser.c
index 12ebad2..b4fe5af 100644
--- a/contrib/libucl/src/ucl_parser.c
+++ b/contrib/libucl/src/ucl_parser.c
@@ -55,34 +55,6 @@ struct ucl_parser_saved_state {
(chunk)->remain --; \
} while (0)
-/**
- * Save parser state
- * @param chunk
- * @param s
- */
-static inline void
-ucl_chunk_save_state (struct ucl_chunk *chunk, struct ucl_parser_saved_state *s)
-{
- s->column = chunk->column;
- s->pos = chunk->pos;
- s->line = chunk->line;
- s->remain = chunk->remain;
-}
-
-/**
- * Restore parser state
- * @param chunk
- * @param s
- */
-static inline void
-ucl_chunk_restore_state (struct ucl_chunk *chunk, struct ucl_parser_saved_state *s)
-{
- chunk->column = s->column;
- chunk->pos = s->pos;
- chunk->line = s->line;
- chunk->remain = s->remain;
-}
-
static inline void
ucl_set_err (struct ucl_chunk *chunk, int code, const char *str, UT_string **err)
{
@@ -264,6 +236,9 @@ ucl_check_variable_safe (struct ucl_parser *parser, const char *ptr, size_t rema
size_t *out_len, bool strict, bool *found)
{
struct ucl_variable *var;
+ unsigned char *dst;
+ size_t dstlen;
+ bool need_free = false;
LL_FOREACH (parser->variables, var) {
if (strict) {
@@ -286,6 +261,19 @@ ucl_check_variable_safe (struct ucl_parser *parser, const char *ptr, size_t rema
}
}
+ /* XXX: can only handle ${VAR} */
+ if (!(*found) && parser->var_handler != NULL && strict) {
+ /* Call generic handler */
+ if (parser->var_handler (ptr, remain, &dst, &dstlen, &need_free,
+ parser->var_data)) {
+ *found = true;
+ if (need_free) {
+ free (dst);
+ }
+ return (ptr + remain);
+ }
+ }
+
return ptr;
}
@@ -299,7 +287,8 @@ ucl_check_variable_safe (struct ucl_parser *parser, const char *ptr, size_t rema
* @return
*/
static const char *
-ucl_check_variable (struct ucl_parser *parser, const char *ptr, size_t remain, size_t *out_len, bool *vars_found)
+ucl_check_variable (struct ucl_parser *parser, const char *ptr,
+ size_t remain, size_t *out_len, bool *vars_found)
{
const char *p, *end, *ret = ptr;
bool found = false;
@@ -310,7 +299,8 @@ ucl_check_variable (struct ucl_parser *parser, const char *ptr, size_t remain, s
end = ptr + remain;
while (p < end) {
if (*p == '}') {
- ret = ucl_check_variable_safe (parser, ptr + 1, p - ptr - 1, out_len, true, &found);
+ ret = ucl_check_variable_safe (parser, ptr + 1, p - ptr - 1,
+ out_len, true, &found);
if (found) {
/* {} must be excluded actually */
ret ++;
@@ -356,10 +346,13 @@ static const char *
ucl_expand_single_variable (struct ucl_parser *parser, const char *ptr,
size_t remain, unsigned char **dest)
{
- unsigned char *d = *dest;
+ unsigned char *d = *dest, *dst;
const char *p = ptr + 1, *ret;
struct ucl_variable *var;
+ size_t dstlen;
+ bool need_free = false;
bool found = false;
+ bool strict = false;
ret = ptr + 1;
remain --;
@@ -371,6 +364,7 @@ ucl_expand_single_variable (struct ucl_parser *parser, const char *ptr,
}
else if (*p == '{') {
p ++;
+ strict = true;
ret += 2;
remain -= 2;
}
@@ -387,9 +381,22 @@ ucl_expand_single_variable (struct ucl_parser *parser, const char *ptr,
}
}
if (!found) {
- memcpy (d, ptr, 2);
- d += 2;
- ret --;
+ if (strict && parser->var_handler != NULL) {
+ if (parser->var_handler (ptr, remain, &dst, &dstlen, &need_free,
+ parser->var_data)) {
+ memcpy (d, dst, dstlen);
+ ret += dstlen;
+ d += remain;
+ found = true;
+ }
+ }
+
+ /* Leave variable as is */
+ if (!found) {
+ memcpy (d, ptr, 2);
+ d += 2;
+ ret --;
+ }
}
*dest = d;
@@ -544,6 +551,10 @@ ucl_add_parser_stack (ucl_object_t *obj, struct ucl_parser *parser, bool is_arra
}
st = UCL_ALLOC (sizeof (struct ucl_stack));
+ if (st == NULL) {
+ ucl_set_err (parser->chunks, 0, "cannot allocate memory for an object", &parser->err);
+ return NULL;
+ }
st->obj = obj;
st->level = level;
LL_PREPEND (parser->stack, st);
@@ -554,12 +565,13 @@ ucl_add_parser_stack (ucl_object_t *obj, struct ucl_parser *parser, bool is_arra
int
ucl_maybe_parse_number (ucl_object_t *obj,
- const char *start, const char *end, const char **pos, bool allow_double, bool number_bytes)
+ const char *start, const char *end, const char **pos,
+ bool allow_double, bool number_bytes, bool allow_time)
{
const char *p = start, *c = start;
char *endptr;
bool got_dot = false, got_exp = false, need_double = false,
- is_date = false, valid_start = false, is_hex = false,
+ is_time = false, valid_start = false, is_hex = false,
is_neg = false;
double dv = 0;
int64_t lv = 0;
@@ -657,7 +669,8 @@ ucl_maybe_parse_number (ucl_object_t *obj,
}
/* Now check endptr */
- if (endptr == NULL || ucl_lex_is_atom_end (*endptr) || *endptr == '\0') {
+ if (endptr == NULL || ucl_lex_is_atom_end (*endptr) || *endptr == '\0' ||
+ ucl_test_character (*endptr, UCL_CHARACTER_WHITESPACE_UNSAFE)) {
p = endptr;
goto set_obj;
}
@@ -678,7 +691,7 @@ ucl_maybe_parse_number (ucl_object_t *obj,
need_double = true;
dv = lv;
}
- is_date = true;
+ is_time = true;
if (p[0] == 'm' || p[0] == 'M') {
dv /= 1000.;
}
@@ -708,7 +721,7 @@ ucl_maybe_parse_number (ucl_object_t *obj,
p ++;
goto set_obj;
}
- else if (end - p >= 3) {
+ else if (allow_time && end - p >= 3) {
if (tolower (p[0]) == 'm' &&
tolower (p[1]) == 'i' &&
tolower (p[2]) == 'n') {
@@ -717,7 +730,7 @@ ucl_maybe_parse_number (ucl_object_t *obj,
need_double = true;
dv = lv;
}
- is_date = true;
+ is_time = true;
dv *= 60.;
p += 3;
goto set_obj;
@@ -737,13 +750,14 @@ ucl_maybe_parse_number (ucl_object_t *obj,
break;
case 'S':
case 's':
- if (p == end - 1 || ucl_lex_is_atom_end (p[1])) {
+ if (allow_time &&
+ (p == end - 1 || ucl_lex_is_atom_end (p[1]))) {
if (!need_double) {
need_double = true;
dv = lv;
}
p ++;
- is_date = true;
+ is_time = true;
goto set_obj;
}
break;
@@ -755,12 +769,13 @@ ucl_maybe_parse_number (ucl_object_t *obj,
case 'W':
case 'Y':
case 'y':
- if (p == end - 1 || ucl_lex_is_atom_end (p[1])) {
+ if (allow_time &&
+ (p == end - 1 || ucl_lex_is_atom_end (p[1]))) {
if (!need_double) {
need_double = true;
dv = lv;
}
- is_date = true;
+ is_time = true;
dv *= ucl_lex_time_multiplier (*p);
p ++;
goto set_obj;
@@ -773,8 +788,8 @@ ucl_maybe_parse_number (ucl_object_t *obj,
return EINVAL;
set_obj:
- if (allow_double && (need_double || is_date)) {
- if (!is_date) {
+ if (allow_double && (need_double || is_time)) {
+ if (!is_time) {
obj->type = UCL_FLOAT;
}
else {
@@ -803,7 +818,8 @@ ucl_lex_number (struct ucl_parser *parser,
const unsigned char *pos;
int ret;
- ret = ucl_maybe_parse_number (obj, chunk->pos, chunk->end, (const char **)&pos, true, false);
+ ret = ucl_maybe_parse_number (obj, chunk->pos, chunk->end, (const char **)&pos,
+ true, false, ((parser->flags & UCL_PARSER_NO_TIME) == 0));
if (ret == 0) {
chunk->remain -= pos - chunk->pos;
@@ -1077,19 +1093,19 @@ ucl_parse_key (struct ucl_parser *parser, struct ucl_chunk *chunk, bool *next_ke
keylen = ucl_copy_or_store_ptr (parser, c, &nobj->trash_stack[UCL_TRASH_KEY],
&key, end - c, need_unescape, parser->flags & UCL_PARSER_KEY_LOWERCASE, false);
if (keylen == -1) {
- ucl_object_free(nobj);
+ ucl_object_unref (nobj);
return false;
}
else if (keylen == 0) {
ucl_set_err (chunk, UCL_ESYNTAX, "empty keys are not allowed", &parser->err);
- ucl_object_free(nobj);
+ ucl_object_unref (nobj);
return false;
}
container = parser->stack->obj->value.ov;
nobj->key = key;
nobj->keylen = keylen;
- tobj = ucl_hash_search_obj (container, nobj);
+ tobj = __DECONST (ucl_object_t *, ucl_hash_search_obj (container, nobj));
if (tobj == NULL) {
container = ucl_hash_insert_object (container, nobj);
nobj->prev = nobj;
@@ -1308,6 +1324,9 @@ ucl_parse_value (struct ucl_parser *parser, struct ucl_chunk *chunk)
obj = ucl_get_value_object (parser);
/* We have a new object */
obj = ucl_add_parser_stack (obj, parser, false, parser->stack->level);
+ if (obj == NULL) {
+ return false;
+ }
ucl_chunk_skipc (chunk, p);
return true;
@@ -1316,6 +1335,9 @@ ucl_parse_value (struct ucl_parser *parser, struct ucl_chunk *chunk)
obj = ucl_get_value_object (parser);
/* We have a new array */
obj = ucl_add_parser_stack (obj, parser, true, parser->stack->level);
+ if (obj == NULL) {
+ return false;
+ }
ucl_chunk_skipc (chunk, p);
return true;
@@ -1608,6 +1630,9 @@ ucl_state_machine (struct ucl_parser *parser)
else {
obj = ucl_add_parser_stack (NULL, parser, false, 0);
}
+ if (obj == NULL) {
+ return false;
+ }
parser->top_obj = obj;
parser->cur_obj = obj;
parser->state = UCL_STATE_INIT;
@@ -1673,7 +1698,11 @@ ucl_state_machine (struct ucl_parser *parser)
else if (parser->state != UCL_STATE_MACRO_NAME) {
if (next_key && parser->stack->obj->type == UCL_OBJECT) {
/* Parse more keys and nest objects accordingly */
- obj = ucl_add_parser_stack (parser->cur_obj, parser, false, parser->stack->level + 1);
+ obj = ucl_add_parser_stack (parser->cur_obj, parser, false,
+ parser->stack->level + 1);
+ if (obj == NULL) {
+ return false;
+ }
}
else {
parser->state = UCL_STATE_VALUE;
@@ -1787,6 +1816,9 @@ ucl_parser_new (int flags)
struct ucl_parser *new;
new = UCL_ALLOC (sizeof (struct ucl_parser));
+ if (new == NULL) {
+ return NULL;
+ }
memset (new, 0, sizeof (struct ucl_parser));
ucl_parser_register_macro (new, "include", ucl_include_handler, new);
@@ -1808,7 +1840,13 @@ ucl_parser_register_macro (struct ucl_parser *parser, const char *macro,
{
struct ucl_macro *new;
+ if (macro == NULL || handler == NULL) {
+ return;
+ }
new = UCL_ALLOC (sizeof (struct ucl_macro));
+ if (new == NULL) {
+ return;
+ }
memset (new, 0, sizeof (struct ucl_macro));
new->handler = handler;
new->name = strdup (macro);
@@ -1851,6 +1889,9 @@ ucl_parser_register_variable (struct ucl_parser *parser, const char *var,
else {
if (new == NULL) {
new = UCL_ALLOC (sizeof (struct ucl_variable));
+ if (new == NULL) {
+ return;
+ }
memset (new, 0, sizeof (struct ucl_variable));
new->var = strdup (var);
new->var_len = strlen (var);
@@ -1867,14 +1908,30 @@ ucl_parser_register_variable (struct ucl_parser *parser, const char *var,
}
}
+void
+ucl_parser_set_variables_handler (struct ucl_parser *parser,
+ ucl_variable_handler handler, void *ud)
+{
+ parser->var_handler = handler;
+ parser->var_data = ud;
+}
+
bool
ucl_parser_add_chunk (struct ucl_parser *parser, const unsigned char *data,
size_t len)
{
struct ucl_chunk *chunk;
+ if (data == NULL || len == 0) {
+ ucl_create_err (&parser->err, "invalid chunk added");
+ return false;
+ }
if (parser->state != UCL_STATE_ERROR) {
chunk = UCL_ALLOC (sizeof (struct ucl_chunk));
+ if (chunk == NULL) {
+ ucl_create_err (&parser->err, "cannot allocate chunk structure");
+ return false;
+ }
chunk->begin = data;
chunk->remain = len;
chunk->pos = chunk->begin;
@@ -1895,3 +1952,18 @@ ucl_parser_add_chunk (struct ucl_parser *parser, const unsigned char *data,
return false;
}
+
+bool
+ucl_parser_add_string (struct ucl_parser *parser, const char *data,
+ size_t len)
+{
+ if (data == NULL) {
+ ucl_create_err (&parser->err, "invalid string added");
+ return false;
+ }
+ if (len == 0) {
+ len = strlen (data);
+ }
+
+ return ucl_parser_add_chunk (parser, (const unsigned char *)data, len);
+}
OpenPOWER on IntegriCloud