diff options
Diffstat (limited to 'src/xpath.c')
-rw-r--r-- | src/xpath.c | 473 |
1 files changed, 299 insertions, 174 deletions
diff --git a/src/xpath.c b/src/xpath.c index ab7921e..bc5f695 100644 --- a/src/xpath.c +++ b/src/xpath.c @@ -43,8 +43,6 @@ #include "tree_schema_internal.h" #include "xml.h" -static LY_ERR set_scnode_insert_node(struct lyxp_set *set, const struct lysc_node *node, enum lyxp_node_type node_type, - enum lyxp_axis axis, uint32_t *index_p); static LY_ERR reparse_or_expr(const struct ly_ctx *ctx, struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t depth); static LY_ERR eval_expr_select(const struct lyxp_expr *exp, uint32_t *tok_idx, enum lyxp_expr_type etype, struct lyxp_set *set, uint32_t options); @@ -123,6 +121,8 @@ lyxp_token2str(enum lyxp_token tok) return "@"; case LYXP_TOKEN_COMMA: return ","; + case LYXP_TOKEN_DCOLON: + return "::"; case LYXP_TOKEN_NAMETEST: return "NameTest"; case LYXP_TOKEN_NODETYPE: @@ -147,6 +147,8 @@ lyxp_token2str(enum lyxp_token tok) return "Operator(Path)"; case LYXP_TOKEN_OPER_RPATH: return "Operator(Recursive Path)"; + case LYXP_TOKEN_AXISNAME: + return "AxisName"; case LYXP_TOKEN_LITERAL: return "Literal"; case LYXP_TOKEN_NUMBER: @@ -217,16 +219,53 @@ str2axis(const char *str, uint32_t str_len) } /** - * @brief Print the whole expression \p exp to debug output. + * @brief Append a string to a dynamic string variable. + * + * @param[in,out] str String to use. + * @param[in,out] size String size. + * @param[in,out] used String used size excluding terminating zero. + * @param[in] format Message format. + * @param[in] ... Message format arguments. + */ +static void +print_expr_str(char **str, size_t *size, size_t *used, const char *format, ...) +{ + int p; + va_list ap; + + va_start(ap, format); + + /* try to append the string */ + p = vsnprintf(*str ? *str + *used : NULL, *size - *used, format, ap); + + if ((unsigned)p >= *size - *used) { + /* realloc */ + *str = ly_realloc(*str, *size + p + 1); + *size += p + 1; + + /* restart ap */ + va_end(ap); + va_start(ap, format); + + /* print */ + p = vsnprintf(*str + *used, *size - *used, format, ap); + } + + *used += p; + va_end(ap); +} + +/** + * @brief Print the whole expression @p exp to debug output. * * @param[in] exp Expression to use. */ static void print_expr_struct_debug(const struct lyxp_expr *exp) { -#define MSG_BUFFER_SIZE 128 - char tmp[MSG_BUFFER_SIZE]; + char *buf = NULL; uint32_t i, j; + size_t size = 0, used = 0; if (!exp || (ly_ll < LY_LLDBG)) { return; @@ -234,18 +273,21 @@ print_expr_struct_debug(const struct lyxp_expr *exp) LOGDBG(LY_LDGXPATH, "expression \"%s\":", exp->expr); for (i = 0; i < exp->used; ++i) { - sprintf(tmp, "\ttoken %s, in expression \"%.*s\"", lyxp_token2str(exp->tokens[i]), exp->tok_len[i], - &exp->expr[exp->tok_pos[i]]); + print_expr_str(&buf, &size, &used, "\ttoken %s, in expression \"%.*s\"", + lyxp_token2str(exp->tokens[i]), exp->tok_len[i], &exp->expr[exp->tok_pos[i]]); + if (exp->repeat && exp->repeat[i]) { - sprintf(tmp + strlen(tmp), " (repeat %d", exp->repeat[i][0]); + print_expr_str(&buf, &size, &used, " (repeat %d", exp->repeat[i][0]); for (j = 1; exp->repeat[i][j]; ++j) { - sprintf(tmp + strlen(tmp), ", %d", exp->repeat[i][j]); + print_expr_str(&buf, &size, &used, ", %d", exp->repeat[i][j]); } - strcat(tmp, ")"); + print_expr_str(&buf, &size, &used, ")"); } - LOGDBG(LY_LDGXPATH, tmp); + LOGDBG(LY_LDGXPATH, buf); + used = 0; } -#undef MSG_BUFFER_SIZE + + free(buf); } #ifndef NDEBUG @@ -284,18 +326,19 @@ print_set_debug(struct lyxp_set *set) LOGDBG(LY_LDGXPATH, "\t%d (pos %u): ROOT CONFIG", i + 1, item->pos); break; case LYXP_NODE_ELEM: - if ((item->node->schema->nodetype == LYS_LIST) && (lyd_child(item->node)->schema->nodetype == LYS_LEAF)) { + if (item->node->schema && (item->node->schema->nodetype == LYS_LIST) && + (lyd_child(item->node)->schema->nodetype == LYS_LEAF)) { LOGDBG(LY_LDGXPATH, "\t%d (pos %u): ELEM %s (1st child val: %s)", i + 1, item->pos, item->node->schema->name, lyd_get_value(lyd_child(item->node))); - } else if (item->node->schema->nodetype == LYS_LEAFLIST) { + } else if ((!item->node->schema && !lyd_child(item->node)) || (item->node->schema->nodetype == LYS_LEAFLIST)) { LOGDBG(LY_LDGXPATH, "\t%d (pos %u): ELEM %s (val: %s)", i + 1, item->pos, - item->node->schema->name, lyd_get_value(item->node)); + LYD_NAME(item->node), lyd_get_value(item->node)); } else { - LOGDBG(LY_LDGXPATH, "\t%d (pos %u): ELEM %s", i + 1, item->pos, item->node->schema->name); + LOGDBG(LY_LDGXPATH, "\t%d (pos %u): ELEM %s", i + 1, item->pos, LYD_NAME(item->node)); } break; case LYXP_NODE_TEXT: - if (item->node->schema->nodetype & LYS_ANYDATA) { + if (item->node->schema && (item->node->schema->nodetype & LYS_ANYDATA)) { LOGDBG(LY_LDGXPATH, "\t%d (pos %u): TEXT <%s>", i + 1, item->pos, item->node->schema->nodetype == LYS_ANYXML ? "anyxml" : "anydata"); } else { @@ -416,13 +459,14 @@ cast_string_recursive(const struct lyd_node *node, struct lyxp_set *set, uint32_ { char *buf, *line, *ptr = NULL; const char *value_str; + uint16_t nodetype; const struct lyd_node *child; enum lyxp_node_type child_type; struct lyd_node *tree; struct lyd_node_any *any; LY_ERR rc; - if ((set->root_type == LYXP_NODE_ROOT_CONFIG) && node && (node->schema->flags & LYS_CONFIG_R)) { + if ((set->root_type == LYXP_NODE_ROOT_CONFIG) && node && node->schema && (node->schema->flags & LYS_CONFIG_R)) { return LY_SUCCESS; } @@ -448,7 +492,15 @@ cast_string_recursive(const struct lyd_node *node, struct lyxp_set *set, uint32_ --indent; } else { - switch (node->schema->nodetype) { + if (node->schema) { + nodetype = node->schema->nodetype; + } else if (lyd_child(node)) { + nodetype = LYS_CONTAINER; + } else { + nodetype = LYS_LEAF; + } + + switch (nodetype) { case LYS_CONTAINER: case LYS_LIST: case LYS_RPC: @@ -691,29 +743,29 @@ set_insert_node_hash(struct lyxp_set *set, struct lyd_node *node, enum lyxp_node hnode.node = set->val.nodes[i].node; hnode.type = set->val.nodes[i].type; - hash = dict_hash_multi(0, (const char *)&hnode.node, sizeof hnode.node); - hash = dict_hash_multi(hash, (const char *)&hnode.type, sizeof hnode.type); - hash = dict_hash_multi(hash, NULL, 0); + hash = lyht_hash_multi(0, (const char *)&hnode.node, sizeof hnode.node); + hash = lyht_hash_multi(hash, (const char *)&hnode.type, sizeof hnode.type); + hash = lyht_hash_multi(hash, NULL, 0); r = lyht_insert(set->ht, &hnode, hash, NULL); assert(!r); (void)r; - if (hnode.node == node) { + if ((hnode.node == node) && (hnode.type == type)) { /* it was just added, do not add it twice */ - node = NULL; + return; } } } - if (set->ht && node) { + if (set->ht) { /* add the new node into hash table */ hnode.node = node; hnode.type = type; - hash = dict_hash_multi(0, (const char *)&hnode.node, sizeof hnode.node); - hash = dict_hash_multi(hash, (const char *)&hnode.type, sizeof hnode.type); - hash = dict_hash_multi(hash, NULL, 0); + hash = lyht_hash_multi(0, (const char *)&hnode.node, sizeof hnode.node); + hash = lyht_hash_multi(hash, (const char *)&hnode.type, sizeof hnode.type); + hash = lyht_hash_multi(hash, NULL, 0); r = lyht_insert(set->ht, &hnode, hash, NULL); assert(!r); @@ -739,16 +791,16 @@ set_remove_node_hash(struct lyxp_set *set, struct lyd_node *node, enum lyxp_node hnode.node = node; hnode.type = type; - hash = dict_hash_multi(0, (const char *)&hnode.node, sizeof hnode.node); - hash = dict_hash_multi(hash, (const char *)&hnode.type, sizeof hnode.type); - hash = dict_hash_multi(hash, NULL, 0); + hash = lyht_hash_multi(0, (const char *)&hnode.node, sizeof hnode.node); + hash = lyht_hash_multi(hash, (const char *)&hnode.type, sizeof hnode.type); + hash = lyht_hash_multi(hash, NULL, 0); r = lyht_remove(set->ht, &hnode, hash); assert(!r); (void)r; if (!set->ht->used) { - lyht_free(set->ht); + lyht_free(set->ht, NULL); set->ht = NULL; } } @@ -772,9 +824,9 @@ set_dup_node_hash_check(const struct lyxp_set *set, struct lyd_node *node, enum hnode.node = node; hnode.type = type; - hash = dict_hash_multi(0, (const char *)&hnode.node, sizeof hnode.node); - hash = dict_hash_multi(hash, (const char *)&hnode.type, sizeof hnode.type); - hash = dict_hash_multi(hash, NULL, 0); + hash = lyht_hash_multi(0, (const char *)&hnode.node, sizeof hnode.node); + hash = lyht_hash_multi(hash, (const char *)&hnode.type, sizeof hnode.type); + hash = lyht_hash_multi(hash, NULL, 0); if (!lyht_find(set->ht, &hnode, hash, (void **)&match_p)) { if ((skip_idx > -1) && (set->val.nodes[skip_idx].node == match_p->node) && (set->val.nodes[skip_idx].type == match_p->type)) { @@ -802,10 +854,10 @@ lyxp_set_free_content(struct lyxp_set *set) if (set->type == LYXP_SET_NODE_SET) { free(set->val.nodes); - lyht_free(set->ht); + lyht_free(set->ht, NULL); } else if (set->type == LYXP_SET_SCNODE_SET) { free(set->val.scnodes); - lyht_free(set->ht); + lyht_free(set->ht, NULL); } else { if (set->type == LYXP_SET_STRING) { free(set->val.str); @@ -847,18 +899,21 @@ static void set_init(struct lyxp_set *new, const struct lyxp_set *set) { memset(new, 0, sizeof *new); - if (set) { - new->non_child_axis = set->non_child_axis; - new->ctx = set->ctx; - new->cur_node = set->cur_node; - new->root_type = set->root_type; - new->context_op = set->context_op; - new->tree = set->tree; - new->cur_mod = set->cur_mod; - new->format = set->format; - new->prefix_data = set->prefix_data; - new->vars = set->vars; + if (!set) { + return; } + + new->non_child_axis = set->non_child_axis; + new->not_found = set->not_found; + new->ctx = set->ctx; + new->cur_node = set->cur_node; + new->root_type = set->root_type; + new->context_op = set->context_op; + new->tree = set->tree; + new->cur_mod = set->cur_mod; + new->format = set->format; + new->prefix_data = set->prefix_data; + new->vars = set->vars; } /** @@ -889,7 +944,7 @@ set_copy(struct lyxp_set *set) (set->val.scnodes[i].in_ctx == LYXP_SET_SCNODE_START)) { uint32_t idx; - LY_CHECK_ERR_RET(set_scnode_insert_node(ret, set->val.scnodes[i].scnode, set->val.scnodes[i].type, + LY_CHECK_ERR_RET(lyxp_set_scnode_insert_node(ret, set->val.scnodes[i].scnode, set->val.scnodes[i].type, set->val.scnodes[i].axis, &idx), lyxp_set_free(ret), NULL); /* coverity seems to think scnodes can be NULL */ if (!ret->val.scnodes) { @@ -989,11 +1044,7 @@ set_fill_set(struct lyxp_set *trg, const struct lyxp_set *src) return; } - if (trg->type == LYXP_SET_NODE_SET) { - free(trg->val.nodes); - } else if (trg->type == LYXP_SET_STRING) { - free(trg->val.str); - } + lyxp_set_free_content(trg); set_init(trg, src); if (src->type == LYXP_SET_SCNODE_SET) { @@ -1314,19 +1365,8 @@ set_insert_node(struct lyxp_set *set, const struct lyd_node *node, uint32_t pos, set_insert_node_hash(set, (struct lyd_node *)node, node_type); } -/** - * @brief Insert schema node into set. - * - * @param[in] set Set to insert into. - * @param[in] node Node to insert. - * @param[in] node_type Node type of @p node. - * @param[in] axis Axis that @p node was reached on. - * @param[out] index_p Optional pointer to store index if the inserted @p node. - * @return LY_SUCCESS on success. - * @return LY_EMEM on memory allocation failure. - */ -static LY_ERR -set_scnode_insert_node(struct lyxp_set *set, const struct lysc_node *node, enum lyxp_node_type node_type, +LY_ERR +lyxp_set_scnode_insert_node(struct lyxp_set *set, const struct lysc_node *node, enum lyxp_node_type node_type, enum lyxp_axis axis, uint32_t *index_p) { uint32_t index; @@ -1346,7 +1386,7 @@ set_scnode_insert_node(struct lyxp_set *set, const struct lysc_node *node, enum } if (lyxp_set_scnode_contains(set, node, node_type, -1, &index)) { - /* BUG if axes differs, this new one is thrown away */ + /* BUG if axes differ, this new one is thrown away */ set->val.scnodes[index].in_ctx = LYXP_SET_SCNODE_ATOM_CTX; } else { if (set->used == set->size) { @@ -1445,7 +1485,7 @@ dfs_search: LYD_TREE_DFS_continue = 0; } - if (!elem->schema || ((root_type == LYXP_NODE_ROOT_CONFIG) && (elem->schema->flags & LYS_CONFIG_R))) { + if ((root_type == LYXP_NODE_ROOT_CONFIG) && elem->schema && (elem->schema->flags & LYS_CONFIG_R)) { /* skip */ LYD_TREE_DFS_continue = 1; } else { @@ -1662,7 +1702,7 @@ set_comp_canonize(struct lyxp_set *set, const struct lyxp_set_node *xp_node) /* is there anything to canonize even? */ if (set->type == LYXP_SET_STRING) { /* do we have a type to use for canonization? */ - if ((xp_node->type == LYXP_NODE_ELEM) && (xp_node->node->schema->nodetype & LYD_NODE_TERM)) { + if ((xp_node->type == LYXP_NODE_ELEM) && xp_node->node->schema && (xp_node->node->schema->nodetype & LYD_NODE_TERM)) { type = ((struct lyd_node_term *)xp_node->node)->value.realtype; } else if (xp_node->type == LYXP_NODE_META) { type = ((struct lyd_meta *)xp_node->node)->value.realtype; @@ -1785,9 +1825,9 @@ set_sort(struct lyxp_set *set) hnode.node = set->val.nodes[i].node; hnode.type = set->val.nodes[i].type; - hash = dict_hash_multi(0, (const char *)&hnode.node, sizeof hnode.node); - hash = dict_hash_multi(hash, (const char *)&hnode.type, sizeof hnode.type); - hash = dict_hash_multi(hash, NULL, 0); + hash = lyht_hash_multi(0, (const char *)&hnode.node, sizeof hnode.node); + hash = lyht_hash_multi(hash, (const char *)&hnode.type, sizeof hnode.type); + hash = lyht_hash_multi(hash, NULL, 0); assert(!lyht_find(set->ht, &hnode, hash, NULL)); } @@ -1993,11 +2033,11 @@ lyxp_next_token2(const struct ly_ctx *ctx, const struct lyxp_expr *exp, uint32_t * @brief Stack operation push on the repeat array. * * @param[in] exp Expression to use. - * @param[in] tok_idx Position in the expresion \p exp. - * @param[in] repeat_op_idx Index from \p exp of the operator token. This value is pushed. + * @param[in] tok_idx Position in the expresion @p exp. + * @param[in] repeat_expr_type Repeated expression type, this value is pushed. */ static void -exp_repeat_push(struct lyxp_expr *exp, uint32_t tok_idx, uint32_t repeat_op_idx) +exp_repeat_push(struct lyxp_expr *exp, uint32_t tok_idx, enum lyxp_expr_type repeat_expr_type) { uint32_t i; @@ -2005,12 +2045,12 @@ exp_repeat_push(struct lyxp_expr *exp, uint32_t tok_idx, uint32_t repeat_op_idx) for (i = 0; exp->repeat[tok_idx][i]; ++i) {} exp->repeat[tok_idx] = realloc(exp->repeat[tok_idx], (i + 2) * sizeof *exp->repeat[tok_idx]); LY_CHECK_ERR_RET(!exp->repeat[tok_idx], LOGMEM(NULL), ); - exp->repeat[tok_idx][i] = repeat_op_idx; + exp->repeat[tok_idx][i] = repeat_expr_type; exp->repeat[tok_idx][i + 1] = 0; } else { exp->repeat[tok_idx] = calloc(2, sizeof *exp->repeat[tok_idx]); LY_CHECK_ERR_RET(!exp->repeat[tok_idx], LOGMEM(NULL), ); - exp->repeat[tok_idx][0] = repeat_op_idx; + exp->repeat[tok_idx][0] = repeat_expr_type; } } @@ -2994,7 +3034,7 @@ lyxp_expr_parse(const struct ly_ctx *ctx, const char *expr_str, size_t expr_len, parsed++; ncname_len = parse_ncname(&expr_str[parsed]); LY_CHECK_ERR_GOTO(ncname_len < 1, LOGVAL(ctx, LY_VCODE_XP_INEXPR, expr_str[parsed - ncname_len], - parsed - ncname_len + 1, expr_str); ret = LY_EVALID, error); + (uint32_t)(parsed - ncname_len + 1), expr_str); ret = LY_EVALID, error); tok_len = ncname_len; LY_CHECK_ERR_GOTO(expr_str[parsed + tok_len] == ':', LOGVAL(ctx, LYVE_XPATH, "Variable with prefix is not supported."); ret = LY_EVALID, @@ -3084,7 +3124,7 @@ lyxp_expr_parse(const struct ly_ctx *ctx, const char *expr_str, size_t expr_len, ret = LY_EVALID; goto error; } else { - LOGVAL(ctx, LY_VCODE_XP_INEXPR, expr_str[parsed], parsed + 1, expr_str); + LOGVAL(ctx, LY_VCODE_XP_INEXPR, expr_str[parsed], (uint32_t)(parsed + 1), expr_str); ret = LY_EVALID; goto error; } @@ -3096,7 +3136,7 @@ lyxp_expr_parse(const struct ly_ctx *ctx, const char *expr_str, size_t expr_len, } else { ncname_len = parse_ncname(&expr_str[parsed]); LY_CHECK_ERR_GOTO(ncname_len < 1, LOGVAL(ctx, LY_VCODE_XP_INEXPR, expr_str[parsed - ncname_len], - parsed - ncname_len + 1, expr_str); ret = LY_EVALID, error); + (uint32_t)(parsed - ncname_len + 1), expr_str); ret = LY_EVALID, error); } tok_len = ncname_len; @@ -3104,7 +3144,8 @@ lyxp_expr_parse(const struct ly_ctx *ctx, const char *expr_str, size_t expr_len, if (!strncmp(&expr_str[parsed + tok_len], "::", 2)) { /* axis */ LY_CHECK_ERR_GOTO(expr_parse_axis(&expr_str[parsed], ncname_len), - LOGVAL(ctx, LY_VCODE_XP_INEXPR, expr_str[parsed], parsed + 1, expr_str); ret = LY_EVALID, error); + LOGVAL(ctx, LY_VCODE_XP_INEXPR, expr_str[parsed], (uint32_t)(parsed + 1), expr_str); ret = LY_EVALID, + error); tok_type = LYXP_TOKEN_AXISNAME; LY_CHECK_GOTO(ret = exp_add_token(ctx, expr, tok_type, parsed, tok_len), error); @@ -3122,7 +3163,7 @@ lyxp_expr_parse(const struct ly_ctx *ctx, const char *expr_str, size_t expr_len, } else { ncname_len = parse_ncname(&expr_str[parsed]); LY_CHECK_ERR_GOTO(ncname_len < 1, LOGVAL(ctx, LY_VCODE_XP_INEXPR, expr_str[parsed - ncname_len], - parsed - ncname_len + 1, expr_str); ret = LY_EVALID, error); + (uint32_t)(parsed - ncname_len + 1), expr_str); ret = LY_EVALID, error); } tok_len = ncname_len; @@ -3136,7 +3177,7 @@ lyxp_expr_parse(const struct ly_ctx *ctx, const char *expr_str, size_t expr_len, } else { ncname_len = parse_ncname(&expr_str[parsed + tok_len]); LY_CHECK_ERR_GOTO(ncname_len < 1, LOGVAL(ctx, LY_VCODE_XP_INEXPR, expr_str[parsed - ncname_len], - parsed - ncname_len + 1, expr_str); ret = LY_EVALID, error); + (uint32_t)(parsed - ncname_len + 1), expr_str); ret = LY_EVALID, error); tok_len += ncname_len; } /* remove old flags to prevent ambiguities */ @@ -3934,10 +3975,10 @@ xpath_current(struct lyxp_set **args, uint32_t arg_count, struct lyxp_set *set, set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_NODE); if (set->cur_scnode) { - LY_CHECK_RET(set_scnode_insert_node(set, set->cur_scnode, LYXP_NODE_ELEM, LYXP_AXIS_SELF, NULL)); + LY_CHECK_RET(lyxp_set_scnode_insert_node(set, set->cur_scnode, LYXP_NODE_ELEM, LYXP_AXIS_SELF, NULL)); } else { /* root node */ - LY_CHECK_RET(set_scnode_insert_node(set, NULL, set->root_type, LYXP_AXIS_SELF, NULL)); + LY_CHECK_RET(lyxp_set_scnode_insert_node(set, NULL, set->root_type, LYXP_AXIS_SELF, NULL)); } } else { lyxp_set_free_content(set); @@ -4003,7 +4044,7 @@ xpath_deref(struct lyxp_set **args, uint32_t UNUSED(arg_count), struct lyxp_set target = p[LY_ARRAY_COUNT(p) - 1].node; ly_path_free(set->ctx, p); - LY_CHECK_RET(set_scnode_insert_node(set, target, LYXP_NODE_ELEM, LYXP_AXIS_SELF, NULL)); + LY_CHECK_RET(lyxp_set_scnode_insert_node(set, target, LYXP_NODE_ELEM, LYXP_AXIS_SELF, NULL)); } /* else the target was found before but is disabled so it was removed */ } @@ -4030,7 +4071,7 @@ xpath_deref(struct lyxp_set **args, uint32_t UNUSED(arg_count), struct lyxp_set } } else { assert(sleaf->type->basetype == LY_TYPE_INST); - if (ly_path_eval(leaf->value.target, set->tree, &node)) { + if (ly_path_eval(leaf->value.target, set->tree, NULL, &node)) { LOGERR(set->ctx, LY_EVALID, "Invalid instance-identifier \"%s\" value - required instance not found.", lyd_get_value(&leaf->node)); return LY_EVALID; @@ -4274,9 +4315,25 @@ xpath_false(struct lyxp_set **UNUSED(args), uint32_t UNUSED(arg_count), struct l * @return LY_ERR */ static LY_ERR -xpath_floor(struct lyxp_set **args, uint32_t UNUSED(arg_count), struct lyxp_set *set, uint32_t UNUSED(options)) +xpath_floor(struct lyxp_set **args, uint32_t UNUSED(arg_count), struct lyxp_set *set, uint32_t options) { - LY_ERR rc; + struct lysc_node_leaf *sleaf; + LY_ERR rc = LY_SUCCESS; + + if (options & LYXP_SCNODE_ALL) { + if (args[0]->type != LYXP_SET_SCNODE_SET) { + LOGWRN(set->ctx, "Argument #1 of %s not a node-set as expected.", __func__); + } else if ((sleaf = (struct lysc_node_leaf *)warn_get_scnode_in_ctx(args[0]))) { + if (!(sleaf->nodetype & (LYS_LEAF | LYS_LEAFLIST))) { + LOGWRN(set->ctx, "Argument #1 of %s is a %s node \"%s\".", __func__, lys_nodetype2str(sleaf->nodetype), + sleaf->name); + } else if (!warn_is_specific_type(sleaf->type, LY_TYPE_DEC64)) { + LOGWRN(set->ctx, "Argument #1 of %s is node \"%s\", not of type \"decimal64\".", __func__, sleaf->name); + } + } + set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_VAL); + return rc; + } rc = lyxp_set_cast(args[0], LYXP_SET_NUMBER); LY_CHECK_RET(rc); @@ -4474,7 +4531,7 @@ xpath_local_name(struct lyxp_set **args, uint32_t arg_count, struct lyxp_set *se set_fill_string(set, "", 0); break; case LYXP_NODE_ELEM: - set_fill_string(set, item->node->schema->name, strlen(item->node->schema->name)); + set_fill_string(set, LYD_NAME(item->node), strlen(LYD_NAME(item->node))); break; case LYXP_NODE_META: set_fill_string(set, ((struct lyd_meta *)item->node)->name, strlen(((struct lyd_meta *)item->node)->name)); @@ -4498,7 +4555,7 @@ static LY_ERR xpath_name(struct lyxp_set **args, uint32_t arg_count, struct lyxp_set *set, uint32_t options) { struct lyxp_set_node *item; - struct lys_module *mod = NULL; + const struct lys_module *mod = NULL; char *str; const char *name = NULL; @@ -4544,8 +4601,8 @@ xpath_name(struct lyxp_set **args, uint32_t arg_count, struct lyxp_set *set, uin /* keep NULL */ break; case LYXP_NODE_ELEM: - mod = item->node->schema->module; - name = item->node->schema->name; + mod = lyd_node_module(item->node); + name = LYD_NAME(item->node); break; case LYXP_NODE_META: mod = ((struct lyd_meta *)item->node)->annotation->module; @@ -4580,7 +4637,7 @@ static LY_ERR xpath_namespace_uri(struct lyxp_set **args, uint32_t arg_count, struct lyxp_set *set, uint32_t options) { struct lyxp_set_node *item; - struct lys_module *mod; + const struct lys_module *mod; /* suppress unused variable warning */ (void)options; @@ -4630,7 +4687,7 @@ xpath_namespace_uri(struct lyxp_set **args, uint32_t arg_count, struct lyxp_set case LYXP_NODE_ELEM: case LYXP_NODE_META: if (item->type == LYXP_NODE_ELEM) { - mod = item->node->schema->module; + mod = lyd_node_module(item->node); } else { /* LYXP_NODE_META */ /* annotations */ mod = ((struct lyd_meta *)item->node)->annotation->module; @@ -5541,7 +5598,7 @@ xpath_pi_text(struct lyxp_set *set, enum lyxp_axis axis, uint32_t options) case LYXP_NODE_NONE: LOGINT_RET(set->ctx); case LYXP_NODE_ELEM: - if (set->val.nodes[i].node->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST)) { + if (!set->val.nodes[i].node->schema || (set->val.nodes[i].node->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST))) { set->val.nodes[i].type = LYXP_NODE_TEXT; break; } @@ -5588,7 +5645,7 @@ moveto_resolve_model(const char **qname, uint32_t *qname_len, const struct lyxp_ /* check for errors and non-implemented modules, as they are not valid */ if (!mod || !mod->implemented) { - LOGVAL(set->ctx, LY_VCODE_XP_INMOD, pref_len, *qname); + LOGVAL(set->ctx, LY_VCODE_XP_INMOD, (int)pref_len, *qname); return LY_EVALID; } @@ -5641,10 +5698,9 @@ moveto_root(struct lyxp_set *set, uint32_t options) if (options & LYXP_SCNODE_ALL) { set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_NODE); - LY_CHECK_RET(set_scnode_insert_node(set, NULL, set->root_type, LYXP_AXIS_SELF, NULL)); + LY_CHECK_RET(lyxp_set_scnode_insert_node(set, NULL, set->root_type, LYXP_AXIS_SELF, NULL)); } else { - set->type = LYXP_SET_NODE_SET; - set->used = 0; + lyxp_set_free_content(set); set_insert_node(set, NULL, 0, set->root_type, 0); set->non_child_axis = 0; } @@ -5668,6 +5724,8 @@ static LY_ERR moveto_node_check(const struct lyd_node *node, enum lyxp_node_type node_type, const struct lyxp_set *set, const char *node_name, const struct lys_module *moveto_mod, uint32_t options) { + const struct lysc_node *schema; + if ((node_type == LYXP_NODE_ROOT_CONFIG) || (node_type == LYXP_NODE_ROOT)) { assert(node_type == set->root_type); @@ -5681,39 +5739,40 @@ moveto_node_check(const struct lyd_node *node, enum lyxp_node_type node_type, co return LY_ENOT; } - if (!node->schema) { - /* opaque node never matches */ + /* get schema node even of an opaque node */ + schema = lyd_node_schema(node); + if (!schema) { + /* unknown opaque node never matches */ return LY_ENOT; } /* module check */ if (moveto_mod) { - if ((set->ctx == LYD_CTX(node)) && (node->schema->module != moveto_mod)) { + if ((set->ctx == LYD_CTX(node)) && (schema->module != moveto_mod)) { return LY_ENOT; - } else if ((set->ctx != LYD_CTX(node)) && strcmp(node->schema->module->name, moveto_mod->name)) { + } else if ((set->ctx != LYD_CTX(node)) && strcmp(schema->module->name, moveto_mod->name)) { return LY_ENOT; } } /* context check */ - if ((set->root_type == LYXP_NODE_ROOT_CONFIG) && (node->schema->flags & LYS_CONFIG_R)) { + if ((set->root_type == LYXP_NODE_ROOT_CONFIG) && (schema->flags & LYS_CONFIG_R)) { return LY_EINVAL; - } else if (set->context_op && (node->schema->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)) && - (node->schema != set->context_op)) { + } else if (set->context_op && (schema->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)) && (schema != set->context_op)) { return LY_EINVAL; } /* name check */ if (node_name) { - if ((set->ctx == LYD_CTX(node)) && (node->schema->name != node_name)) { + if ((set->ctx == LYD_CTX(node)) && (schema->name != node_name)) { return LY_ENOT; - } else if ((set->ctx != LYD_CTX(node)) && strcmp(node->schema->name, node_name)) { + } else if ((set->ctx != LYD_CTX(node)) && strcmp(schema->name, node_name)) { return LY_ENOT; } } /* when check, accept the context node because it should only be the path ".", we have checked the when is valid before */ - if (!(options & LYXP_IGNORE_WHEN) && lysc_has_when(node->schema) && !(node->flags & LYD_WHEN_TRUE) && + if (!(options & LYXP_IGNORE_WHEN) && lysc_has_when(schema) && !(node->flags & LYD_WHEN_TRUE) && (node != set->cur_node)) { return LY_EINCOMPLETE; } @@ -6144,7 +6203,7 @@ moveto_node_hash_child(struct lyxp_set *set, const struct lysc_node *scnode, con /* create specific data instance if needed */ if (scnode->nodetype == LYS_LIST) { - LY_CHECK_GOTO(ret = lyd_create_list(scnode, predicates, &inst), cleanup); + LY_CHECK_GOTO(ret = lyd_create_list(scnode, predicates, NULL, &inst), cleanup); } else if (scnode->nodetype == LYS_LEAFLIST) { LY_CHECK_GOTO(ret = lyd_create_term2(scnode, &predicates[0].value, &inst), cleanup); } @@ -6168,6 +6227,10 @@ moveto_node_hash_child(struct lyxp_set *set, const struct lysc_node *scnode, con } else { r = lyd_find_sibling_val(siblings, scnode, NULL, 0, &sub); } + if (r == LY_ENOTFOUND) { + /* may still be an opaque node */ + r = lyd_find_sibling_opaq_next(siblings, scnode->name, &sub); + } LY_CHECK_ERR_GOTO(r && (r != LY_ENOTFOUND), ret = r, cleanup); /* when check */ @@ -6655,7 +6718,7 @@ moveto_scnode(struct lyxp_set *set, const struct lys_module *moveto_mod, const c { ly_bool temp_ctx = 0; uint32_t getnext_opts, orig_used, i, mod_idx, idx; - const struct lys_module *mod; + const struct lys_module *mod = NULL; const struct lysc_node *iter; enum lyxp_node_type iter_type; @@ -6673,6 +6736,9 @@ moveto_scnode(struct lyxp_set *set, const struct lys_module *moveto_mod, const c if (options & LYXP_SCNODE_OUTPUT) { getnext_opts |= LYS_GETNEXT_OUTPUT; } + if (options & LYXP_SCNODE_SCHEMAMOUNT) { + getnext_opts |= LYS_GETNEXT_WITHSCHEMAMOUNT; + } orig_used = set->used; for (i = 0; i < orig_used; ++i) { @@ -6691,7 +6757,7 @@ moveto_scnode(struct lyxp_set *set, const struct lys_module *moveto_mod, const c } /* insert */ - LY_CHECK_RET(set_scnode_insert_node(set, iter, iter_type, axis, &idx)); + LY_CHECK_RET(lyxp_set_scnode_insert_node(set, iter, iter_type, axis, &idx)); /* we need to prevent these nodes from being considered in this moveto */ if ((idx < orig_used) && (idx > i)) { @@ -6704,7 +6770,7 @@ moveto_scnode(struct lyxp_set *set, const struct lys_module *moveto_mod, const c (set->val.scnodes[i].type == LYXP_NODE_ELEM) && !ly_nested_ext_schema(NULL, set->val.scnodes[i].scnode, moveto_mod->name, strlen(moveto_mod->name), LY_VALUE_JSON, NULL, ncname, strlen(ncname), &iter, NULL)) { /* there is a matching node from an extension, use it */ - LY_CHECK_RET(set_scnode_insert_node(set, iter, LYXP_NODE_ELEM, axis, &idx)); + LY_CHECK_RET(lyxp_set_scnode_insert_node(set, iter, LYXP_NODE_ELEM, axis, &idx)); if ((idx < orig_used) && (idx > i)) { set->val.scnodes[idx].in_ctx = LYXP_SET_SCNODE_ATOM_NEW_CTX; temp_ctx = 1; @@ -6848,7 +6914,7 @@ moveto_scnode_dfs(struct lyxp_set *set, const struct lysc_node *start, uint32_t goto skip_children; } } else { - LY_CHECK_RET(set_scnode_insert_node(set, elem, LYXP_NODE_ELEM, LYXP_AXIS_DESCENDANT, NULL)); + LY_CHECK_RET(lyxp_set_scnode_insert_node(set, elem, LYXP_NODE_ELEM, LYXP_AXIS_DESCENDANT, NULL)); } } else if (rc == LY_EINVAL) { goto skip_children; @@ -7459,7 +7525,11 @@ only_parse: *tok_idx = orig_exp; rc = eval_expr_select(exp, tok_idx, 0, &set2, options); - if (rc != LY_SUCCESS) { + if (!rc && set2.not_found) { + set->not_found = 1; + break; + } + if (rc) { lyxp_set_free_content(&set2); return rc; } @@ -7508,6 +7578,9 @@ only_parse: *tok_idx = orig_exp; rc = eval_expr_select(exp, tok_idx, 0, set, options); + if (!rc && set->not_found) { + break; + } LY_CHECK_RET(rc); set->val.scnodes[i].in_ctx = pred_in_ctx; @@ -7527,7 +7600,7 @@ only_parse: set_fill_set(&set2, set); rc = eval_expr_select(exp, tok_idx, 0, &set2, options); - if (rc != LY_SUCCESS) { + if (rc) { lyxp_set_free_content(&set2); return rc; } @@ -7702,14 +7775,13 @@ cleanup: * @param[in] ctx_scnode Found schema node as the context for the predicate. * @param[in] set Context set. * @param[out] predicates Parsed predicates. - * @param[out] pred_type Type of @p predicates. * @return LY_SUCCESS on success, * @return LY_ENOT if a predicate could not be compiled. * @return LY_ERR on any error. */ static LY_ERR eval_name_test_try_compile_predicates(const struct lyxp_expr *exp, uint32_t *tok_idx, const struct lysc_node *ctx_scnode, - const struct lyxp_set *set, struct ly_path_predicate **predicates, enum ly_path_pred_type *pred_type) + const struct lyxp_set *set, struct ly_path_predicate **predicates) { LY_ERR rc = LY_SUCCESS; uint32_t e_idx, val_start_idx, pred_idx = 0, temp_lo = 0, pred_len = 0, nested_pred; @@ -7848,7 +7920,7 @@ eval_name_test_try_compile_predicates(const struct lyxp_expr *exp, uint32_t *tok /* compile */ rc = ly_path_compile_predicate(set->ctx, set->cur_node ? set->cur_node->schema : NULL, set->cur_mod, ctx_scnode, exp2, - &pred_idx, LY_VALUE_JSON, NULL, predicates, pred_type); + &pred_idx, LY_VALUE_JSON, NULL, predicates); LY_CHECK_GOTO(rc, cleanup); /* success, the predicate must include all the needed information for hash-based search */ @@ -7881,7 +7953,7 @@ eval_name_test_with_predicate_get_scnode(const struct ly_ctx *ctx, const struct uint32_t name_len, const struct lys_module *moveto_mod, enum lyxp_node_type root_type, LY_VALUE_FORMAT format, const struct lysc_node **found) { - const struct lysc_node *scnode; + const struct lysc_node *scnode, *scnode2; const struct lys_module *mod; uint32_t idx = 0; @@ -7919,7 +7991,19 @@ continue_search: } /* search in children, do not repeat the same search */ - scnode = lys_find_child(node->schema, moveto_mod, name, name_len, 0, 0); + if (node->schema->nodetype & (LYS_RPC | LYS_ACTION)) { + /* make sure the node is unique, whether in input or output */ + scnode = lys_find_child(node->schema, moveto_mod, name, name_len, 0, 0); + scnode2 = lys_find_child(node->schema, moveto_mod, name, name_len, 0, LYS_GETNEXT_OUTPUT); + if (scnode && scnode2) { + /* conflict, do not use hashes */ + scnode = NULL; + } else if (scnode2) { + scnode = scnode2; + } + } else { + scnode = lys_find_child(node->schema, moveto_mod, name, name_len, 0, 0); + } } /* else skip redundant search */ /* additional context check */ @@ -7977,14 +8061,14 @@ eval_name_test_scnode_no_match_msg(struct lyxp_set *set, const struct lyxp_set_s if (ppath) { format = "Schema node \"%.*s\" for parent \"%s\" not found; in expr \"%.*s\" with context node \"%s\"."; if (options & LYXP_SCNODE_ERROR) { - LOGERR(set->ctx, LY_EVALID, format, ncname_len, ncname, ppath, (ncname - expr) + ncname_len, expr, path); + LOGERR(set->ctx, LY_ENOTFOUND, format, ncname_len, ncname, ppath, (ncname - expr) + ncname_len, expr, path); } else { LOGWRN(set->ctx, format, ncname_len, ncname, ppath, (ncname - expr) + ncname_len, expr, path); } } else { format = "Schema node \"%.*s\" not found; in expr \"%.*s\" with context node \"%s\"."; if (options & LYXP_SCNODE_ERROR) { - LOGERR(set->ctx, LY_EVALID, format, ncname_len, ncname, (ncname - expr) + ncname_len, expr, path); + LOGERR(set->ctx, LY_ENOTFOUND, format, ncname_len, ncname, (ncname - expr) + ncname_len, expr, path); } else { LOGWRN(set->ctx, format, ncname_len, ncname, (ncname - expr) + ncname_len, expr, path); } @@ -8018,7 +8102,6 @@ eval_name_test_with_predicate(const struct lyxp_expr *exp, uint32_t *tok_idx, en const struct lys_module *moveto_mod = NULL; const struct lysc_node *scnode = NULL; struct ly_path_predicate *predicates = NULL; - enum ly_path_pred_type pred_type = 0; int scnode_skip_pred = 0; LOGDBG(LY_LDGXPATH, "%-27s %s %s[%u]", __func__, (options & LYXP_SKIP_EXPR ? "skipped" : "parsed"), @@ -8060,7 +8143,7 @@ eval_name_test_with_predicate(const struct lyxp_expr *exp, uint32_t *tok_idx, en if (scnode && (scnode->nodetype & (LYS_LIST | LYS_LEAFLIST))) { /* try to create the predicates */ - if (eval_name_test_try_compile_predicates(exp, tok_idx, scnode, set, &predicates, &pred_type)) { + if (eval_name_test_try_compile_predicates(exp, tok_idx, scnode, set, &predicates)) { /* hashes cannot be used */ scnode = NULL; } @@ -8132,8 +8215,7 @@ moveto: if (options & LYXP_SCNODE_ERROR) { /* error */ - rc = LY_EVALID; - goto cleanup; + set->not_found = 1; } /* skip the predicates and the rest of this path to not generate invalid warnings */ @@ -8175,10 +8257,8 @@ cleanup: /* restore options */ options &= ~LYXP_SKIP_EXPR; } - if (!(options & LYXP_SKIP_EXPR)) { - lydict_remove(set->ctx, ncname_dict); - ly_path_predicates_free(set->ctx, pred_type, predicates); - } + lydict_remove(set->ctx, ncname_dict); + ly_path_predicates_free(set->ctx, predicates); return rc; } @@ -8350,8 +8430,9 @@ step: rc = eval_name_test_with_predicate(exp, tok_idx, axis, all_desc, set, options); if (rc == LY_ENOT) { assert(options & LYXP_SCNODE_ALL); - /* skip the rest of this path */ rc = LY_SUCCESS; + + /* skip the rest of this path */ scnode_skip_path = 1; options |= LYXP_SKIP_EXPR; } @@ -8600,8 +8681,9 @@ eval_function_call(const struct lyxp_expr *exp, uint32_t *tok_idx, struct lyxp_s rc = eval_expr_select(exp, tok_idx, 0, args[0], options); LY_CHECK_GOTO(rc, cleanup); + set->not_found = args[0]->not_found; } else { - rc = eval_expr_select(exp, tok_idx, 0, set, options | LYXP_SKIP_EXPR); + rc = eval_expr_select(exp, tok_idx, 0, set, options); LY_CHECK_GOTO(rc, cleanup); } } @@ -8623,8 +8705,11 @@ eval_function_call(const struct lyxp_expr *exp, uint32_t *tok_idx, struct lyxp_s rc = eval_expr_select(exp, tok_idx, 0, args[arg_count - 1], options); LY_CHECK_GOTO(rc, cleanup); + if (args[arg_count - 1]->not_found) { + set->not_found = 1; + } } else { - rc = eval_expr_select(exp, tok_idx, 0, set, options | LYXP_SKIP_EXPR); + rc = eval_expr_select(exp, tok_idx, 0, set, options); LY_CHECK_GOTO(rc, cleanup); } } @@ -8698,27 +8783,30 @@ eval_number(struct ly_ctx *ctx, const struct lyxp_expr *exp, uint32_t *tok_idx, } LY_ERR -lyxp_vars_find(struct lyxp_var *vars, const char *name, size_t name_len, struct lyxp_var **var) +lyxp_vars_find(const struct ly_ctx *ctx, const struct lyxp_var *vars, const char *name, size_t name_len, + struct lyxp_var **var) { - LY_ERR ret = LY_ENOTFOUND; LY_ARRAY_COUNT_TYPE u; - assert(vars && name); + assert(name); - name_len = name_len ? name_len : strlen(name); + if (!name_len) { + name_len = strlen(name); + } LY_ARRAY_FOR(vars, u) { if (!strncmp(vars[u].name, name, name_len)) { - ret = LY_SUCCESS; - break; + if (var) { + *var = (struct lyxp_var *)&vars[u]; + } + return LY_SUCCESS; } } - if (var && !ret) { - *var = &vars[u]; + if (ctx) { + LOGERR(ctx, LY_ENOTFOUND, "Variable \"%.*s\" not defined.", (int)name_len, name); } - - return ret; + return LY_ENOTFOUND; } /** @@ -8737,17 +8825,14 @@ eval_variable_reference(const struct lyxp_expr *exp, uint32_t *tok_idx, struct l LY_ERR ret; const char *name; struct lyxp_var *var; - const struct lyxp_var *vars; struct lyxp_expr *tokens = NULL; uint32_t token_index, name_len; - vars = set->vars; - /* find out the name and value of the variable */ name = &exp->expr[exp->tok_pos[*tok_idx]]; name_len = exp->tok_len[*tok_idx]; - ret = lyxp_vars_find((struct lyxp_var *)vars, name, name_len, &var); - LY_CHECK_ERR_RET(ret, LOGERR(set->ctx, ret, "XPath variable \"%.*s\" not defined.", (int)name_len, name), ret); + ret = lyxp_vars_find(set->ctx, set->vars, name, name_len, &var); + LY_CHECK_RET(ret); /* parse value */ ret = lyxp_expr_parse(set->ctx, var->value, 0, 1, &tokens); @@ -8917,8 +9002,9 @@ static LY_ERR eval_union_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t repeat, struct lyxp_set *set, uint32_t options) { LY_ERR rc = LY_SUCCESS; - struct lyxp_set orig_set, set2; uint32_t i; + struct lyxp_set orig_set, set2; + ly_bool found = 0; assert(repeat); @@ -8929,6 +9015,11 @@ eval_union_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t repeat, rc = eval_expr_select(exp, tok_idx, LYXP_EXPR_UNION, set, options); LY_CHECK_GOTO(rc, cleanup); + if (set->not_found) { + set->not_found = 0; + } else { + found = 1; + } /* ('|' PathExpr)* */ for (i = 0; i < repeat; ++i) { @@ -8946,6 +9037,9 @@ eval_union_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t repeat, set_fill_set(&set2, &orig_set); rc = eval_expr_select(exp, tok_idx, LYXP_EXPR_UNION, &set2, options); LY_CHECK_GOTO(rc, cleanup); + if (!set2.not_found) { + found = 1; + } /* eval */ if (options & LYXP_SCNODE_ALL) { @@ -8959,6 +9053,9 @@ eval_union_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t repeat, cleanup: lyxp_set_free_content(&orig_set); lyxp_set_free_content(&set2); + if (!found) { + set->not_found = 1; + } return rc; } @@ -9026,7 +9123,7 @@ static LY_ERR eval_multiplicative_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t repeat, struct lyxp_set *set, uint32_t options) { - LY_ERR rc; + LY_ERR rc = LY_SUCCESS; uint32_t i, this_op; struct lyxp_set orig_set, set2; @@ -9058,6 +9155,9 @@ eval_multiplicative_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_ set_fill_set(&set2, &orig_set); rc = eval_expr_select(exp, tok_idx, LYXP_EXPR_MULTIPLICATIVE, &set2, options); LY_CHECK_GOTO(rc, cleanup); + if (set2.not_found) { + set->not_found = 1; + } /* eval */ if (options & LYXP_SCNODE_ALL) { @@ -9093,7 +9193,7 @@ cleanup: static LY_ERR eval_additive_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t repeat, struct lyxp_set *set, uint32_t options) { - LY_ERR rc; + LY_ERR rc = LY_SUCCESS; uint32_t i, this_op; struct lyxp_set orig_set, set2; @@ -9125,6 +9225,9 @@ eval_additive_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t repe set_fill_set(&set2, &orig_set); rc = eval_expr_select(exp, tok_idx, LYXP_EXPR_ADDITIVE, &set2, options); LY_CHECK_GOTO(rc, cleanup); + if (set2.not_found) { + set->not_found = 1; + } /* eval */ if (options & LYXP_SCNODE_ALL) { @@ -9162,7 +9265,7 @@ cleanup: static LY_ERR eval_relational_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t repeat, struct lyxp_set *set, uint32_t options) { - LY_ERR rc; + LY_ERR rc = LY_SUCCESS; uint32_t i, this_op; struct lyxp_set orig_set, set2; @@ -9194,6 +9297,9 @@ eval_relational_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t re set_fill_set(&set2, &orig_set); rc = eval_expr_select(exp, tok_idx, LYXP_EXPR_RELATIONAL, &set2, options); LY_CHECK_GOTO(rc, cleanup); + if (set2.not_found) { + set->not_found = 1; + } /* eval */ if (options & LYXP_SCNODE_ALL) { @@ -9231,7 +9337,7 @@ cleanup: static LY_ERR eval_equality_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t repeat, struct lyxp_set *set, uint32_t options) { - LY_ERR rc; + LY_ERR rc = LY_SUCCESS; uint32_t i, this_op; struct lyxp_set orig_set, set2; @@ -9263,6 +9369,9 @@ eval_equality_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t repe set_fill_set(&set2, &orig_set); rc = eval_expr_select(exp, tok_idx, LYXP_EXPR_EQUALITY, &set2, options); LY_CHECK_GOTO(rc, cleanup); + if (set2.not_found) { + set->not_found = 1; + } /* eval */ if (options & LYXP_SCNODE_ALL) { @@ -9301,7 +9410,7 @@ cleanup: static LY_ERR eval_and_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t repeat, struct lyxp_set *set, uint32_t options) { - LY_ERR rc; + LY_ERR rc = LY_SUCCESS; struct lyxp_set orig_set, set2; uint32_t i; @@ -9315,11 +9424,13 @@ eval_and_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t repeat, s rc = eval_expr_select(exp, tok_idx, LYXP_EXPR_AND, set, options); LY_CHECK_GOTO(rc, cleanup); - /* cast to boolean, we know that will be the final result */ - if (!(options & LYXP_SKIP_EXPR) && (options & LYXP_SCNODE_ALL)) { - set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_NODE); - } else { - lyxp_set_cast(set, LYXP_SET_BOOLEAN); + if (!(options & LYXP_SKIP_EXPR)) { + if (options & LYXP_SCNODE_ALL) { + set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_NODE); + } else { + /* cast to boolean, we know that will be the final result */ + lyxp_set_cast(set, LYXP_SET_BOOLEAN); + } } /* ('and' EqualityExpr)* */ @@ -9339,6 +9450,9 @@ eval_and_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t repeat, s set_fill_set(&set2, &orig_set); rc = eval_expr_select(exp, tok_idx, LYXP_EXPR_AND, &set2, options); LY_CHECK_GOTO(rc, cleanup); + if (set2.not_found) { + set->not_found = 1; + } /* eval - just get boolean value actually */ if (set->type == LYXP_SET_SCNODE_SET) { @@ -9371,7 +9485,7 @@ cleanup: static LY_ERR eval_or_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t repeat, struct lyxp_set *set, uint32_t options) { - LY_ERR rc; + LY_ERR rc = LY_SUCCESS; struct lyxp_set orig_set, set2; uint32_t i; @@ -9385,11 +9499,13 @@ eval_or_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t repeat, st rc = eval_expr_select(exp, tok_idx, LYXP_EXPR_OR, set, options); LY_CHECK_GOTO(rc, cleanup); - /* cast to boolean, we know that will be the final result */ - if (!(options & LYXP_SKIP_EXPR) && (options & LYXP_SCNODE_ALL)) { - set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_NODE); - } else { - lyxp_set_cast(set, LYXP_SET_BOOLEAN); + if (!(options & LYXP_SKIP_EXPR)) { + if (options & LYXP_SCNODE_ALL) { + set_scnode_clear_ctx(set, LYXP_SET_SCNODE_ATOM_NODE); + } else { + /* cast to boolean, we know that will be the final result */ + lyxp_set_cast(set, LYXP_SET_BOOLEAN); + } } /* ('or' AndExpr)* */ @@ -9411,6 +9527,9 @@ eval_or_expr(const struct lyxp_expr *exp, uint32_t *tok_idx, uint32_t repeat, st * but it does not matter */ rc = eval_expr_select(exp, tok_idx, LYXP_EXPR_OR, &set2, options); LY_CHECK_GOTO(rc, cleanup); + if (set2.not_found) { + set->not_found = 1; + } /* eval - just get boolean value actually */ if (set->type == LYXP_SET_SCNODE_SET) { @@ -9523,7 +9642,7 @@ lyxp_get_root_type(const struct lyd_node *ctx_node, const struct lysc_node *ctx_ /* schema */ for (op = ctx_scnode; op && !(op->nodetype & (LYS_RPC | LYS_ACTION | LYS_NOTIF)); op = op->parent) {} - if (op || (options & LYXP_SCNODE)) { + if (op || !(options & LYXP_SCNODE_SCHEMA)) { /* general root that can access everything */ return LYXP_NODE_ROOT; } else if (!ctx_scnode || (ctx_scnode->flags & LYS_CONFIG_W)) { @@ -9597,7 +9716,10 @@ lyxp_eval(const struct ly_ctx *ctx, const struct lyxp_expr *exp, const struct ly /* evaluate */ rc = eval_expr_select(exp, &tok_idx, 0, set, options); - if (rc != LY_SUCCESS) { + if (!rc && set->not_found) { + rc = LY_ENOTFOUND; + } + if (rc) { lyxp_set_free_content(set); } @@ -9838,7 +9960,7 @@ lyxp_atomize(const struct ly_ctx *ctx, const struct lyxp_expr *exp, const struct LY_VALUE_FORMAT format, void *prefix_data, const struct lysc_node *cur_scnode, const struct lysc_node *ctx_scnode, struct lyxp_set *set, uint32_t options) { - LY_ERR ret; + LY_ERR rc; uint32_t tok_idx = 0; LY_CHECK_ARG_RET(ctx, ctx, exp, set, LY_EINVAL); @@ -9851,7 +9973,7 @@ lyxp_atomize(const struct ly_ctx *ctx, const struct lyxp_expr *exp, const struct memset(set, 0, sizeof *set); set->type = LYXP_SET_SCNODE_SET; set->root_type = lyxp_get_root_type(NULL, ctx_scnode, options); - LY_CHECK_RET(set_scnode_insert_node(set, ctx_scnode, ctx_scnode ? LYXP_NODE_ELEM : set->root_type, LYXP_AXIS_SELF, NULL)); + LY_CHECK_RET(lyxp_set_scnode_insert_node(set, ctx_scnode, ctx_scnode ? LYXP_NODE_ELEM : set->root_type, LYXP_AXIS_SELF, NULL)); set->val.scnodes[0].in_ctx = LYXP_SET_SCNODE_START; set->ctx = (struct ly_ctx *)ctx; @@ -9866,10 +9988,13 @@ lyxp_atomize(const struct ly_ctx *ctx, const struct lyxp_expr *exp, const struct LOG_LOCSET(set->cur_scnode, NULL, NULL, NULL); /* evaluate */ - ret = eval_expr_select(exp, &tok_idx, 0, set, options); + rc = eval_expr_select(exp, &tok_idx, 0, set, options); + if (!rc && set->not_found) { + rc = LY_ENOTFOUND; + } LOG_LOCBACK(set->cur_scnode ? 1 : 0, 0, 0, 0); - return ret; + return rc; } LIBYANG_API_DEF const char * |