xpath CHANGE root handling refactored

Simplified parameters of many functions.
diff --git a/src/xpath.c b/src/xpath.c
index d1e7bfb..9ba8338 100644
--- a/src/xpath.c
+++ b/src/xpath.c
@@ -34,8 +34,6 @@
 #include "tree_schema_internal.h"
 #include "plugins_types.h"
 
-static const struct lyd_node *moveto_get_root(const struct lyd_node *ctx_node, int options,
-                                              enum lyxp_node_type *root_type);
 static LY_ERR reparse_or_expr(struct ly_ctx *ctx, struct lyxp_expr *exp, uint16_t *exp_idx);
 static int set_scnode_insert_node(struct lyxp_set *set, const struct lysc_node *node, enum lyxp_node_type node_type);
 static LY_ERR eval_expr_select(struct lyxp_expr *exp, uint16_t *exp_idx, enum lyxp_expr_type etype, struct lyxp_set *set, int options);
@@ -497,14 +495,12 @@
  *        Context position aware.
  *
  * @param[in] set Set to cast.
- * @param[in] options XPath options.
  * @param[out] str Cast dynamically-allocated string.
  * @return LY_ERR
  */
 static LY_ERR
-cast_node_set_to_string(struct lyxp_set *set, int options, char **str)
+cast_node_set_to_string(struct lyxp_set *set, char **str)
 {
-    enum lyxp_node_type root_type;
     int dynamic;
 
     if ((set->val.nodes[0].type != LYXP_NODE_ATTR) && (set->val.nodes[0].node->flags & LYD_DUMMY)) {
@@ -512,15 +508,13 @@
         return LY_EVALID;
     }
 
-    moveto_get_root(set->ctx_node, options, &root_type);
-
     switch (set->val.nodes[0].type) {
     case LYXP_NODE_ROOT:
     case LYXP_NODE_ROOT_CONFIG:
-        return cast_string_elem(set->val.nodes[0].node, 1, root_type, str);
+        return cast_string_elem(set->val.nodes[0].node, 1, set->root_type, str);
     case LYXP_NODE_ELEM:
     case LYXP_NODE_TEXT:
-        return cast_string_elem(set->val.nodes[0].node, 0, root_type, str);
+        return cast_string_elem(set->val.nodes[0].node, 0, set->root_type, str);
     case LYXP_NODE_ATTR:
         *str = (char *)lyd_attr2str(set->val.attrs[0].attr, &dynamic);
         if (!dynamic) {
@@ -721,7 +715,12 @@
     set->type = LYXP_SET_EMPTY;
 }
 
-void
+/**
+ * @brief Free dynamically-allocated set.
+ *
+ * @param[in] set Set to free.
+ */
+static void
 lyxp_set_free(struct lyxp_set *set)
 {
     if (!set) {
@@ -1517,11 +1516,10 @@
  * @param[in] src Source set.
  * @param[in] type Target set type.
  * @param[in] src_idx Source set node index.
- * @param[in] options XPath options.
  * @return LY_ERR
  */
 static LY_ERR
-set_comp_cast(struct lyxp_set *trg, struct lyxp_set *src, enum lyxp_set_type type, uint32_t src_idx, int options)
+set_comp_cast(struct lyxp_set *trg, struct lyxp_set *src, enum lyxp_set_type type, uint32_t src_idx)
 {
     assert(src->type == LYXP_SET_NODE_SET);
 
@@ -1531,7 +1529,7 @@
     set_insert_node(trg, src->val.nodes[src_idx].node, src->val.nodes[src_idx].pos, src->val.nodes[src_idx].type, 0);
 
     /* cast target set appropriately */
-    return lyxp_set_cast(trg, type, options);
+    return lyxp_set_cast(trg, type);
 }
 
 #ifndef NDEBUG
@@ -1541,16 +1539,14 @@
  *        Context position aware. Unused in the 'Release' build target.
  *
  * @param[in] set Set to sort.
- * @param[in] options Xpath options.
  * @return How many times the whole set was traversed - 1 (if set was sorted, returns 0).
  */
 static int
-set_sort(struct lyxp_set *set, int options)
+set_sort(struct lyxp_set *set)
 {
     uint32_t i, j;
     int ret = 0, cmp, inverted, change;
     const struct lyd_node *root;
-    enum lyxp_node_type root_type;
     struct lyxp_set_node item;
     struct lyxp_set_hash_node hnode;
     uint64_t hash;
@@ -1559,11 +1555,12 @@
         return 0;
     }
 
-    /* get root */
-    root = moveto_get_root(set->ctx_node, options, &root_type);
+    /* find first top-level node to be used as anchor for positions */
+    for (root = set->ctx_node; root->parent; root = (const struct lyd_node *)root->parent);
+    for (; root->prev->next; root = root->prev);
 
     /* fill positions */
-    if (set_assign_pos(set, root, root_type)) {
+    if (set_assign_pos(set, root, set->root_type)) {
         return -1;
     }
 
@@ -1657,16 +1654,14 @@
  *
  * @param[in,out] trg Set to merge into. Duplicates are removed.
  * @param[in] src Set to be merged into @p trg. It is cast to #LYXP_SET_EMPTY on success.
- * @param[in] options XPath options.
  * @return LY_ERR
  */
 static LY_ERR
-set_sorted_merge(struct lyxp_set *trg, struct lyxp_set *src, int options)
+set_sorted_merge(struct lyxp_set *trg, struct lyxp_set *src)
 {
     uint32_t i, j, k, count, dup_count;
     int cmp;
     const struct lyd_node *root;
-    enum lyxp_node_type root_type;
 
     if (((trg->type != LYXP_SET_NODE_SET) && (trg->type != LYXP_SET_EMPTY))
             || ((src->type != LYXP_SET_NODE_SET) && (src->type != LYXP_SET_EMPTY))) {
@@ -1677,15 +1672,16 @@
         return LY_SUCCESS;
     } else if (trg->type == LYXP_SET_EMPTY) {
         set_fill_set(trg, src);
-        lyxp_set_cast(src, LYXP_SET_EMPTY, options);
+        lyxp_set_cast(src, LYXP_SET_EMPTY);
         return LY_SUCCESS;
     }
 
-    /* get root */
-    root = moveto_get_root(trg->ctx_node, options, &root_type);
+    /* find first top-level node to be used as anchor for positions */
+    for (root = trg->ctx_node; root->parent; root = (const struct lyd_node *)root->parent);
+    for (; root->prev->next; root = root->prev);
 
     /* fill positions */
-    if (set_assign_pos(trg, root, root_type) || set_assign_pos(src, root, root_type)) {
+    if (set_assign_pos(trg, root, trg->root_type) || set_assign_pos(src, root, src->root_type)) {
         return LY_EINT;
     }
 
@@ -1776,7 +1772,7 @@
     print_set_debug(trg);
 #endif
 
-    lyxp_set_cast(src, LYXP_SET_EMPTY, options);
+    lyxp_set_cast(src, LYXP_SET_EMPTY);
     return LY_SUCCESS;
 }
 
@@ -3245,7 +3241,7 @@
         LOGVAL(set->ctx, LY_VLOG_LYD, set->ctx_node, LY_VCODE_XP_INARGTYPE, 1, print_set_type(args[0]), "bit-is-set(node-set, string)");
         return LY_EVALID;
     }
-    rc = lyxp_set_cast(args[1], LYXP_SET_STRING, options);
+    rc = lyxp_set_cast(args[1], LYXP_SET_STRING);
     LY_CHECK_RET(rc);
 
     set_fill_boolean(set, 0);
@@ -3286,7 +3282,7 @@
         return LY_SUCCESS;
     }
 
-    rc = lyxp_set_cast(args[0], LYXP_SET_BOOLEAN, options);
+    rc = lyxp_set_cast(args[0], LYXP_SET_BOOLEAN);
     LY_CHECK_RET(rc);
     set_fill_set(set, args[0]);
 
@@ -3324,7 +3320,7 @@
         return rc;
     }
 
-    rc = lyxp_set_cast(args[0], LYXP_SET_NUMBER, options);
+    rc = lyxp_set_cast(args[0], LYXP_SET_NUMBER);
     LY_CHECK_RET(rc);
     if ((long long)args[0]->val.num != args[0]->val.num) {
         set_fill_number(set, ((long long)args[0]->val.num) + 1);
@@ -3372,7 +3368,7 @@
     }
 
     for (i = 0; i < arg_count; ++i) {
-        rc = lyxp_set_cast(args[i], LYXP_SET_STRING, options);
+        rc = lyxp_set_cast(args[i], LYXP_SET_STRING);
         if (rc != LY_SUCCESS) {
             free(str);
             return rc;
@@ -3385,7 +3381,7 @@
     }
 
     /* free, kind of */
-    lyxp_set_cast(set, LYXP_SET_EMPTY, options);
+    lyxp_set_cast(set, LYXP_SET_EMPTY);
     set->type = LYXP_SET_STRING;
     set->val.str = str;
 
@@ -3433,9 +3429,9 @@
         return rc;
     }
 
-    rc = lyxp_set_cast(args[0], LYXP_SET_STRING, options);
+    rc = lyxp_set_cast(args[0], LYXP_SET_STRING);
     LY_CHECK_RET(rc);
-    rc = lyxp_set_cast(args[1], LYXP_SET_STRING, options);
+    rc = lyxp_set_cast(args[1], LYXP_SET_STRING);
     LY_CHECK_RET(rc);
 
     if (strstr(args[0]->val.str, args[1]->val.str)) {
@@ -3509,7 +3505,7 @@
 
         set_scnode_insert_node(set, set->ctx_scnode, LYXP_NODE_ELEM);
     } else {
-        lyxp_set_cast(set, LYXP_SET_EMPTY, options);
+        lyxp_set_cast(set, LYXP_SET_EMPTY);
 
         /* position is filled later */
         set_insert_node(set, set->ctx_node, 0, LYXP_NODE_ELEM, 0);
@@ -3571,7 +3567,7 @@
         return LY_EVALID;
     }
 
-    lyxp_set_cast(set, LYXP_SET_EMPTY, options);
+    lyxp_set_cast(set, LYXP_SET_EMPTY);
     if (args[0]->type != LYXP_SET_EMPTY) {
         leaf = (struct lyd_node_term *)args[0]->val.nodes[0].node;
         sleaf = (struct lysc_node_leaf *)leaf->schema;
@@ -3661,7 +3657,7 @@
         LOGVAL(set->ctx, LY_VLOG_LYD, set->ctx_node, LY_VCODE_XP_INARGTYPE, 1, print_set_type(args[0]), "derived-from(node-set, string)");
         return LY_EVALID;
     }
-    rc = lyxp_set_cast(args[1], LYXP_SET_STRING, options);
+    rc = lyxp_set_cast(args[1], LYXP_SET_STRING);
     LY_CHECK_RET(rc);
 
     set_fill_boolean(set, 0);
@@ -3749,7 +3745,7 @@
         LOGVAL(set->ctx, LY_VLOG_LYD, set->ctx_node, LY_VCODE_XP_INARGTYPE, 1, print_set_type(args[0]), "derived-from-or-self(node-set, string)");
         return LY_EVALID;
     }
-    rc = lyxp_set_cast(args[1], LYXP_SET_STRING, options);
+    rc = lyxp_set_cast(args[1], LYXP_SET_STRING);
     LY_CHECK_RET(rc);
 
     set_fill_boolean(set, 0);
@@ -3872,11 +3868,11 @@
  * @return LY_ERR (LY_EINVAL for wrong arguments on schema)
  */
 static LY_ERR
-xpath_floor(struct lyxp_set **args, uint16_t UNUSED(arg_count), struct lyxp_set *set, int options)
+xpath_floor(struct lyxp_set **args, uint16_t UNUSED(arg_count), struct lyxp_set *set, int UNUSED(options))
 {
     LY_ERR rc;
 
-    rc = lyxp_set_cast(args[0], LYXP_SET_NUMBER, options);
+    rc = lyxp_set_cast(args[0], LYXP_SET_NUMBER);
     LY_CHECK_RET(rc);
     if (isfinite(args[0]->val.num)) {
         set_fill_number(set, (long long)args[0]->val.num);
@@ -3919,7 +3915,7 @@
         return rc;
     }
 
-    rc = lyxp_set_cast(args[0], LYXP_SET_STRING, options);
+    rc = lyxp_set_cast(args[0], LYXP_SET_STRING);
     LY_CHECK_RET(rc);
 
     if (set->type == LYXP_SET_EMPTY) {
@@ -4049,7 +4045,7 @@
         }
 
         /* we need the set sorted, it affects the result */
-        assert(!set_sort(args[0], options));
+        assert(!set_sort(args[0]));
 
         item = &args[0]->val.nodes[0];
     } else {
@@ -4063,7 +4059,7 @@
         }
 
         /* we need the set sorted, it affects the result */
-        assert(!set_sort(set, options));
+        assert(!set_sort(set));
 
         item = &set->val.nodes[0];
     }
@@ -4120,7 +4116,7 @@
         }
 
         /* we need the set sorted, it affects the result */
