plugins ext FEATURE initial schema-mount support

Only for XML data for now. Includes lots of other
changes needed to support this extension.
diff --git a/src/context.c b/src/context.c
index 3d79958..15043d3 100644
--- a/src/context.c
+++ b/src/context.c
@@ -319,7 +319,7 @@
 }
 
 static LY_ERR
-ly_ctx_new_yl_legacy(struct ly_ctx *ctx, struct lyd_node *yltree)
+ly_ctx_new_yl_legacy(struct ly_ctx *ctx, const struct lyd_node *yltree)
 {
     struct lyd_node *module, *node;
     struct ly_set *set;
@@ -329,11 +329,12 @@
     ly_bool imported = 0;
     const struct lys_module *mod;
     LY_ERR ret = LY_SUCCESS;
+    uint32_t i, j;
 
     LY_CHECK_RET(ret = lyd_find_xpath(yltree, "/ietf-yang-library:yang-library/modules-state/module", &set));
 
     /* process the data tree */
-    for (uint32_t i = 0; i < set->count; ++i) {
+    for (i = 0; i < set->count; ++i) {
         module = set->dnodes[i];
 
         /* initiate */
@@ -365,8 +366,8 @@
         LY_CHECK_ERR_GOTO(!feature_arr, ret = LY_EMEM, cleanup);
 
         /* Parse features into an array of strings */
-        for (uint32_t u = 0; u < features.count; u++) {
-            feature_arr[u] = lyd_get_value(features.dnodes[u]);
+        for (j = 0; j < features.count; ++j) {
+            feature_arr[j] = lyd_get_value(features.dnodes[j]);
         }
         feature_arr[features.count] = NULL;
         ly_set_clean(&features, free);
@@ -387,32 +388,72 @@
     return ret;
 }
 
-static LY_ERR
-ly_ctx_new_yl_common(const char *search_dir, const char *input, LYD_FORMAT format, int options,
-        LY_ERR (*parser_func)(const struct ly_ctx *, const char *, LYD_FORMAT, uint32_t, uint32_t, struct lyd_node **),
-        struct ly_ctx **ctx)
+LIBYANG_API_DEF LY_ERR
+ly_ctx_new_ylpath(const char *search_dir, const char *path, LYD_FORMAT format, int options, struct ly_ctx **ctx)
+{
+    LY_ERR ret = LY_SUCCESS;
+    struct ly_ctx *ctx_yl = NULL;
+    struct lyd_node *data_yl = NULL;
+
+    LY_CHECK_ARG_RET(NULL, path, ctx, LY_EINVAL);
+
+    /* create a seperate context for the data */
+    LY_CHECK_GOTO(ret = ly_ctx_new(search_dir, 0, &ctx_yl), cleanup);
+
+    /* parse yang library data tree */
+    LY_CHECK_GOTO(ret = lyd_parse_data_path(ctx_yl, path, format, 0, LYD_VALIDATE_PRESENT, &data_yl), cleanup);
+
+    /* create the new context */
+    ret = ly_ctx_new_yldata(search_dir, data_yl, options, ctx);
+
+cleanup:
+    lyd_free_all(data_yl);
+    ly_ctx_destroy(ctx_yl);
+    return ret;
+}
+
+LIBYANG_API_DEF LY_ERR
+ly_ctx_new_ylmem(const char *search_dir, const char *data, LYD_FORMAT format, int options, struct ly_ctx **ctx)
+{
+    LY_ERR ret = LY_SUCCESS;
+    struct ly_ctx *ctx_yl = NULL;
+    struct lyd_node *data_yl = NULL;
+
+    LY_CHECK_ARG_RET(NULL, data, ctx, LY_EINVAL);
+
+    /* create a seperate context for the data */
+    LY_CHECK_GOTO(ret = ly_ctx_new(search_dir, 0, &ctx_yl), cleanup);
+
+    /* parse yang library data tree */
+    LY_CHECK_GOTO(ret = lyd_parse_data_mem(ctx_yl, data, format, 0, LYD_VALIDATE_PRESENT, &data_yl), cleanup);
+
+    /* create the new context */
+    ret = ly_ctx_new_yldata(search_dir, data_yl, options, ctx);
+
+cleanup:
+    lyd_free_all(data_yl);
+    ly_ctx_destroy(ctx_yl);
+    return ret;
+}
+
+LIBYANG_API_DEF LY_ERR
+ly_ctx_new_yldata(const char *search_dir, const struct lyd_node *tree, int options, struct ly_ctx **ctx)
 {
     const char *name = NULL, *revision = NULL;
     struct lyd_node *module, *node;
-    struct lyd_node *yltree = NULL;
     struct ly_set *set = NULL;
     const char **feature_arr = NULL;
     struct ly_set features = {0};
     LY_ERR ret = LY_SUCCESS;
     const struct lys_module *mod;
-    struct ly_ctx *ctx_yl = NULL, *ctx_new = NULL;
+    struct ly_ctx *ctx_new = NULL;
     ly_bool no_expl_compile = 0;
+    uint32_t i, j;
 
-    /* create a seperate context in case it is LY_CTX_NO_YANGLIBRARY since it needs it for parsing */
-    if (options & LY_CTX_NO_YANGLIBRARY) {
-        LY_CHECK_GOTO(ret = ly_ctx_new(search_dir, 0, &ctx_yl), cleanup);
-        LY_CHECK_GOTO(ret = ly_ctx_new(search_dir, options, &ctx_new), cleanup);
-    } else {
-        LY_CHECK_GOTO(ret = ly_ctx_new(search_dir, options, &ctx_new), cleanup);
-    }
+    LY_CHECK_ARG_RET(NULL, tree, ctx, LY_EINVAL);
 
-    /* parse yang library data tree */
-    LY_CHECK_GOTO(ret = parser_func(ctx_yl ? ctx_yl : ctx_new, input, format, 0, LYD_VALIDATE_PRESENT, &yltree), cleanup);
+    /* create a new context */
+    LY_CHECK_GOTO(ret = ly_ctx_new(search_dir, options, &ctx_new), cleanup);
 
     /* redundant to compile modules one-by-one */
     if (!(options & LY_CTX_EXPLICIT_COMPILE)) {
@@ -420,20 +461,20 @@
         no_expl_compile = 1;
     }
 
-    LY_CHECK_GOTO(ret = lyd_find_xpath(yltree, "/ietf-yang-library:yang-library/module-set[1]/module", &set), cleanup);
+    LY_CHECK_GOTO(ret = lyd_find_xpath(tree, "/ietf-yang-library:yang-library/module-set[1]/module", &set), cleanup);
     if (set->count == 0) {
         /* perhaps a legacy data tree? */
-        LY_CHECK_GOTO(ret = ly_ctx_new_yl_legacy(ctx_new, yltree), cleanup);
+        LY_CHECK_GOTO(ret = ly_ctx_new_yl_legacy(ctx_new, tree), cleanup);
     } else {
         /* process the data tree */
-        for (uint32_t i = 0; i < set->count; ++i) {
+        for (i = 0; i < set->count; ++i) {
             module = set->dnodes[i];
 
             /* initiate */
             name = NULL;
             revision = NULL;
 
-            /* Iterate over data */
+            /* iterate over data */
             LY_LIST_FOR(lyd_child(module), node) {
                 if (!strcmp(node->schema->name, "name")) {
                     name = lyd_get_value(node);
@@ -447,9 +488,9 @@
             feature_arr = malloc((features.count + 1) * sizeof *feature_arr);
             LY_CHECK_ERR_GOTO(!feature_arr, ret = LY_EMEM, cleanup);
 
-            /* Parse features into an array of strings */
-            for (uint32_t u = 0; u < features.count; u++) {
-                feature_arr[u] = lyd_get_value(features.dnodes[u]);
+            /* parse features into an array of strings */
+            for (j = 0; j < features.count; ++j) {
+                feature_arr[j] = lyd_get_value(features.dnodes[j]);
             }
             feature_arr[features.count] = NULL;
             ly_set_clean(&features, NULL);
@@ -466,10 +507,6 @@
         }
     }
 
-    /* free data because their context may be recompiled */
-    lyd_free_all(yltree);
-    yltree = NULL;
-
     /* compile */
     LY_CHECK_GOTO(ret = ly_ctx_compile(ctx_new), cleanup);
 
@@ -479,34 +516,17 @@
     }
 
 cleanup:
-    lyd_free_all(yltree);
     ly_set_free(set, NULL);
     ly_set_erase(&features, NULL);
-    ly_ctx_destroy(ctx_yl);
     *ctx = ctx_new;
     if (ret) {
         ly_ctx_destroy(*ctx);
         *ctx = NULL;
     }
-
     return ret;
 }
 
 LIBYANG_API_DEF LY_ERR
-ly_ctx_new_ylpath(const char *search_dir, const char *path, LYD_FORMAT format, int options, struct ly_ctx **ctx)
-{
-    LY_CHECK_ARG_RET(NULL, path, ctx, LY_EINVAL);
-    return ly_ctx_new_yl_common(search_dir, path, format, options, lyd_parse_data_path, ctx);
-}
-
-LIBYANG_API_DEF LY_ERR
-ly_ctx_new_ylmem(const char *search_dir, const char *data, LYD_FORMAT format, int options, struct ly_ctx **ctx)
-{
-    LY_CHECK_ARG_RET(NULL, data, ctx, LY_EINVAL);
-    return ly_ctx_new_yl_common(search_dir, data, format, options, lyd_parse_data_mem, ctx);
-}
-
-LIBYANG_API_DEF LY_ERR
 ly_ctx_compile(struct ly_ctx *ctx)
 {
     LY_ERR ret = LY_SUCCESS;
@@ -641,15 +661,6 @@
     return ctx->change_count;
 }
 
-LIBYANG_API_DEF void
-ly_ctx_set_module_imp_clb(struct ly_ctx *ctx, ly_module_imp_clb clb, void *user_data)
-{
-    LY_CHECK_ARG_RET(ctx, ctx, );
-
-    ctx->imp_clb = clb;
-    ctx->imp_clb_data = user_data;
-}
-
 LIBYANG_API_DEF ly_module_imp_clb
 ly_ctx_get_module_imp_clb(const struct ly_ctx *ctx, void **user_data)
 {
@@ -661,6 +672,29 @@
     return ctx->imp_clb;
 }
 
+LIBYANG_API_DEF void
+ly_ctx_set_module_imp_clb(struct ly_ctx *ctx, ly_module_imp_clb clb, void *user_data)
+{
+    LY_CHECK_ARG_RET(ctx, ctx, );
+
+    ctx->imp_clb = clb;
+    ctx->imp_clb_data = user_data;
+}
+
+LIBYANG_API_DEF ly_ext_data_clb
+ly_ctx_set_ext_data_clb(struct ly_ctx *ctx, ly_ext_data_clb clb, void *user_data)
+{
+    ly_ext_data_clb prev;
+
+    LY_CHECK_ARG_RET(ctx, ctx, NULL);
+
+    prev = ctx->ext_clb;
+    ctx->ext_clb = clb;
+    ctx->ext_clb_data = user_data;
+
+    return prev;
+}
+
 LIBYANG_API_DEF struct lys_module *
 ly_ctx_get_module_iter(const struct ly_ctx *ctx, uint32_t *index)
 {