xpath CHANGE refactor lyxp_expr_parse() to return LY_ERR
To correctly inherit LY_ERR value and detect errors, it is necessary to
refactor lyxp_expr_parse() to return LY_ERR value and return the
processed expression via an output parameter.
diff --git a/src/context.c b/src/context.c
index 876240c..08ae49f 100644
--- a/src/context.c
+++ b/src/context.c
@@ -546,8 +546,8 @@
}
/* parse */
- exp = lyxp_expr_parse(ctx, data_path, strlen(data_path), 0);
- LY_CHECK_GOTO(!exp, cleanup);
+ ret = lyxp_expr_parse(ctx, data_path, strlen(data_path), 0, &exp);
+ LY_CHECK_GOTO(ret, cleanup);
/* compile */
oper = output ? LY_PATH_OPER_OUTPUT : LY_PATH_OPER_INPUT;
diff --git a/src/path.c b/src/path.c
index bbd9ac5..03d735a 100644
--- a/src/path.c
+++ b/src/path.c
@@ -228,7 +228,8 @@
ly_path_parse(const struct ly_ctx *ctx, const struct lysc_node *ctx_node, const char *str_path, size_t path_len,
uint8_t begin, uint8_t lref, uint8_t prefix, uint8_t pred, struct lyxp_expr **expr)
{
- struct lyxp_expr *exp;
+ LY_ERR ret = LY_SUCCESS;
+ struct lyxp_expr *exp = NULL;
uint16_t tok_idx, cur_len;
const char *cur_node, *prev_prefix = NULL, *ptr;
@@ -239,8 +240,7 @@
assert((pred == LY_PATH_PRED_KEYS) || (pred == LY_PATH_PRED_SIMPLE) || (pred == LY_PATH_PRED_LEAFREF));
/* parse as a generic XPath expression */
- exp = lyxp_expr_parse(ctx, str_path, path_len, 1);
- LY_CHECK_GOTO(!exp, error);
+ LY_CHECK_GOTO(ret = lyxp_expr_parse(ctx, str_path, path_len, 1, &exp), error);
tok_idx = 0;
if (begin == LY_PATH_BEGIN_EITHER) {
@@ -249,17 +249,17 @@
/* '..' */
while ((lref == LY_PATH_LREF_TRUE) && !lyxp_next_token(NULL, exp, &tok_idx, LYXP_TOKEN_DDOT)) {
/* '/' */
- LY_CHECK_GOTO(lyxp_next_token(ctx, exp, &tok_idx, LYXP_TOKEN_OPER_PATH), error);
+ LY_CHECK_ERR_GOTO(lyxp_next_token(ctx, exp, &tok_idx, LYXP_TOKEN_OPER_PATH), ret = LY_EVALID, error);
}
}
} else {
/* '/' */
- LY_CHECK_GOTO(lyxp_next_token(ctx, exp, &tok_idx, LYXP_TOKEN_OPER_PATH), error);
+ LY_CHECK_ERR_GOTO(lyxp_next_token(ctx, exp, &tok_idx, LYXP_TOKEN_OPER_PATH), ret = LY_EVALID, error);
}
do {
/* NameTest */
- LY_CHECK_GOTO(lyxp_check_token(ctx, exp, tok_idx, LYXP_TOKEN_NAMETEST), error);
+ LY_CHECK_ERR_GOTO(lyxp_check_token(ctx, exp, tok_idx, LYXP_TOKEN_NAMETEST), ret = LY_EVALID, error);
/* check prefix based on the options */
cur_node = exp->expr + exp->tok_pos[tok_idx];
@@ -267,6 +267,7 @@
if (prefix == LY_PATH_PREFIX_MANDATORY) {
if (!strnstr(cur_node, ":", cur_len)) {
LOGVAL_P(ctx, ctx_node, LYVE_XPATH, "Prefix missing for \"%.*s\" in path.", cur_len, cur_node);
+ ret = LY_EVALID;
goto error;
}
} else if (prefix == LY_PATH_PREFIX_STRICT_INHERIT) {
@@ -274,6 +275,7 @@
/* the first node must have a prefix */
if (!strnstr(cur_node, ":", cur_len)) {
LOGVAL_P(ctx, ctx_node, LYVE_XPATH, "Prefix missing for \"%.*s\" in path.", cur_len, cur_node);
+ ret = LY_EVALID;
goto error;
}
@@ -285,6 +287,7 @@
if (ptr) {
if (!strncmp(prev_prefix, cur_node, ptr - cur_node) && (prev_prefix[ptr - cur_node] == ':')) {
LOGVAL_P(ctx, ctx_node, LYVE_XPATH, "Duplicate prefix for \"%.*s\" in path.", cur_len, cur_node);
+ ret = LY_EVALID;
goto error;
}
@@ -297,7 +300,7 @@
++tok_idx;
/* Predicate* */
- LY_CHECK_GOTO(ly_path_check_predicate(ctx, ctx_node, exp, &tok_idx, prefix, pred), error);
+ LY_CHECK_GOTO(ret = ly_path_check_predicate(ctx, ctx_node, exp, &tok_idx, prefix, pred), error);
/* '/' */
} while (!lyxp_next_token(NULL, exp, &tok_idx, LYXP_TOKEN_OPER_PATH));
@@ -306,6 +309,7 @@
if (exp->used > tok_idx) {
LOGVAL_P(ctx, ctx_node, LYVE_XPATH, "Unparsed characters \"%s\" left at the end of path.",
exp->expr + exp->tok_pos[tok_idx]);
+ ret = LY_EVALID;
goto error;
}
@@ -314,30 +318,31 @@
error:
lyxp_expr_free(ctx, exp);
- return LY_EVALID;
+ return ret;
}
LY_ERR
ly_path_parse_predicate(const struct ly_ctx *ctx, const struct lysc_node *cur_node, const char *str_path,
size_t path_len, uint8_t prefix, uint8_t pred, struct lyxp_expr **expr)
{
- struct lyxp_expr *exp;
+ LY_ERR ret = LY_SUCCESS;
+ struct lyxp_expr *exp = NULL;
uint16_t tok_idx;
assert((prefix == LY_PATH_PREFIX_OPTIONAL) || (prefix == LY_PATH_PREFIX_MANDATORY));
assert((pred == LY_PATH_PRED_KEYS) || (pred == LY_PATH_PRED_SIMPLE) || (pred == LY_PATH_PRED_LEAFREF));
/* parse as a generic XPath expression */
- exp = lyxp_expr_parse(ctx, str_path, path_len, 0);
- LY_CHECK_GOTO(!exp, error);
+ LY_CHECK_GOTO(ret = lyxp_expr_parse(ctx, str_path, path_len, 0, &exp), error);
tok_idx = 0;
- LY_CHECK_GOTO(ly_path_check_predicate(ctx, cur_node, exp, &tok_idx, prefix, pred), error);
+ LY_CHECK_GOTO(ret = ly_path_check_predicate(ctx, cur_node, exp, &tok_idx, prefix, pred), error);
/* trailing token check */
if (exp->used > tok_idx) {
LOGVAL_P(ctx, cur_node, LYVE_XPATH, "Unparsed characters \"%s\" left at the end of predicate.",
exp->expr + exp->tok_pos[tok_idx]);
+ ret = LY_EVALID;
goto error;
}
@@ -346,7 +351,7 @@
error:
lyxp_expr_free(ctx, exp);
- return LY_EVALID;
+ return ret;
}
/**
diff --git a/src/tree_data.c b/src/tree_data.c
index 1b59493..e68314d 100644
--- a/src/tree_data.c
+++ b/src/tree_data.c
@@ -3341,7 +3341,7 @@
{
LY_ERR ret = LY_SUCCESS;
struct lyxp_set xp_set;
- struct lyxp_expr *exp;
+ struct lyxp_expr *exp = NULL;
uint32_t i;
LY_CHECK_ARG_RET(NULL, ctx_node, xpath, set, LY_EINVAL);
@@ -3349,8 +3349,8 @@
memset(&xp_set, 0, sizeof xp_set);
/* compile expression */
- exp = lyxp_expr_parse((struct ly_ctx *)LYD_CTX(ctx_node), xpath, 0, 1);
- LY_CHECK_ERR_GOTO(!exp, ret = LY_EINVAL, cleanup);
+ ret = lyxp_expr_parse((struct ly_ctx *)LYD_CTX(ctx_node), xpath, 0, 1, &exp);
+ LY_CHECK_GOTO(ret, cleanup);
/* evaluate expression */
ret = lyxp_eval(exp, LY_PREF_JSON, ctx_node->schema->module, ctx_node, LYXP_NODE_ELEM, ctx_node, &xp_set, 0);
diff --git a/src/tree_schema.c b/src/tree_schema.c
index fb77d58..43597db 100644
--- a/src/tree_schema.c
+++ b/src/tree_schema.c
@@ -301,7 +301,7 @@
{
LY_ERR ret = LY_SUCCESS;
struct lyxp_set xp_set;
- struct lyxp_expr *exp;
+ struct lyxp_expr *exp = NULL;
uint32_t i;
LY_CHECK_ARG_RET(NULL, ctx_node, xpath, set, LY_EINVAL);
@@ -312,8 +312,8 @@
memset(&xp_set, 0, sizeof xp_set);
/* compile expression */
- exp = lyxp_expr_parse(ctx_node->module->ctx, xpath, 0, 1);
- LY_CHECK_ERR_GOTO(!exp, ret = LY_EINVAL, cleanup);
+ ret = lyxp_expr_parse(ctx_node->module->ctx, xpath, 0, 1, &exp);
+ LY_CHECK_GOTO(ret, cleanup);
/* atomize expression */
ret = lyxp_atomize(exp, LY_PREF_JSON, ctx_node->module, ctx_node, LYXP_NODE_ELEM, &xp_set, options);
@@ -346,7 +346,7 @@
{
LY_ERR ret = LY_SUCCESS;
struct lyxp_set xp_set;
- struct lyxp_expr *exp;
+ struct lyxp_expr *exp = NULL;
uint32_t i;
LY_CHECK_ARG_RET(NULL, ctx_node, xpath, set, LY_EINVAL);
@@ -357,8 +357,8 @@
memset(&xp_set, 0, sizeof xp_set);
/* compile expression */
- exp = lyxp_expr_parse(ctx_node->module->ctx, xpath, 0, 1);
- LY_CHECK_ERR_GOTO(!exp, ret = LY_EINVAL, cleanup);
+ ret = lyxp_expr_parse(ctx_node->module->ctx, xpath, 0, 1, &exp);
+ LY_CHECK_GOTO(ret, cleanup);
/* atomize expression */
ret = lyxp_atomize(exp, LY_PREF_JSON, ctx_node->module, ctx_node, LYXP_NODE_ELEM, &xp_set, options);
diff --git a/src/tree_schema_compile.c b/src/tree_schema_compile.c
index 61edac2..720351a 100644
--- a/src/tree_schema_compile.c
+++ b/src/tree_schema_compile.c
@@ -909,13 +909,13 @@
LY_ERR ret = LY_SUCCESS;
*when = calloc(1, sizeof **when);
+ LY_CHECK_ERR_RET(!(*when), LOGMEM(ctx->ctx), LY_EMEM);
(*when)->refcount = 1;
- (*when)->cond = lyxp_expr_parse(ctx->ctx, when_p->cond, 0, 1);
+ LY_CHECK_RET(lyxp_expr_parse(ctx->ctx, when_p->cond, 0, 1, &(*when)->cond));
(*when)->module = ctx->mod_def;
(*when)->context = lysc_xpath_context(node);
DUP_STRING_GOTO(ctx->ctx, when_p->dsc, (*when)->dsc, ret, done);
DUP_STRING_GOTO(ctx->ctx, when_p->ref, (*when)->ref, ret, done);
- LY_CHECK_ERR_GOTO(!(*when)->cond, ret = ly_errcode(ctx->ctx), done);
COMPILE_EXTS_GOTO(ctx, when_p->exts, (*when)->exts, (*when), LYEXT_PAR_WHEN, ret, done);
(*when)->flags = flags & LYS_STATUS_MASK;
@@ -935,8 +935,7 @@
{
LY_ERR ret = LY_SUCCESS;
- must->cond = lyxp_expr_parse(ctx->ctx, must_p->arg, 0, 1);
- LY_CHECK_ERR_GOTO(!must->cond, ret = ly_errcode(ctx->ctx), done);
+ LY_CHECK_RET(lyxp_expr_parse(ctx->ctx, must_p->arg, 0, 1, &must->cond));
must->module = ctx->mod_def;
DUP_STRING_GOTO(ctx->ctx, must_p->eapptag, must->eapptag, ret, done);
DUP_STRING_GOTO(ctx->ctx, must_p->emsg, must->emsg, ret, done);
diff --git a/src/xpath.c b/src/xpath.c
index bc23eae..4691984 100644
--- a/src/xpath.c
+++ b/src/xpath.c
@@ -2653,146 +2653,150 @@
free(expr);
}
-struct lyxp_expr *
-lyxp_expr_parse(const struct ly_ctx *ctx, const char *expr, size_t expr_len, ly_bool reparse)
+LY_ERR
+lyxp_expr_parse(const struct ly_ctx *ctx, const char *expr_str, size_t expr_len, ly_bool reparse, struct lyxp_expr **expr_p)
{
- struct lyxp_expr *ret;
+ LY_ERR ret = LY_SUCCESS;
+ struct lyxp_expr *expr;
size_t parsed = 0, tok_len;
enum lyxp_token tok_type;
ly_bool prev_function_check = 0;
uint16_t tok_idx = 0;
- if (!expr[0]) {
+ assert(expr_p);
+
+ if (!expr_str[0]) {
LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_XP_EOF);
- return NULL;
+ return LY_EVALID;
}
if (!expr_len) {
- expr_len = strlen(expr);
+ expr_len = strlen(expr_str);
}
if (expr_len > UINT16_MAX) {
- LOGERR(ctx, LY_EINVAL, "XPath expression cannot be longer than %ud characters.", UINT16_MAX);
- return NULL;
+ LOGVAL(ctx, LY_VLOG_NONE, NULL, LYVE_XPATH, "XPath expression cannot be longer than %ud characters.", UINT16_MAX);
+ return LY_EVALID;
}
/* init lyxp_expr structure */
- ret = calloc(1, sizeof *ret);
- LY_CHECK_ERR_GOTO(!ret, LOGMEM(ctx), error);
- LY_CHECK_GOTO(lydict_insert(ctx, expr, expr_len, &ret->expr), error);
- LY_CHECK_ERR_GOTO(!ret->expr, LOGMEM(ctx), error);
- ret->used = 0;
- ret->size = LYXP_EXPR_SIZE_START;
- ret->tokens = malloc(ret->size * sizeof *ret->tokens);
- LY_CHECK_ERR_GOTO(!ret->tokens, LOGMEM(ctx), error);
+ expr = calloc(1, sizeof *expr);
+ LY_CHECK_ERR_GOTO(!expr, LOGMEM(ctx); ret = LY_EMEM, error);
+ LY_CHECK_GOTO(ret = lydict_insert(ctx, expr_str, expr_len, &expr->expr), error);
+ expr->used = 0;
+ expr->size = LYXP_EXPR_SIZE_START;
+ expr->tokens = malloc(expr->size * sizeof *expr->tokens);
+ LY_CHECK_ERR_GOTO(!expr->tokens, LOGMEM(ctx); ret = LY_EMEM, error);
- ret->tok_pos = malloc(ret->size * sizeof *ret->tok_pos);
- LY_CHECK_ERR_GOTO(!ret->tok_pos, LOGMEM(ctx), error);
+ expr->tok_pos = malloc(expr->size * sizeof *expr->tok_pos);
+ LY_CHECK_ERR_GOTO(!expr->tok_pos, LOGMEM(ctx); ret = LY_EMEM, error);
- ret->tok_len = malloc(ret->size * sizeof *ret->tok_len);
- LY_CHECK_ERR_GOTO(!ret->tok_len, LOGMEM(ctx), error);
+ expr->tok_len = malloc(expr->size * sizeof *expr->tok_len);
+ LY_CHECK_ERR_GOTO(!expr->tok_len, LOGMEM(ctx); ret = LY_EMEM, error);
/* make expr 0-terminated */
- expr = ret->expr;
+ expr_str = expr->expr;
- while (is_xmlws(expr[parsed])) {
+ while (is_xmlws(expr_str[parsed])) {
++parsed;
}
do {
- if (expr[parsed] == '(') {
+ if (expr_str[parsed] == '(') {
/* '(' */
tok_len = 1;
tok_type = LYXP_TOKEN_PAR1;
- if (prev_function_check && ret->used && (ret->tokens[ret->used - 1] == LYXP_TOKEN_NAMETEST)) {
+ if (prev_function_check && expr->used && (expr->tokens[expr->used - 1] == LYXP_TOKEN_NAMETEST)) {
/* it is a NodeType/FunctionName after all */
- if (((ret->tok_len[ret->used - 1] == 4)
- && (!strncmp(&expr[ret->tok_pos[ret->used - 1]], "node", 4)
- || !strncmp(&expr[ret->tok_pos[ret->used - 1]], "text", 4))) ||
- ((ret->tok_len[ret->used - 1] == 7)
- && !strncmp(&expr[ret->tok_pos[ret->used - 1]], "comment", 7))) {
- ret->tokens[ret->used - 1] = LYXP_TOKEN_NODETYPE;
+ if (((expr->tok_len[expr->used - 1] == 4)
+ && (!strncmp(&expr_str[expr->tok_pos[expr->used - 1]], "node", 4)
+ || !strncmp(&expr_str[expr->tok_pos[expr->used - 1]], "text", 4))) ||
+ ((expr->tok_len[expr->used - 1] == 7)
+ && !strncmp(&expr_str[expr->tok_pos[expr->used - 1]], "comment", 7))) {
+ expr->tokens[expr->used - 1] = LYXP_TOKEN_NODETYPE;
} else {
- ret->tokens[ret->used - 1] = LYXP_TOKEN_FUNCNAME;
+ expr->tokens[expr->used - 1] = LYXP_TOKEN_FUNCNAME;
}
prev_function_check = 0;
}
- } else if (expr[parsed] == ')') {
+ } else if (expr_str[parsed] == ')') {
/* ')' */
tok_len = 1;
tok_type = LYXP_TOKEN_PAR2;
- } else if (expr[parsed] == '[') {
+ } else if (expr_str[parsed] == '[') {
/* '[' */
tok_len = 1;
tok_type = LYXP_TOKEN_BRACK1;
- } else if (expr[parsed] == ']') {
+ } else if (expr_str[parsed] == ']') {
/* ']' */
tok_len = 1;
tok_type = LYXP_TOKEN_BRACK2;
- } else if (!strncmp(&expr[parsed], "..", 2)) {
+ } else if (!strncmp(&expr_str[parsed], "..", 2)) {
/* '..' */
tok_len = 2;
tok_type = LYXP_TOKEN_DDOT;
- } else if ((expr[parsed] == '.') && (!isdigit(expr[parsed + 1]))) {
+ } else if ((expr_str[parsed] == '.') && (!isdigit(expr_str[parsed + 1]))) {
/* '.' */
tok_len = 1;
tok_type = LYXP_TOKEN_DOT;
- } else if (expr[parsed] == '@') {
+ } else if (expr_str[parsed] == '@') {
/* '@' */
tok_len = 1;
tok_type = LYXP_TOKEN_AT;
- } else if (expr[parsed] == ',') {
+ } else if (expr_str[parsed] == ',') {
/* ',' */
tok_len = 1;
tok_type = LYXP_TOKEN_COMMA;
- } else if (expr[parsed] == '\'') {
+ } else if (expr_str[parsed] == '\'') {
/* Literal with ' */
- for (tok_len = 1; (expr[parsed + tok_len] != '\0') && (expr[parsed + tok_len] != '\''); ++tok_len) {}
- LY_CHECK_ERR_GOTO(expr[parsed + tok_len] == '\0',
- LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_XP_EOE, expr[parsed], &expr[parsed]), error);
+ for (tok_len = 1; (expr_str[parsed + tok_len] != '\0') && (expr_str[parsed + tok_len] != '\''); ++tok_len) {}
+ LY_CHECK_ERR_GOTO(expr_str[parsed + tok_len] == '\0',
+ LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_XP_EOE, expr_str[parsed], &expr_str[parsed]); ret = LY_EVALID,
+ error);
++tok_len;
tok_type = LYXP_TOKEN_LITERAL;
- } else if (expr[parsed] == '\"') {
+ } else if (expr_str[parsed] == '\"') {
/* Literal with " */
- for (tok_len = 1; (expr[parsed + tok_len] != '\0') && (expr[parsed + tok_len] != '\"'); ++tok_len) {}
- LY_CHECK_ERR_GOTO(expr[parsed + tok_len] == '\0',
- LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_XP_EOE, expr[parsed], &expr[parsed]), error);
+ for (tok_len = 1; (expr_str[parsed + tok_len] != '\0') && (expr_str[parsed + tok_len] != '\"'); ++tok_len) {}
+ LY_CHECK_ERR_GOTO(expr_str[parsed + tok_len] == '\0',
+ LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_XP_EOE, expr_str[parsed], &expr_str[parsed]); ret = LY_EVALID,
+ error);
++tok_len;
tok_type = LYXP_TOKEN_LITERAL;
- } else if ((expr[parsed] == '.') || (isdigit(expr[parsed]))) {
+ } else if ((expr_str[parsed] == '.') || (isdigit(expr_str[parsed]))) {
/* Number */
- for (tok_len = 0; isdigit(expr[parsed + tok_len]); ++tok_len) {}
- if (expr[parsed + tok_len] == '.') {
+ for (tok_len = 0; isdigit(expr_str[parsed + tok_len]); ++tok_len) {}
+ if (expr_str[parsed + tok_len] == '.') {
++tok_len;
- for ( ; isdigit(expr[parsed + tok_len]); ++tok_len) {}
+ for ( ; isdigit(expr_str[parsed + tok_len]); ++tok_len) {}
}
tok_type = LYXP_TOKEN_NUMBER;
- } else if (expr[parsed] == '/') {
+ } else if (expr_str[parsed] == '/') {
/* Operator '/', '//' */
- if (!strncmp(&expr[parsed], "//", 2)) {
+ if (!strncmp(&expr_str[parsed], "//", 2)) {
tok_len = 2;
tok_type = LYXP_TOKEN_OPER_RPATH;
} else {
@@ -2800,81 +2804,83 @@
tok_type = LYXP_TOKEN_OPER_PATH;
}
- } else if (!strncmp(&expr[parsed], "!=", 2)) {
+ } else if (!strncmp(&expr_str[parsed], "!=", 2)) {
/* Operator '!=' */
tok_len = 2;
tok_type = LYXP_TOKEN_OPER_NEQUAL;
- } else if (!strncmp(&expr[parsed], "<=", 2) || !strncmp(&expr[parsed], ">=", 2)) {
+ } else if (!strncmp(&expr_str[parsed], "<=", 2) || !strncmp(&expr_str[parsed], ">=", 2)) {
/* Operator '<=', '>=' */
tok_len = 2;
tok_type = LYXP_TOKEN_OPER_COMP;
- } else if (expr[parsed] == '|') {
+ } else if (expr_str[parsed] == '|') {
/* Operator '|' */
tok_len = 1;
tok_type = LYXP_TOKEN_OPER_UNI;
- } else if ((expr[parsed] == '+') || (expr[parsed] == '-')) {
+ } else if ((expr_str[parsed] == '+') || (expr_str[parsed] == '-')) {
/* Operator '+', '-' */
tok_len = 1;
tok_type = LYXP_TOKEN_OPER_MATH;
- } else if (expr[parsed] == '=') {
+ } else if (expr_str[parsed] == '=') {
/* Operator '=' */
tok_len = 1;
tok_type = LYXP_TOKEN_OPER_EQUAL;
- } else if ((expr[parsed] == '<') || (expr[parsed] == '>')) {
+ } else if ((expr_str[parsed] == '<') || (expr_str[parsed] == '>')) {
/* Operator '<', '>' */
tok_len = 1;
tok_type = LYXP_TOKEN_OPER_COMP;
- } else if (ret->used && (ret->tokens[ret->used - 1] != LYXP_TOKEN_AT)
- && (ret->tokens[ret->used - 1] != LYXP_TOKEN_PAR1)
- && (ret->tokens[ret->used - 1] != LYXP_TOKEN_BRACK1)
- && (ret->tokens[ret->used - 1] != LYXP_TOKEN_COMMA)
- && (ret->tokens[ret->used - 1] != LYXP_TOKEN_OPER_LOG)
- && (ret->tokens[ret->used - 1] != LYXP_TOKEN_OPER_EQUAL)
- && (ret->tokens[ret->used - 1] != LYXP_TOKEN_OPER_NEQUAL)
- && (ret->tokens[ret->used - 1] != LYXP_TOKEN_OPER_COMP)
- && (ret->tokens[ret->used - 1] != LYXP_TOKEN_OPER_MATH)
- && (ret->tokens[ret->used - 1] != LYXP_TOKEN_OPER_UNI)
- && (ret->tokens[ret->used - 1] != LYXP_TOKEN_OPER_PATH)
- && (ret->tokens[ret->used - 1] != LYXP_TOKEN_OPER_RPATH)) {
+ } else if (expr->used && (expr->tokens[expr->used - 1] != LYXP_TOKEN_AT)
+ && (expr->tokens[expr->used - 1] != LYXP_TOKEN_PAR1)
+ && (expr->tokens[expr->used - 1] != LYXP_TOKEN_BRACK1)
+ && (expr->tokens[expr->used - 1] != LYXP_TOKEN_COMMA)
+ && (expr->tokens[expr->used - 1] != LYXP_TOKEN_OPER_LOG)
+ && (expr->tokens[expr->used - 1] != LYXP_TOKEN_OPER_EQUAL)
+ && (expr->tokens[expr->used - 1] != LYXP_TOKEN_OPER_NEQUAL)
+ && (expr->tokens[expr->used - 1] != LYXP_TOKEN_OPER_COMP)
+ && (expr->tokens[expr->used - 1] != LYXP_TOKEN_OPER_MATH)
+ && (expr->tokens[expr->used - 1] != LYXP_TOKEN_OPER_UNI)
+ && (expr->tokens[expr->used - 1] != LYXP_TOKEN_OPER_PATH)
+ && (expr->tokens[expr->used - 1] != LYXP_TOKEN_OPER_RPATH)) {
/* Operator '*', 'or', 'and', 'mod', or 'div' */
- if (expr[parsed] == '*') {
+ if (expr_str[parsed] == '*') {
tok_len = 1;
tok_type = LYXP_TOKEN_OPER_MATH;
- } else if (!strncmp(&expr[parsed], "or", 2)) {
+ } else if (!strncmp(&expr_str[parsed], "or", 2)) {
tok_len = 2;
tok_type = LYXP_TOKEN_OPER_LOG;
- } else if (!strncmp(&expr[parsed], "and", 3)) {
+ } else if (!strncmp(&expr_str[parsed], "and", 3)) {
tok_len = 3;
tok_type = LYXP_TOKEN_OPER_LOG;
- } else if (!strncmp(&expr[parsed], "mod", 3) || !strncmp(&expr[parsed], "div", 3)) {
+ } else if (!strncmp(&expr_str[parsed], "mod", 3) || !strncmp(&expr_str[parsed], "div", 3)) {
tok_len = 3;
tok_type = LYXP_TOKEN_OPER_MATH;
} else if (prev_function_check) {
LOGVAL(ctx, LY_VLOG_NONE, NULL, LYVE_XPATH, "Invalid character 0x%x ('%c'), perhaps \"%.*s\" is supposed to be a function call.",
- expr[parsed], expr[parsed], ret->tok_len[ret->used - 1], &ret->expr[ret->tok_pos[ret->used - 1]]);
+ expr_str[parsed], expr_str[parsed], expr->tok_len[expr->used - 1], &expr->expr[expr->tok_pos[expr->used - 1]]);
+ ret = LY_EVALID;
goto error;
} else {
- LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_XP_INEXPR, parsed + 1, expr);
+ LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_XP_INEXPR, parsed + 1, expr_str);
+ ret = LY_EVALID;
goto error;
}
- } else if (expr[parsed] == '*') {
+ } else if (expr_str[parsed] == '*') {
/* NameTest '*' */
tok_len = 1;
@@ -2883,17 +2889,21 @@
} else {
/* NameTest (NCName ':' '*' | QName) or NodeType/FunctionName */
- long int ncname_len = parse_ncname(&expr[parsed]);
- LY_CHECK_ERR_GOTO(ncname_len < 0, LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_XP_INEXPR, parsed - ncname_len + 1, expr), error);
+ long int ncname_len = parse_ncname(&expr_str[parsed]);
+ LY_CHECK_ERR_GOTO(ncname_len < 0,
+ LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_XP_INEXPR, parsed - ncname_len + 1, expr_str); ret = LY_EVALID,
+ error);
tok_len = ncname_len;
- if (expr[parsed + tok_len] == ':') {
+ if (expr_str[parsed + tok_len] == ':') {
++tok_len;
- if (expr[parsed + tok_len] == '*') {
+ if (expr_str[parsed + tok_len] == '*') {
++tok_len;
} else {
- ncname_len = parse_ncname(&expr[parsed + tok_len]);
- LY_CHECK_ERR_GOTO(ncname_len < 0, LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_XP_INEXPR, parsed - ncname_len + 1, expr), error);
+ ncname_len = parse_ncname(&expr_str[parsed + tok_len]);
+ LY_CHECK_ERR_GOTO(ncname_len < 0,
+ LOGVAL(ctx, LY_VLOG_NONE, NULL, LY_VCODE_XP_INEXPR, parsed - ncname_len + 1, expr_str); ret = LY_EVALID,
+ error);
tok_len += ncname_len;
}
/* remove old flag to prevent ambiguities */
@@ -2907,35 +2917,36 @@
}
/* store the token, move on to the next one */
- LY_CHECK_GOTO(exp_add_token(ctx, ret, tok_type, parsed, tok_len), error);
+ LY_CHECK_GOTO(ret = exp_add_token(ctx, expr, tok_type, parsed, tok_len), error);
parsed += tok_len;
- while (is_xmlws(expr[parsed])) {
+ while (is_xmlws(expr_str[parsed])) {
++parsed;
}
- } while (expr[parsed]);
+ } while (expr_str[parsed]);
if (reparse) {
/* prealloc repeat */
- ret->repeat = calloc(ret->size, sizeof *ret->repeat);
- LY_CHECK_ERR_GOTO(!ret->repeat, LOGMEM(ctx), error);
+ expr->repeat = calloc(expr->size, sizeof *expr->repeat);
+ LY_CHECK_ERR_GOTO(!expr->repeat, LOGMEM(ctx); ret = LY_EMEM, error);
/* fill repeat */
- LY_CHECK_GOTO(reparse_or_expr(ctx, ret, &tok_idx), error);
- if (ret->used > tok_idx) {
+ LY_CHECK_ERR_GOTO(reparse_or_expr(ctx, expr, &tok_idx), ret = LY_EVALID, error);
+ if (expr->used > tok_idx) {
LOGVAL(ctx, LY_VLOG_NONE, NULL, LYVE_XPATH, "Unparsed characters \"%s\" left at the end of an XPath expression.",
- &ret->expr[ret->tok_pos[tok_idx]]);
+ &expr->expr[expr->tok_pos[tok_idx]]);
+ ret = LY_EVALID;
goto error;
}
}
- print_expr_struct_debug(ret);
-
- return ret;
+ print_expr_struct_debug(expr);
+ *expr_p = expr;
+ return LY_SUCCESS;
error:
- lyxp_expr_free(ctx, ret);
- return NULL;
+ lyxp_expr_free(ctx, expr);
+ return ret;
}
struct lyxp_expr *
diff --git a/src/xpath.h b/src/xpath.h
index e74f48b..20498cd 100644
--- a/src/xpath.h
+++ b/src/xpath.h
@@ -374,13 +374,16 @@
* https://www.w3.org/TR/1999/REC-xpath-19991116/#exprlex
*
* @param[in] ctx Context for errors.
- * @param[in] expr XPath expression to parse. It is duplicated.
+ * @param[in] expr_str XPath expression to parse. It is duplicated.
* @param[in] expr_len Length of @p expr, can be 0 if @p expr is 0-terminated.
* @param[in] reparse Whether to re-parse the expression to finalize full XPath parsing and fill
* information about expressions and their operators (fill repeat).
- * @return Filled expression structure or NULL on error.
+ * @param[out] expr_p Pointer to return the filled expression structure.
+ * @return LY_SUCCESS in case of success.
+ * @return LY_EMEM in case of memory allocation failure.
+ * @return LY_EVALID in case of invalid XPath expression in @p expr_str.
*/
-struct lyxp_expr *lyxp_expr_parse(const struct ly_ctx *ctx, const char *expr, size_t expr_len, ly_bool reparse);
+LY_ERR lyxp_expr_parse(const struct ly_ctx *ctx, const char *expr_str, size_t expr_len, ly_bool reparse, struct lyxp_expr **expr_p);
/**
* @brief Duplicate parsed XPath expression.