-        assert(!set_sort(args[0], options));
+        assert(!set_sort(args[0]));
 
         item = &args[0]->val.nodes[0];
     } else {
@@ -4134,7 +4130,7 @@
         }
 
         /* we need the set sorted, it affects the result */
-        assert(!set_sort(set, options));
+        assert(!set_sort(set));
 
         item = &set->val.nodes[0];
     }
@@ -4211,7 +4207,7 @@
         }
 
         /* we need the set sorted, it affects the result */
-        assert(!set_sort(args[0], options));
+        assert(!set_sort(args[0]));
 
         item = &args[0]->val.nodes[0];
     } else {
@@ -4225,7 +4221,7 @@
         }
 
         /* we need the set sorted, it affects the result */
-        assert(!set_sort(set, options));
+        assert(!set_sort(set));
 
         item = &set->val.nodes[0];
     }
@@ -4272,7 +4268,7 @@
     }
 
     if (set->type != LYXP_SET_NODE_SET) {
-        lyxp_set_cast(set, LYXP_SET_EMPTY, options);
+        lyxp_set_cast(set, LYXP_SET_EMPTY);
     }
     return LY_SUCCESS;
 }
@@ -4314,7 +4310,7 @@
     if (arg_count) {
         set_fill_set(set, args[0]);
     }
-    rc = lyxp_set_cast(set, LYXP_SET_STRING, options);
+    rc = lyxp_set_cast(set, LYXP_SET_STRING);
     LY_CHECK_RET(rc);
 
     /* is there any normalization necessary? */
@@ -4388,7 +4384,7 @@
         return LY_SUCCESS;
     }
 
-    lyxp_set_cast(args[0], LYXP_SET_BOOLEAN, options);
+    lyxp_set_cast(args[0], LYXP_SET_BOOLEAN);
     if (args[0]->val.bool) {
         set_fill_boolean(set, 0);
     } else {
@@ -4419,11 +4415,11 @@
     }
 
     if (arg_count) {
-        rc = lyxp_set_cast(args[0], LYXP_SET_NUMBER, options);
+        rc = lyxp_set_cast(args[0], LYXP_SET_NUMBER);
         LY_CHECK_RET(rc);
         set_fill_set(set, args[0]);
     } else {
-        rc = lyxp_set_cast(set, LYXP_SET_NUMBER, options);
+        rc = lyxp_set_cast(set, LYXP_SET_NUMBER);
         LY_CHECK_RET(rc);
     }
 
@@ -4508,9 +4504,9 @@
         return rc;
     }
 
-    rc = lyxp_set_cast(args[0], LYXP_SET_STRING, options);
+    rc = lyxp_set_cast(args[0], LYXP_SET_STRING);
     LY_CHECK_RET(rc);
-    rc = lyxp_set_cast(args[1], LYXP_SET_STRING, options);
+    rc = lyxp_set_cast(args[1], LYXP_SET_STRING);
     LY_CHECK_RET(rc);
 
     LY_ARRAY_NEW_RET(set->ctx, patterns, pattern, LY_EMEM);
@@ -4575,7 +4571,7 @@
         return rc;
     }
 
-    rc = lyxp_set_cast(args[0], LYXP_SET_NUMBER, options);
+    rc = lyxp_set_cast(args[0], LYXP_SET_NUMBER);
     LY_CHECK_RET(rc);
 
     /* cover only the cases where floor can't be used */
@@ -4632,9 +4628,9 @@
         return rc;
     }
 
-    rc = lyxp_set_cast(args[0], LYXP_SET_STRING, options);
+    rc = lyxp_set_cast(args[0], LYXP_SET_STRING);
     LY_CHECK_RET(rc);
-    rc = lyxp_set_cast(args[1], LYXP_SET_STRING, options);
+    rc = lyxp_set_cast(args[1], LYXP_SET_STRING);
     LY_CHECK_RET(rc);
 
     if (strncmp(args[0]->val.str, args[1]->val.str, strlen(args[1]->val.str))) {
@@ -4667,11 +4663,11 @@
     }
 
     if (arg_count) {
-        rc = lyxp_set_cast(args[0], LYXP_SET_STRING, options);
+        rc = lyxp_set_cast(args[0], LYXP_SET_STRING);
         LY_CHECK_RET(rc);
         set_fill_set(set, args[0]);
     } else {
-        rc = lyxp_set_cast(set, LYXP_SET_STRING, options);
+        rc = lyxp_set_cast(set, LYXP_SET_STRING);
         LY_CHECK_RET(rc);
     }
 
@@ -4718,11 +4714,11 @@
     }
 
     if (arg_count) {
-        rc = lyxp_set_cast(args[0], LYXP_SET_STRING, options);
+        rc = lyxp_set_cast(args[0], LYXP_SET_STRING);
         LY_CHECK_RET(rc);
         set_fill_number(set, strlen(args[0]->val.str));
     } else {
-        rc = lyxp_set_cast(set, LYXP_SET_STRING, options);
+        rc = lyxp_set_cast(set, LYXP_SET_STRING);
         LY_CHECK_RET(rc);
         set_fill_number(set, strlen(set->val.str));
     }
@@ -4786,7 +4782,7 @@
         return rc;
     }
 
-    rc = lyxp_set_cast(args[0], LYXP_SET_STRING, options);
+    rc = lyxp_set_cast(args[0], LYXP_SET_STRING);
     LY_CHECK_RET(rc);
 
     /* start */
@@ -4875,9 +4871,9 @@
         return rc;
     }
 
-    rc = lyxp_set_cast(args[0], LYXP_SET_STRING, options);
+    rc = lyxp_set_cast(args[0], LYXP_SET_STRING);
     LY_CHECK_RET(rc);
-    rc = lyxp_set_cast(args[1], LYXP_SET_STRING, options);
+    rc = lyxp_set_cast(args[1], LYXP_SET_STRING);
     LY_CHECK_RET(rc);
 
     ptr = strstr(args[0]->val.str, args[1]->val.str);
@@ -4932,9 +4928,9 @@
         return rc;
     }
 
-    rc = lyxp_set_cast(args[0], LYXP_SET_STRING, options);
+    rc = lyxp_set_cast(args[0], LYXP_SET_STRING);
     LY_CHECK_RET(rc);
-    rc = lyxp_set_cast(args[1], LYXP_SET_STRING, options);
+    rc = lyxp_set_cast(args[1], LYXP_SET_STRING);
     LY_CHECK_RET(rc);
 
     ptr = strstr(args[0]->val.str, args[1]->val.str);
@@ -5007,7 +5003,7 @@
     for (i = 0; i < args[0]->used; ++i) {
         set_item.val.nodes[0] = args[0]->val.nodes[i];
 
-        rc = cast_node_set_to_string(&set_item, options, &str);
+        rc = cast_node_set_to_string(&set_item, &str);
         LY_CHECK_RET(rc);
         num = cast_string_to_number(str);
         free(str);
@@ -5127,11 +5123,11 @@
         return rc;
     }
 
-    rc = lyxp_set_cast(args[0], LYXP_SET_STRING, options);
+    rc = lyxp_set_cast(args[0], LYXP_SET_STRING);
     LY_CHECK_RET(rc);
-    rc = lyxp_set_cast(args[1], LYXP_SET_STRING, options);
+    rc = lyxp_set_cast(args[1], LYXP_SET_STRING);
     LY_CHECK_RET(rc);
-    rc = lyxp_set_cast(args[2], LYXP_SET_STRING, options);
+    rc = lyxp_set_cast(args[2], LYXP_SET_STRING);
     LY_CHECK_RET(rc);
 
     new = malloc((strlen(args[0]->val.str) + 1) * sizeof(char));
@@ -5171,7 +5167,7 @@
     }
     new[new_used] = '\0';
 
-    lyxp_set_cast(set, LYXP_SET_EMPTY, options);
+    lyxp_set_cast(set, LYXP_SET_EMPTY);
     set->type = LYXP_SET_STRING;
     set->val.str = new;
 
@@ -5265,72 +5261,6 @@
 }
 
 /**
- * @brief Get the context root.
- *
- * @param[in] ctx_node Original context node.
- * @param[in] options XPath options.
- * @param[out] root_type Root type, differs only for when/must evaluation.
- * @return Context root.
- */
-static const struct lyd_node *
-moveto_get_root(const struct lyd_node *ctx_node, int options, enum lyxp_node_type *root_type)
-{
-    const struct lyd_node *root;
-
-    if (!ctx_node) {
-        return NULL;
-    }
-
-    if (!(options & LYXP_SCHEMA)) {
-        /* special kind of root that can access everything */
-        for (root = ctx_node; root->parent; root = (struct lyd_node *)root->parent);
-        for (; root->prev->next; root = root->prev);
-        *root_type = LYXP_NODE_ROOT;
-        return root;
-    }
-
-    if (ctx_node->schema->flags & LYS_CONFIG_W) {
-        *root_type = LYXP_NODE_ROOT_CONFIG;
-    } else {
-        *root_type = LYXP_NODE_ROOT;
-    }
-
-    for (root = ctx_node; root->parent; root = (struct lyd_node *)root->parent);
-    for (; root->prev->next; root = root->prev);
-
-    return root;
-}
-
-/**
- * @brief Get the schema context root.
- *
- * @param[in] ctx_scnode Original schema context node.
- * @param[in] options XPath options.
- * @param[out] root_type Root type, doffers only for when/must evaluation.
- * @return Context schema root.
- */
-static const struct lysc_node *
-moveto_scnode_get_root(const struct lysc_node *ctx_scnode, int options, enum lyxp_node_type *root_type)
-{
-    const struct lysc_node *root;
-
-    assert(ctx_scnode && root_type);
-
-    if (options & LYXP_SCNODE) {
-        /* general root that can access everything */
-        *root_type = LYXP_NODE_ROOT;
-    } else if (ctx_scnode->flags & LYS_CONFIG_W) {
-        *root_type = LYXP_NODE_ROOT_CONFIG;
-    } else {
-        *root_type = LYXP_NODE_ROOT;
-    }
-
-    root = lys_getnext(NULL, NULL, ctx_scnode->module->compiled, LYS_GETNEXT_NOSTATECHECK);
-
-    return root;
-}
-
-/**
  * @brief Move context @p set to the root. Handles absolute path.
  *        Result is LYXP_SET_NODE_SET.
  *
@@ -5340,24 +5270,16 @@
 static void
 moveto_root(struct lyxp_set *set, int options)
 {
-    const struct lysc_node *scroot;
-    const struct lyd_node *root;
-    enum lyxp_node_type root_type;
-
     if (!set) {
         return;
     }
 
     if (options & LYXP_SCNODE_ALL) {
-        scroot = moveto_scnode_get_root(set->ctx_scnode, options, &root_type);
         set_scnode_clear_ctx(set);
-        set_scnode_insert_node(set, scroot, root_type);
+        set_scnode_insert_node(set, NULL, set->root_type);
     } else {
-        root = moveto_get_root(set->ctx_node, options, &root_type);
-        lyxp_set_cast(set, LYXP_SET_EMPTY, options);
-        if (root) {
-            set_insert_node(set, root, 0, root_type, 0);
-        }
+        lyxp_set_cast(set, LYXP_SET_EMPTY);
+        set_insert_node(set, NULL, 0, set->root_type, 0);
     }
 }
 
@@ -5457,14 +5379,13 @@
  * @return LY_ERR (LY_EINCOMPLETE on unresolved when)
  */
 static LY_ERR
-moveto_node(struct lyxp_set *set, const char *qname, uint16_t qname_len, int options)
+moveto_node(struct lyxp_set *set, const char *qname, uint16_t qname_len)
 {
     uint32_t i;
     int replaced;
     const char *name_dict = NULL; /* optimization - so we can do (==) instead (!strncmp(...)) in moveto_node_check() */
     const struct lys_module *moveto_mod;
     const struct lyd_node *sub;
-    enum lyxp_node_type root_type;
     LY_ERR rc;
 
     if (!set || (set->type == LYXP_SET_EMPTY)) {
@@ -5476,7 +5397,6 @@
         return LY_EVALID;
     }
 
-    moveto_get_root(set->ctx_node, options, &root_type);
     rc = moveto_resolve_model(&qname, &qname_len, set, &moveto_mod);
     LY_CHECK_RET(rc);
 
@@ -5487,30 +5407,11 @@
         replaced = 0;
 
         if ((set->val.nodes[i].type == LYXP_NODE_ROOT_CONFIG) || (set->val.nodes[i].type == LYXP_NODE_ROOT)) {
-            if (set->trees) {
-                /* search in all the trees */
-                LY_ARRAY_FOR(set->trees, i) {
-                    for (sub = set->trees[i]; sub; sub = sub->next) {
-                        rc = moveto_node_check(sub, root_type, name_dict, moveto_mod);
-                        if (rc == LY_SUCCESS) {
-                            /* pos filled later */
-                            if (!replaced) {
-                                set_replace_node(set, sub, 0, LYXP_NODE_ELEM, i);
-                                replaced = 1;
-                            } else {
-                                set_insert_node(set, sub, 0, LYXP_NODE_ELEM, i);
-                            }
-                            ++i;
-                        } else if (rc == LY_EINCOMPLETE) {
-                            lydict_remove(set->ctx, name_dict);
-                            return rc;
-                        }
-                    }
-                }
-            } else {
-                /* use just the context node */
-                for (sub = set->val.nodes[i].node; sub; sub = sub->next) {
-                    rc = moveto_node_check(sub, root_type, name_dict, moveto_mod);
+            assert(!set->val.nodes[i].node);
+            /* search in all the trees */
+            LY_ARRAY_FOR(set->trees, i) {
+                for (sub = set->trees[i]; sub; sub = sub->next) {
+                    rc = moveto_node_check(sub, set->root_type, name_dict, moveto_mod);
                     if (rc == LY_SUCCESS) {
                         /* pos filled later */
                         if (!replaced) {
@@ -5532,7 +5433,7 @@
                 && !(set->val.nodes[i].node->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA))) {
 
             for (sub = lyd_node_children(set->val.nodes[i].node); sub; sub = sub->next) {
-                rc = moveto_node_check(sub, root_type, name_dict, moveto_mod);
+                rc = moveto_node_check(sub, set->root_type, name_dict, moveto_mod);
                 if (rc == LY_SUCCESS) {
                     if (!replaced) {
                         set_replace_node(set, sub, 0, LYXP_NODE_ELEM, i);
@@ -5576,7 +5477,6 @@
     const char *name_dict = NULL; /* optimization - so we can do (==) instead (!strncmp(...)) in moveto_node_check() */
     const struct lys_module *moveto_mod;
     const struct lysc_node *sub, *start_parent;
-    enum lyxp_node_type root_type;
     LY_ERR rc;
 
     if (!set || (set->type == LYXP_SET_EMPTY)) {
@@ -5588,7 +5488,6 @@
         return LY_EVALID;
     }
 
-    moveto_scnode_get_root(set->ctx_scnode, options, &root_type);
     rc = moveto_resolve_model(&qname, &qname_len, set, &moveto_mod);
     LY_CHECK_RET(rc);
 
@@ -5611,7 +5510,7 @@
             while (moveto_mod || (moveto_mod = (struct lys_module *)ly_ctx_get_module_iter(set->ctx, &mod_idx))) {
                 sub = NULL;
                 while ((sub = lys_getnext(sub, NULL, moveto_mod->compiled, LYS_GETNEXT_NOSTATECHECK))) {
-                    if (!moveto_scnode_check(sub, root_type, name_dict, moveto_mod, options)) {
+                    if (!moveto_scnode_check(sub, set->root_type, name_dict, moveto_mod, options)) {
                         idx = set_scnode_insert_node(set, sub, LYXP_NODE_ELEM);
                         /* we need to prevent these nodes from being considered in this moveto */
                         if ((idx < orig_used) && (idx > i)) {
@@ -5633,7 +5532,7 @@
         } else if (!(start_parent->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA))) {
             sub = NULL;
             while ((sub = lys_getnext(sub, start_parent, NULL, LYS_GETNEXT_NOSTATECHECK))) {
-                if (!moveto_scnode_check(sub, root_type, name_dict, (moveto_mod ? moveto_mod : set->local_mod), options)) {
+                if (!moveto_scnode_check(sub, set->root_type, name_dict, (moveto_mod ? moveto_mod : set->local_mod), options)) {
                     idx = set_scnode_insert_node(set, sub, LYXP_NODE_ELEM);
                     if ((idx < orig_used) && (idx > i)) {
                         set->val.scnodes[idx].in_ctx = 2;
@@ -5665,17 +5564,15 @@
  * @param[in] set Set to use.
  * @param[in] qname Qualified node name to move to.
  * @param[in] qname_len Length of @p qname.
- * @param[in] options XPath options.
  * @return LY_ERR (LY_EINCOMPLETE on unresolved when)
  */
 static LY_ERR
-moveto_node_alldesc(struct lyxp_set *set, const char *qname, uint16_t qname_len, int options)
+moveto_node_alldesc(struct lyxp_set *set, const char *qname, uint16_t qname_len)
 {
     uint32_t i;
     const char *name_dict = NULL; /* optimization - so we can do (==) instead (!strncmp(...)) in moveto_node_check() */
     const struct lyd_node *next, *elem, *start;
     const struct lys_module *moveto_mod;
-    enum lyxp_node_type root_type;
     struct lyxp_set ret_set;
     LY_ERR rc;
 
@@ -5688,12 +5585,11 @@
         return LY_EVALID;
     }
 
-    moveto_get_root(set->ctx_node, options, &root_type);
     rc = moveto_resolve_model(&qname, &qname_len, set, &moveto_mod);
     LY_CHECK_RET(rc);
 
     /* replace the original nodes (and throws away all text and attr nodes, root is replaced by a child) */
-    rc = moveto_node(set, "*", 1, options);
+    rc = moveto_node(set, "*", 1);
     LY_CHECK_RET(rc);
 
     /* name */
@@ -5706,7 +5602,7 @@
         /* TREE DFS */
         start = set->val.nodes[i].node;
         for (elem = next = start; elem; elem = next) {
-            rc = moveto_node_check(elem, root_type, name_dict, moveto_mod);
+            rc = moveto_node_check(elem, set->root_type, name_dict, moveto_mod);
             if (!rc) {
                 /* add matching node into result set */
                 set_insert_node(&ret_set, elem, 0, LYXP_NODE_ELEM, ret_set.used);
@@ -5777,7 +5673,6 @@
     int i, orig_used, idx;
     const struct lysc_node *next, *elem, *start;
     const struct lys_module *moveto_mod;
-    enum lyxp_node_type root_type;
     LY_ERR rc;
 
     if (!set || (set->type == LYXP_SET_EMPTY)) {
@@ -5789,7 +5684,6 @@
         return LY_EVALID;
     }
 
-    moveto_scnode_get_root(set->ctx_scnode, options, &root_type);
     rc = moveto_resolve_model(&qname, &qname_len, set, &moveto_mod);
     LY_CHECK_RET(rc);
 
@@ -5808,7 +5702,7 @@
                 goto next_iter;
             }
 
-            rc = moveto_scnode_check(elem, root_type, qname, moveto_mod, options);
+            rc = moveto_scnode_check(elem, set->root_type, qname, moveto_mod, options);
             if (!rc) {
                 if ((idx = set_scnode_dup_node_check(set, elem, LYXP_NODE_ELEM, i)) > -1) {
                     set->val.scnodes[idx].in_ctx = 1;
@@ -5864,11 +5758,10 @@
  * @param[in,out] set Set to use.
  * @param[in] qname Qualified node name to move to.
  * @param[in] qname_len Length of @p qname.
- * @param[in] options XPath options.
  * @return LY_ERR
  */
 static LY_ERR
-moveto_attr(struct lyxp_set *set, const char *qname, uint16_t qname_len, int UNUSED(options))
+moveto_attr(struct lyxp_set *set, const char *qname, uint16_t qname_len)
 {
     uint32_t i;
     int replaced, all = 0;
@@ -5935,11 +5828,10 @@
  *
  * @param[in,out] set1 Set to use for the result.
  * @param[in] set2 Set that is copied to @p set1.
- * @param[in] options XPath options.
  * @return LY_ERR
  */
 static LY_ERR
-moveto_union(struct lyxp_set *set1, struct lyxp_set *set2, int options)
+moveto_union(struct lyxp_set *set1, struct lyxp_set *set2)
 {
     LY_ERR rc;
 
@@ -5962,14 +5854,14 @@
     }
 
     /* we assume sets are sorted */
-    assert(!set_sort(set1, options) && !set_sort(set2, options));
+    assert(!set_sort(set1) && !set_sort(set2));
 
     /* sort, remove duplicates */
-    rc = set_sorted_merge(set1, set2, options);
+    rc = set_sorted_merge(set1, set2);
     LY_CHECK_RET(rc);
 
     /* final set must be sorted */
-    assert(!set_sort(set1, options));
+    assert(!set_sort(set1));
 
     return LY_SUCCESS;
 }
@@ -5982,11 +5874,10 @@
  * @param[in,out] set Set to use.
  * @param[in] qname Qualified node name to move to.
  * @param[in] qname_len Length of @p qname.
- * @param[in] options XPath options.
  * @return LY_ERR (LY_EINCOMPLETE on unresolved when)
  */
 static int
-moveto_attr_alldesc(struct lyxp_set *set, const char *qname, uint16_t qname_len, int options)
+moveto_attr_alldesc(struct lyxp_set *set, const char *qname, uint16_t qname_len)
 {
     uint32_t i;
     int replaced, all = 0;
@@ -6012,13 +5903,13 @@
     /* copy the context */
     set_all_desc = set_copy(set);
     /* get all descendant nodes (the original context nodes are removed) */
-    rc = moveto_node_alldesc(set_all_desc, "*", 1, options);
+    rc = moveto_node_alldesc(set_all_desc, "*", 1);
     if (rc != LY_SUCCESS) {
         lyxp_set_free(set_all_desc);
         return rc;
     }
     /* prepend the original context nodes */
-    rc =  moveto_union(set, set_all_desc, options);
+    rc = moveto_union(set, set_all_desc);
     if (rc != LY_SUCCESS) {
         lyxp_set_free(set_all_desc);
         return rc;
@@ -6074,14 +5965,12 @@
  * @param[in] parent_type Node type of @p parent.
  * @param[in,out] to_set Set to use.
  * @param[in] dup_check_set Set for checking duplicities.
- * @param[in] root_type Node type of root.
  * @param[in] options XPath options.
  * @return LY_ERR (LY_EINCOMPLETE on unresolved when)
  */
 static LY_ERR
 moveto_self_add_children_r(const struct lyd_node *parent, uint32_t parent_pos, enum lyxp_node_type parent_type,
-                           struct lyxp_set *to_set, const struct lyxp_set *dup_check_set, enum lyxp_node_type root_type,
-                           int options)
+                           struct lyxp_set *to_set, const struct lyxp_set *dup_check_set, int options)
 {
     const struct lyd_node *sub;
     LY_ERR rc;
@@ -6096,7 +5985,7 @@
             /* skip anydata/anyxml and dummy nodes */
             if (!(parent->schema->nodetype & LYS_ANYDATA) && !(parent->flags & LYD_DUMMY)) {
                 /* also add all the children of this node, recursively */
-                rc = moveto_self_add_children_r(parent, 0, LYXP_NODE_ELEM, to_set, dup_check_set, root_type, options);
+                rc = moveto_self_add_children_r(parent, 0, LYXP_NODE_ELEM, to_set, dup_check_set, options);
                 LY_CHECK_RET(rc);
             }
         }
@@ -6106,7 +5995,7 @@
         if (!(parent->schema->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_ANYDATA))) {
             for (sub = lyd_node_children(parent); sub; sub = sub->next) {
                 /* context check */
-                if ((root_type == LYXP_NODE_ROOT_CONFIG) && (sub->schema->flags & LYS_CONFIG_R)) {
+                if ((to_set->root_type == LYXP_NODE_ROOT_CONFIG) && (sub->schema->flags & LYS_CONFIG_R)) {
                     continue;
                 }
 
@@ -6124,7 +6013,7 @@
                     }
 
                     /* also add all the children of this node, recursively */
-                    rc = moveto_self_add_children_r(sub, 0, LYXP_NODE_ELEM, to_set, dup_check_set, root_type, options);
+                    rc = moveto_self_add_children_r(sub, 0, LYXP_NODE_ELEM, to_set, dup_check_set, options);
                     LY_CHECK_RET(rc);
                 }
             }
@@ -6156,7 +6045,6 @@
 moveto_self(struct lyxp_set *set, int all_desc, int options)
 {
     uint32_t i;
-    enum lyxp_node_type root_type;
     struct lyxp_set ret_set;
     LY_ERR rc;
 
@@ -6174,8 +6062,6 @@
         return LY_SUCCESS;
     }
 
-    moveto_get_root(set->ctx_node, options, &root_type);
-
     /* add all the children, they get added recursively */
     set_init(&ret_set, set);
     for (i = 0; i < set->used; ++i) {
@@ -6194,7 +6080,7 @@
 
         /* add all the children */
         rc = moveto_self_add_children_r(set->val.nodes[i].node, set->val.nodes[i].pos, set->val.nodes[i].type, &ret_set,
-                                        set, root_type, options);
+                                        set, options);
         if (rc != LY_SUCCESS) {
             set_free_content(&ret_set);
             return rc;
@@ -6224,7 +6110,6 @@
 {
     const struct lysc_node *sub;
     uint32_t i;
-    enum lyxp_node_type root_type;
 
     if (!set || (set->type == LYXP_SET_EMPTY)) {
         return LY_SUCCESS;
@@ -6240,8 +6125,6 @@
         return LY_SUCCESS;
     }
 
-    moveto_scnode_get_root(set->ctx_scnode, options, &root_type);
-
     /* add all the children, they get added recursively */
     for (i = 0; i < set->used; ++i) {
         if (set->val.scnodes[i].in_ctx != 1) {
@@ -6264,7 +6147,7 @@
                 }
 
                 /* context check */
-                if ((root_type == LYXP_NODE_ROOT_CONFIG) && (sub->flags & LYS_CONFIG_R)) {
+                if ((set->root_type == LYXP_NODE_ROOT_CONFIG) && (sub->flags & LYS_CONFIG_R)) {
                     continue;
                 }
 
@@ -6292,8 +6175,7 @@
     LY_ERR rc;
     uint32_t i;
     struct lyd_node *node, *new_node;
-    const struct lyd_node *root;
-    enum lyxp_node_type root_type, new_type;
+    enum lyxp_node_type new_type;
 
     if (!set || (set->type == LYXP_SET_EMPTY)) {
         return LY_SUCCESS;
@@ -6310,8 +6192,6 @@
         LY_CHECK_RET(rc);
     }
 
-    root = moveto_get_root(set->ctx_node, options, &root_type);
-
     for (i = 0; i < set->used; ++i) {
         node = set->val.nodes[i].node;
 
@@ -6336,36 +6216,14 @@
         }*/
 
         /* node already there can also be the root */
-        if (root == node) {
-            if (options && (set->ctx_node->schema->flags & LYS_CONFIG_W)) {
-                new_type = LYXP_NODE_ROOT_CONFIG;
-            } else {
-                new_type = LYXP_NODE_ROOT;
-            }
-            new_node = node;
-
-        /* node has no parent */
-        } else if (!new_node) {
-            if (options && (set->ctx_node->schema->flags & LYS_CONFIG_W)) {
-                new_type = LYXP_NODE_ROOT_CONFIG;
-            } else {
-                new_type = LYXP_NODE_ROOT;
-            }
-#ifndef NDEBUG
-            for (; node->prev->next; node = node->prev);
-            if (node != root) {
-                LOGINT(set->ctx);
-            }
-#endif
-            new_node = (struct lyd_node *)root;
+        if (!new_node) {
+            new_type = set->root_type;
 
         /* node has a standard parent (it can equal the root, it's not the root yet since they are fake) */
         } else {
             new_type = LYXP_NODE_ELEM;
         }
 
-        assert((new_type == LYXP_NODE_ELEM) || ((new_type == root_type) && (new_node == root)));
-
         if (set_dup_node_check(set, new_node, new_type, -1)) {
             set_remove_node_null(set, i);
         } else {
@@ -6374,7 +6232,7 @@
     }
 
     set_remove_nodes_null(set);
-    assert(!set_sort(set, options) && !set_sorted_dup_node_clean(set));
+    assert(!set_sort(set) && !set_sorted_dup_node_clean(set));
 
     return LY_SUCCESS;
 }
@@ -6392,8 +6250,8 @@
 moveto_scnode_parent(struct lyxp_set *set, int all_desc, int options)
 {
     int idx, i, orig_used, temp_ctx = 0;
-    const struct lysc_node *root, *node, *new_node;
-    enum lyxp_node_type root_type, new_type;
+    const struct lysc_node *node, *new_node;
+    enum lyxp_node_type new_type;
     LY_ERR rc;
 
     if (!set || (set->type == LYXP_SET_EMPTY)) {
@@ -6411,8 +6269,6 @@
         LY_CHECK_RET(rc);
     }
 
-    root = moveto_scnode_get_root(set->ctx_scnode, options, &root_type);
-
     orig_used = set->used;
     for (i = 0; i < orig_used; ++i) {
         if (set->val.scnodes[i].in_ctx != 1) {
@@ -6431,37 +6287,15 @@
             continue;
         }
 
-        /* node already there can also be the root */
-        if (root == node) {
-            if ((options & LYXP_SCNODE_SCHEMA) && (set->ctx_scnode->flags & LYS_CONFIG_W)) {
-                new_type = LYXP_NODE_ROOT_CONFIG;
-            } else {
-                new_type = LYXP_NODE_ROOT;
-            }
-            new_node = node;
-
         /* node has no parent */
-        } else if (!new_node) {
-            if ((options & LYXP_SCNODE_SCHEMA) && (set->ctx_scnode->flags & LYS_CONFIG_W)) {
-                new_type = LYXP_NODE_ROOT_CONFIG;
-            } else {
-                new_type = LYXP_NODE_ROOT;
-            }
-#ifndef NDEBUG
-            node = lys_getnext(NULL, NULL, node->module->compiled, LYS_GETNEXT_NOSTATECHECK);
-            if (node != root) {
-                LOGINT(set->ctx);
-            }
-#endif
-            new_node = root;
+        if (!new_node) {
+            new_type = set->root_type;
 
         /* node has a standard parent (it can equal the root, it's not the root yet since they are fake) */
         } else {
             new_type = LYXP_NODE_ELEM;
         }
 
-        assert((new_type == LYXP_NODE_ELEM) || ((new_type == root_type) && (new_node == root)));
-
         idx = set_scnode_insert_node(set, new_node, new_type);
         if ((idx < orig_used) && (idx > i)) {
             set->val.scnodes[idx].in_ctx = 2;
@@ -6543,13 +6377,13 @@
             for (i = 0; i < set1->used; ++i) {
                 switch (set2->type) {
                 case LYXP_SET_NUMBER:
-                    rc = set_comp_cast(&iter1, set1, LYXP_SET_NUMBER, i, options);
+                    rc = set_comp_cast(&iter1, set1, LYXP_SET_NUMBER, i);
                     break;
                 case LYXP_SET_BOOLEAN:
-                    rc = set_comp_cast(&iter1, set1, LYXP_SET_BOOLEAN, i, options);
+                    rc = set_comp_cast(&iter1, set1, LYXP_SET_BOOLEAN, i);
                     break;
                 default:
-                    rc = set_comp_cast(&iter1, set1, LYXP_SET_STRING, i, options);
+                    rc = set_comp_cast(&iter1, set1, LYXP_SET_STRING, i);
                     break;
                 }
                 LY_CHECK_RET(rc);
@@ -6570,13 +6404,13 @@
             for (i = 0; i < set2->used; ++i) {
                 switch (set1->type) {
                     case LYXP_SET_NUMBER:
-                        rc = set_comp_cast(&iter2, set2, LYXP_SET_NUMBER, i, options);
+                        rc = set_comp_cast(&iter2, set2, LYXP_SET_NUMBER, i);
                         break;
                     case LYXP_SET_BOOLEAN:
-                        rc = set_comp_cast(&iter2, set2, LYXP_SET_BOOLEAN, i, options);
+                        rc = set_comp_cast(&iter2, set2, LYXP_SET_BOOLEAN, i);
                         break;
                     default:
-                        rc = set_comp_cast(&iter2, set2, LYXP_SET_STRING, i, options);
+                        rc = set_comp_cast(&iter2, set2, LYXP_SET_STRING, i);
                         break;
                 }
                 LY_CHECK_RET(rc);
@@ -6607,18 +6441,18 @@
     /* first convert properly */
     if ((op[0] == '=') || (op[0] == '!')) {
         if ((set1->type == LYXP_SET_BOOLEAN) || (set2->type == LYXP_SET_BOOLEAN)) {
-            lyxp_set_cast(set1, LYXP_SET_BOOLEAN, options);
-            lyxp_set_cast(set2, LYXP_SET_BOOLEAN, options);
+            lyxp_set_cast(set1, LYXP_SET_BOOLEAN);
+            lyxp_set_cast(set2, LYXP_SET_BOOLEAN);
         } else if ((set1->type == LYXP_SET_NUMBER) || (set2->type == LYXP_SET_NUMBER)) {
-            rc = lyxp_set_cast(set1, LYXP_SET_NUMBER, options);
+            rc = lyxp_set_cast(set1, LYXP_SET_NUMBER);
             LY_CHECK_RET(rc);
-            rc = lyxp_set_cast(set2, LYXP_SET_NUMBER, options);
+            rc = lyxp_set_cast(set2, LYXP_SET_NUMBER);
             LY_CHECK_RET(rc);
         } /* else we have 2 strings */
     } else {
-        rc = lyxp_set_cast(set1, LYXP_SET_NUMBER, options);
+        rc = lyxp_set_cast(set1, LYXP_SET_NUMBER);
         LY_CHECK_RET(rc);
-        rc = lyxp_set_cast(set2, LYXP_SET_NUMBER, options);
+        rc = lyxp_set_cast(set2, LYXP_SET_NUMBER);
         LY_CHECK_RET(rc);
     }
 
@@ -6677,17 +6511,16 @@
  * @param[in,out] set1 Set to use for the result.
  * @param[in] set2 Set acting as the second operand for @p op.
  * @param[in] op Operator to process.
- * @param[in] options XPath options.
  * @return LY_ERR
  */
 static LY_ERR
-moveto_op_math(struct lyxp_set *set1, struct lyxp_set *set2, const char *op, int options)
+moveto_op_math(struct lyxp_set *set1, struct lyxp_set *set2, const char *op)
 {
     LY_ERR rc;
 
     /* unary '-' */
     if (!set2 && (op[0] == '-')) {
-        rc = lyxp_set_cast(set1, LYXP_SET_NUMBER, options);
+        rc = lyxp_set_cast(set1, LYXP_SET_NUMBER);
         LY_CHECK_RET(rc);
         set1->val.num *= -1;
         lyxp_set_free(set2);
@@ -6696,9 +6529,9 @@
 
     assert(set1 && set2);
 
-    rc = lyxp_set_cast(set1, LYXP_SET_NUMBER, options);
+    rc = lyxp_set_cast(set1, LYXP_SET_NUMBER);
     LY_CHECK_RET(rc);
-    rc = lyxp_set_cast(set2, LYXP_SET_NUMBER, options);
+    rc = lyxp_set_cast(set2, LYXP_SET_NUMBER);
     LY_CHECK_RET(rc);
 
     switch (op[0]) {
@@ -6791,9 +6624,9 @@
                 rc = LY_SUCCESS;
             } else {
                 if (all_desc) {
-                    rc = moveto_attr_alldesc(set, &exp->expr[exp->tok_pos[*exp_idx]], exp->tok_len[*exp_idx], options);
+                    rc = moveto_attr_alldesc(set, &exp->expr[exp->tok_pos[*exp_idx]], exp->tok_len[*exp_idx]);
                 } else {
-                    rc = moveto_attr(set, &exp->expr[exp->tok_pos[*exp_idx]], exp->tok_len[*exp_idx], options);
+                    rc = moveto_attr(set, &exp->expr[exp->tok_pos[*exp_idx]], exp->tok_len[*exp_idx]);
                 }
             }
         } else {
@@ -6801,13 +6634,13 @@
                 if (set && (options & LYXP_SCNODE_ALL)) {
                     rc = moveto_scnode_alldesc(set, &exp->expr[exp->tok_pos[*exp_idx]], exp->tok_len[*exp_idx], options);
                 } else {
-                    rc = moveto_node_alldesc(set, &exp->expr[exp->tok_pos[*exp_idx]], exp->tok_len[*exp_idx], options);
+                    rc = moveto_node_alldesc(set, &exp->expr[exp->tok_pos[*exp_idx]], exp->tok_len[*exp_idx]);
                 }
             } else {
                 if (set && (options & LYXP_SCNODE_ALL)) {
                     rc = moveto_scnode(set, &exp->expr[exp->tok_pos[*exp_idx]], exp->tok_len[*exp_idx], options);
                 } else {
-                    rc = moveto_node(set, &exp->expr[exp->tok_pos[*exp_idx]], exp->tok_len[*exp_idx], options);
+                    rc = moveto_node(set, &exp->expr[exp->tok_pos[*exp_idx]], exp->tok_len[*exp_idx]);
                 }
             }
 
@@ -6907,7 +6740,7 @@
         LY_CHECK_RET(rc);
     } else if (set->type == LYXP_SET_NODE_SET) {
         /* we (possibly) need the set sorted, it can affect the result (if the predicate result is a number) */
-        assert(!set_sort(set, options));
+        assert(!set_sort(set));
 
         /* empty set, nothing to evaluate */
         if (!set->used) {
@@ -6937,7 +6770,7 @@
 
             rc = eval_expr_select(exp, exp_idx, 0, &set2, options);
             if (rc != LY_SUCCESS) {
-                lyxp_set_cast(&set2, LYXP_SET_EMPTY, options);
+                lyxp_set_cast(&set2, LYXP_SET_EMPTY);
                 return rc;
             }
 
@@ -6949,7 +6782,7 @@
                     set2.val.num = 0;
                 }
             }
-            lyxp_set_cast(&set2, LYXP_SET_BOOLEAN, options);
+            lyxp_set_cast(&set2, LYXP_SET_BOOLEAN);
 
             /* predicate satisfied or not? */
             if (!set2.val.bool) {
@@ -7005,15 +6838,15 @@
 
         rc = eval_expr_select(exp, exp_idx, 0, &set2, options);
         if (rc != LY_SUCCESS) {
-            lyxp_set_cast(&set2, LYXP_SET_EMPTY, options);
+            lyxp_set_cast(&set2, LYXP_SET_EMPTY);
             return rc;
         }
 
-        lyxp_set_cast(&set2, LYXP_SET_BOOLEAN, options);
+        lyxp_set_cast(&set2, LYXP_SET_BOOLEAN);
         if (!set2.val.bool) {
-            lyxp_set_cast(set, LYXP_SET_EMPTY, options);
+            lyxp_set_cast(set, LYXP_SET_EMPTY);
         }
-        lyxp_set_cast(&set2, LYXP_SET_EMPTY, options);
+        lyxp_set_cast(&set2, LYXP_SET_EMPTY);
     }
 
     /* ']' */
@@ -7630,14 +7463,14 @@
         if (options & LYXP_SCNODE_ALL) {
             set_scnode_merge(set, &set2);
         } else {
-            rc = moveto_union(set, &set2, options);
+            rc = moveto_union(set, &set2);
             LY_CHECK_GOTO(rc, cleanup);
         }
     }
 
 cleanup:
-    lyxp_set_cast(&orig_set, LYXP_SET_EMPTY, options);
-    lyxp_set_cast(&set2, LYXP_SET_EMPTY, options);
+    lyxp_set_cast(&orig_set, LYXP_SET_EMPTY);
+    lyxp_set_cast(&set2, LYXP_SET_EMPTY);
     return rc;
 }
 
@@ -7678,7 +7511,7 @@
         if (options & LYXP_SCNODE_ALL) {
             warn_operands(set->ctx, set, NULL, 1, exp->expr, exp->tok_pos[this_op]);
         } else {
-            rc = moveto_op_math(set, NULL, &exp->expr[exp->tok_pos[this_op]], options);
+            rc = moveto_op_math(set, NULL, &exp->expr[exp->tok_pos[this_op]]);
             LY_CHECK_RET(rc);
         }
     }
@@ -7744,14 +7577,14 @@
             set_scnode_merge(set, &set2);
             set_scnode_clear_ctx(set);
         } else {
-            rc = moveto_op_math(set, &set2, &exp->expr[exp->tok_pos[this_op]], options);
+            rc = moveto_op_math(set, &set2, &exp->expr[exp->tok_pos[this_op]]);
             LY_CHECK_GOTO(rc, cleanup);
         }
     }
 
 cleanup:
-    lyxp_set_cast(&orig_set, LYXP_SET_EMPTY, options);
-    lyxp_set_cast(&set2, LYXP_SET_EMPTY, options);
+    lyxp_set_cast(&orig_set, LYXP_SET_EMPTY);
+    lyxp_set_cast(&set2, LYXP_SET_EMPTY);
     return rc;
 }
 
@@ -7812,14 +7645,14 @@
             set_scnode_merge(set, &set2);
             set_scnode_clear_ctx(set);
         } else {
-            rc = moveto_op_math(set, &set2, &exp->expr[exp->tok_pos[this_op]], options);
+            rc = moveto_op_math(set, &set2, &exp->expr[exp->tok_pos[this_op]]);
             LY_CHECK_GOTO(rc, cleanup);
         }
     }
 
 cleanup:
-    lyxp_set_cast(&orig_set, LYXP_SET_EMPTY, options);
-    lyxp_set_cast(&set2, LYXP_SET_EMPTY, options);
+    lyxp_set_cast(&orig_set, LYXP_SET_EMPTY);
+    lyxp_set_cast(&set2, LYXP_SET_EMPTY);
     return rc;
 }
 
@@ -7888,8 +7721,8 @@
     }
 
 cleanup:
-    lyxp_set_cast(&orig_set, LYXP_SET_EMPTY, options);
-    lyxp_set_cast(&set2, LYXP_SET_EMPTY, options);
+    lyxp_set_cast(&orig_set, LYXP_SET_EMPTY);
+    lyxp_set_cast(&set2, LYXP_SET_EMPTY);
     return rc;
 }
 
@@ -7974,8 +7807,8 @@
     }
 
 cleanup:
-    lyxp_set_cast(&orig_set, LYXP_SET_EMPTY, options);
-    lyxp_set_cast(&set2, LYXP_SET_EMPTY, options);
+    lyxp_set_cast(&orig_set, LYXP_SET_EMPTY);
+    lyxp_set_cast(&set2, LYXP_SET_EMPTY);
     return rc;
 }
 
@@ -8012,7 +7845,7 @@
     if (set && (options & LYXP_SCNODE_ALL)) {
         set_scnode_clear_ctx(set);
     } else {
-        lyxp_set_cast(set, LYXP_SET_BOOLEAN, options);
+        lyxp_set_cast(set, LYXP_SET_BOOLEAN);
     }
 
     /* ('and' EqualityExpr)* */
@@ -8038,14 +7871,14 @@
             set_scnode_clear_ctx(&set2);
             set_scnode_merge(set, &set2);
         } else {
-            lyxp_set_cast(&set2, LYXP_SET_BOOLEAN, options);
+            lyxp_set_cast(&set2, LYXP_SET_BOOLEAN);
             set_fill_set(set, &set2);
         }
     }
 
 cleanup:
-    lyxp_set_cast(&orig_set, LYXP_SET_EMPTY, options);
-    lyxp_set_cast(&set2, LYXP_SET_EMPTY, options);
+    lyxp_set_cast(&orig_set, LYXP_SET_EMPTY);
+    lyxp_set_cast(&set2, LYXP_SET_EMPTY);
     return rc;
 }
 
@@ -8082,7 +7915,7 @@
     if (set && (options & LYXP_SCNODE_ALL)) {
         set_scnode_clear_ctx(set);
     } else {
-        lyxp_set_cast(set, LYXP_SET_BOOLEAN, options);
+        lyxp_set_cast(set, LYXP_SET_BOOLEAN);
     }
 
     /* ('or' AndExpr)* */
@@ -8110,14 +7943,14 @@
             set_scnode_clear_ctx(&set2);
             set_scnode_merge(set, &set2);
         } else {
-            lyxp_set_cast(&set2, LYXP_SET_BOOLEAN, options);
+            lyxp_set_cast(&set2, LYXP_SET_BOOLEAN);
             set_fill_set(set, &set2);
         }
     }
 
 cleanup:
-    lyxp_set_cast(&orig_set, LYXP_SET_EMPTY, options);
-    lyxp_set_cast(&set2, LYXP_SET_EMPTY, options);
+    lyxp_set_cast(&orig_set, LYXP_SET_EMPTY);
+    lyxp_set_cast(&set2, LYXP_SET_EMPTY);
     return rc;
 }
 
@@ -8191,6 +8024,37 @@
     return rc;
 }
 
+/**
+ * @brief Get root type.
+ *
+ * @param[in] ctx_node Context node.
+ * @param[in] ctx_scnode Schema context node.
+ * @param[in] options XPath options.
+ * @return Root type.
+ */
+static enum lyxp_node_type
+lyxp_get_root_type(const struct lyd_node *ctx_node, const struct lysc_node *ctx_scnode, int options)
+{
+    if (options & LYXP_SCNODE_ALL) {
+        if (options & LYXP_SCNODE) {
+            /* general root that can access everything */
+            return LYXP_NODE_ROOT;
+        } else if (!ctx_scnode || (ctx_scnode->flags & LYS_CONFIG_W)) {
+            /* root context node can access only config data (because we said so, it is unspecified) */
+            return LYXP_NODE_ROOT_CONFIG;
+        } else {
+            return LYXP_NODE_ROOT;
+        }
+    }
+
+    if (!ctx_node || (ctx_node->schema->flags & LYS_CONFIG_W)) {
+        /* root context node can access only config data (because we said so, it is unspecified) */
+        return LYXP_NODE_ROOT_CONFIG;
+    }
+
+    return LYXP_NODE_ROOT;
+}
+
 LY_ERR
 lyxp_eval(const char *expr, LYD_FORMAT format, const struct lys_module *local_mod, const struct lyd_node *ctx_node,
           enum lyxp_node_type ctx_node_type, const struct lyd_node **trees, struct lyxp_set *set, int options)
@@ -8200,7 +8064,7 @@
     uint16_t exp_idx = 0;
     LY_ERR rc;
 
-    LY_CHECK_ARG_RET(NULL, !expr || !local_mod || !ctx_node || !set, LY_EINVAL);
+    LY_CHECK_ARG_RET(NULL, expr, local_mod, set, LY_EINVAL);
 
     ctx = local_mod->ctx;
 
@@ -8216,6 +8080,7 @@
     set_insert_node(set, (struct lyd_node *)ctx_node, 0, ctx_node_type, options);
     set->ctx = ctx;
     set->ctx_node = ctx_node;
+    set->root_type = lyxp_get_root_type(ctx_node, NULL, options);
     set->local_mod = local_mod;
     set->trees = trees;
     set->format = format;
@@ -8223,7 +8088,7 @@
     /* evaluate */
     rc = eval_expr_select(exp, &exp_idx, 0, set, options);
     if (rc != LY_SUCCESS) {
-        lyxp_set_cast(set, LYXP_SET_EMPTY, options);
+        lyxp_set_cast(set, LYXP_SET_EMPTY);
     }
 
     lyxp_expr_free(ctx, exp);
@@ -8329,7 +8194,7 @@
 #endif
 
 LY_ERR
-lyxp_set_cast(struct lyxp_set *set, enum lyxp_set_type target, int options)
+lyxp_set_cast(struct lyxp_set *set, enum lyxp_set_type target)
 {
     long double num;
     char *str;
@@ -8388,9 +8253,9 @@
             assert(set->used);
 
             /* we need the set sorted, it affects the result */
-            assert(!set_sort(set, options));
+            assert(!set_sort(set));
 
-            rc = cast_node_set_to_string(set, options, &str);
+            rc = cast_node_set_to_string(set, &str);
             LY_CHECK_RET(rc);
             set_free_content(set);
             set->val.str = str;
@@ -8476,7 +8341,7 @@
     struct ly_ctx *ctx;
     uint16_t exp_idx = 0;
 
-    LY_CHECK_ARG_RET(NULL, !exp || !local_mod || !ctx_scnode || !set, LY_EINVAL);
+    LY_CHECK_ARG_RET(NULL, exp, local_mod, set, LY_EINVAL);
 
     ctx = local_mod->ctx;
 
@@ -8487,157 +8352,10 @@
     set_scnode_insert_node(set, ctx_scnode, ctx_scnode_type);
     set->ctx = ctx;
     set->ctx_scnode = ctx_scnode;
+    set->root_type = lyxp_get_root_type(NULL, ctx_scnode, options);
     set->local_mod = local_mod;
     set->format = format;
 
     /* evaluate */
     return eval_expr_select(exp, &exp_idx, 0, set, options);
 }
-
-LY_ERR
-lyxp_node_atomize(const struct lysc_node *node, struct lyxp_set *set, int set_ext_dep_flags)
-{
-    struct ly_ctx *ctx;
-    struct lysc_ctx cctx;
-    struct lysc_node *parent, *elem;
-    struct lyxp_set tmp_set;
-    uint32_t i, j;
-    int opts;
-    struct lysc_when **when = NULL;
-    struct lysc_must *musts = NULL;
-    LY_ERR rc;
-
-    ctx = node->module->ctx;
-
-    memset(&tmp_set, 0, sizeof tmp_set);
-    memset(set, 0, sizeof *set);
-    set->ctx = ctx;
-
-    /* check if we will be traversing RPC output */
-    for (parent = (struct lysc_node *)node; parent && (parent->nodetype != LYS_ACTION); parent = parent->parent);
-    if (parent && (node->flags & LYS_CONFIG_R)) {
-        opts = LYXP_SCNODE_OUTPUT;
-    } else {
-        opts = LYXP_SCNODE_SCHEMA;
-    }
-
-    switch (node->nodetype) {
-    case LYS_CONTAINER:
-        when = ((struct lysc_node_container *)node)->when;
-        musts = ((struct lysc_node_container *)node)->musts;
-        break;
-    case LYS_CHOICE:
-        when = ((struct lysc_node_choice *)node)->when;
-        break;
-    case LYS_LEAF:
-        when = ((struct lysc_node_leaf *)node)->when;
-        musts = ((struct lysc_node_leaf *)node)->musts;
-        break;
-    case LYS_LEAFLIST:
-        when = ((struct lysc_node_leaflist *)node)->when;
-        musts = ((struct lysc_node_leaflist *)node)->musts;
-        break;
-    case LYS_LIST:
-        when = ((struct lysc_node_list *)node)->when;
-        musts = ((struct lysc_node_list *)node)->musts;
-        break;
-    case LYS_ANYXML:
-    case LYS_ANYDATA:
-        when = ((struct lysc_node_anydata *)node)->when;
-        musts = ((struct lysc_node_anydata *)node)->musts;
-        break;
-    case LYS_CASE:
-        when = ((struct lysc_node_case *)node)->when;
-        break;
-    case LYS_NOTIF:
-        musts = ((struct lysc_notif *)node)->musts;
-        break;
-    default:
-        /* nothing to check */
-        break;
-    }
-
-    if (set_ext_dep_flags) {
-        /* find operation if in one, used later */
-        for (parent = (struct lysc_node *)node;
-             parent && !(parent->nodetype & (LYS_ACTION | LYS_NOTIF));
-             parent = parent->parent);
-    }
-
-    /* check "when" */
-    LY_ARRAY_FOR(when, i) {
-        rc = lyxp_atomize(when[i]->cond, LYD_UNKNOWN, when[i]->module, when[i]->context, LYXP_NODE_ELEM, &tmp_set, opts);
-        if (rc != LY_SUCCESS) {
-            free(tmp_set.val.scnodes);
-            LOGVAL(ctx, LY_VLOG_LYS, when[i]->context, LYVE_SEMANTICS, "Invalid when condition \"%s\".", when[i]->cond->expr);
-            goto error;
-        } else {
-            if (set_ext_dep_flags) {
-                for (j = 0; j < tmp_set.used; ++j) {
-                    /* skip roots'n'stuff */
-                    if (tmp_set.val.scnodes[j].type == LYXP_NODE_ELEM) {
-                        /* XPath expression cannot reference "lower" status than the node that has the definition */
-                        cctx.ctx = ctx;
-                        lysc_path((struct lysc_node *)node, LYSC_PATH_LOG, cctx.path, LYSC_CTX_BUFSIZE);
-                        rc = lysc_check_status(&cctx, node->flags, node->module, node->name, tmp_set.val.scnodes[j].scnode->flags,
-                                tmp_set.val.scnodes[j].scnode->module, tmp_set.val.scnodes[j].scnode->name);
-                        LY_CHECK_GOTO(rc, error);
-
-                        if (parent) {
-                            for (elem = tmp_set.val.scnodes[j].scnode; elem && (elem != parent); elem = elem->parent);
-                            if (!elem) {
-                                /* not in node's RPC or notification subtree, set the correct dep flag */
-                                when[i]->flags |= LYS_XPATH_DEP;
-                                ((struct lysc_node *)node)->flags |= LYS_XPATH_DEP;
-                            }
-                        }
-                    }
-                }
-            }
-            set_scnode_merge(set, &tmp_set);
-            memset(&tmp_set, 0, sizeof tmp_set);
-        }
-    }
-
-    /* check "must" */
-    LY_ARRAY_FOR(musts, i) {
-        rc = lyxp_atomize(musts[i].cond, LYD_UNKNOWN, musts[i].module, node, LYXP_NODE_ELEM, &tmp_set, opts);
-        if (rc != LY_SUCCESS) {
-            free(tmp_set.val.scnodes);
-            LOGVAL(ctx, LY_VLOG_LYS, node, LYVE_SEMANTICS, "Invalid must restriction \"%s\".", musts[i].cond->expr);
-            goto error;
-        } else {
-            if (set_ext_dep_flags) {
-                for (j = 0; j < tmp_set.used; ++j) {
-                    /* skip roots'n'stuff */
-                    if (tmp_set.val.scnodes[j].type == LYXP_NODE_ELEM) {
-                        /* XPath expression cannot reference "lower" status than the node that has the definition */
-                        cctx.ctx = ctx;
-                        lysc_path((struct lysc_node *)node, LYSC_PATH_LOG, cctx.path, LYSC_CTX_BUFSIZE);
-                        rc = lysc_check_status(&cctx, node->flags, node->module, node->name, tmp_set.val.scnodes[j].scnode->flags,
-                                tmp_set.val.scnodes[j].scnode->module, tmp_set.val.scnodes[j].scnode->name);
-                        LY_CHECK_GOTO(rc, error);
-
-                        if (parent) {
-                            for (elem = tmp_set.val.scnodes[j].scnode; elem && (elem != parent); elem = elem->parent);
-                            if (!elem) {
-                                /* not in node's RPC or notification subtree, set the correct dep flag */
-                                musts[i].flags |= LYS_XPATH_DEP;
-                                ((struct lysc_node *)node)->flags |= LYS_XPATH_DEP;
-                            }
-                        }
-                    }
-                }
-            }
-            set_scnode_merge(set, &tmp_set);
-            memset(&tmp_set, 0, sizeof tmp_set);
-        }
-    }
-
-    return LY_SUCCESS;
-
-error:
-    free(set->val.scnodes);
-    memset(set, 0, sizeof *set);
-    return rc;
-}
diff --git a/src/xpath.h b/src/xpath.h
index c0d12bb..d72ff6b 100644
--- a/src/xpath.h
+++ b/src/xpath.h
@@ -245,6 +245,7 @@
         const struct lyd_node *ctx_node;
         const struct lysc_node *ctx_scnode;
     };
+    enum lyxp_node_type root_type;
     const struct lys_module *local_mod;
     const struct lyd_node **trees;
     LYD_FORMAT format;
@@ -309,7 +310,7 @@
  * which the node has.
  *
  * @param[in] node Node to examine.
- * @param[in,out] set Resulting set of atoms merged from all the expressions.
+ * @param[in,out] set Optional resulting set of atoms merged from all the expressions.
  * Will be cleared before use.
  * @param[in] set_ext_dep_flags Whether to set #LYS_XPATH_DEP for conditions that require data subtree
  * and also for the node itself, if it has any such condition.
@@ -323,17 +324,9 @@
  *
  * @param[in] set Set to cast.
  * @param[in] target Target type to cast \p set into.
- * @param[in] options Whether to apply some evaluation restrictions.
  * @return LY_ERR
  */
-LY_ERR lyxp_set_cast(struct lyxp_set *set, enum lyxp_set_type target, int options);
-
-/**
- * @brief Free contents of an XPath @p set.
- *
- * @param[in] set Set to free.
- */
-void lyxp_set_free(struct lyxp_set *set);
+LY_ERR lyxp_set_cast(struct lyxp_set *set, enum lyxp_set_type target);
 
 /**
  * @brief Parse an XPath expression into a structure of tokens.