schema tree CHANGE remove compiled ext defs arrays

They are now only parsed or additionally referenced
only from extension instances.
diff --git a/src/tree_schema.c b/src/tree_schema.c
index b1a662e..350201a 100644
--- a/src/tree_schema.c
+++ b/src/tree_schema.c
@@ -802,9 +802,8 @@
     }
 
     if (!mod->implemented) {
-        /* pre-compile features and extension definitions of the module */
+        /* pre-compile features of the module */
         LY_CHECK_GOTO(lys_feature_precompile(NULL, ctx, mod, mod->parsed->features, &mod->off_features), error);
-        LY_CHECK_GOTO(lys_extension_precompile(NULL, ctx, mod, mod->parsed->extensions, &mod->off_extensions), error);
     }
 
     if (latest) {
@@ -836,9 +835,8 @@
             goto error_ctx;
         }
         if (!mod->implemented) {
-            /* pre-compile features and extension definitions of the module */
+            /* pre-compile features of the submodule */
             LY_CHECK_GOTO(lys_feature_precompile(NULL, ctx, mod, inc->submodule->features, &mod->off_features), error);
-            LY_CHECK_GOTO(lys_extension_precompile(NULL, ctx, mod, mod->parsed->extensions, &mod->off_extensions), error);
         }
     }
     mod->parsed->parsing = 0;
diff --git a/src/tree_schema.h b/src/tree_schema.h
index ace3bfd..855a1bf 100644
--- a/src/tree_schema.h
+++ b/src/tree_schema.h
@@ -371,6 +371,8 @@
     const char *ref;                 /**< reference statement */
     struct lysp_ext_instance *exts;  /**< list of the extension instances ([sized array](@ref sizedarrays)) */
     uint16_t flags;                  /**< LYS_STATUS_* and LYS_YINELEM_* values (@ref snodeflags) */
+
+    struct lysc_ext *compiled;       /**< pointer to the compiled extension definition */
 };
 
 /**
@@ -1645,7 +1647,6 @@
     struct lysc_node *data;          /**< list of module's top-level data nodes (linked list) */
     struct lysc_action *rpcs;        /**< list of RPCs ([sized array](@ref sizedarrays)) */
     struct lysc_notif *notifs;       /**< list of notifications ([sized array](@ref sizedarrays)) */
-    struct lysc_ext **extensions;    /**< list of pointers to extension definitions ([sized array](@ref sizedarrays)) */
     struct lysc_ext_instance *exts;  /**< list of the extension instances ([sized array](@ref sizedarrays)) */
 };
 
@@ -1777,12 +1778,6 @@
                                           from if-feature statements of the compiled schemas and their proper use in case
                                           the module became implemented in future (no matter if implicitly via augment/deviate
                                           or explicitly via ly_ctx_module_implement()). */
-    struct lysc_ext **off_extensions;/**< List of pointers to pre-compiled extension definitions of the module in non-implemented modules
-                                          ([sized array](@ref sizedarrays)). These extensions are prepared to be linked with the extension instances,
-                                          but they are not implemented (connected with any extension plugin). In case the module become
-                                          implemented, the list is moved into the compiled module structure and available extension plugins
-                                          are connected with the appropriate extension definision. */
-
     uint8_t implemented;             /**< flag if the module is implemented, not just imported. The module is implemented if
                                           the flag has non-zero value. Specific values are used internally:
                                           1 - implemented module
diff --git a/src/tree_schema_compile.c b/src/tree_schema_compile.c
index 61f4a19..a9649e3 100644
--- a/src/tree_schema_compile.c
+++ b/src/tree_schema_compile.c
@@ -33,6 +33,9 @@
 #include "tree_schema_internal.h"
 #include "xpath.h"
 
+static LY_ERR lys_compile_ext(struct lysc_ctx *ctx, struct lysp_ext_instance *ext_p, struct lysc_ext_instance *ext,
+                              void *parent, LYEXT_PARENT parent_type, const struct lys_module *ext_mod);
+
 /**
  * @brief Duplicate string into dictionary
  * @param[in] CTX libyang context of the dictionary.
@@ -442,6 +445,39 @@
 }
 
 /**
+ * @brief Fill in the prepared compiled extensions definition structure according to the parsed extension definition.
+ */
+static LY_ERR
+lys_compile_extension(struct lysc_ctx *ctx, const struct lys_module *ext_mod, struct lysp_ext *ext_p, struct lysc_ext **ext)
+{
+    LY_ERR ret = LY_SUCCESS;
+
+    if (!ext_p->compiled) {
+        lysc_update_path(ctx, NULL, "{extension}");
+        lysc_update_path(ctx, NULL, ext_p->name);
+
+        /* compile the extension definition */
+        ext_p->compiled = calloc(1, sizeof **ext);
+        ext_p->compiled->refcount = 1;
+        DUP_STRING(ctx->ctx, ext_p->name, ext_p->compiled->name);
+        DUP_STRING(ctx->ctx, ext_p->argument, ext_p->compiled->argument);
+        ext_p->compiled->module = (struct lys_module *)ext_mod;
+        COMPILE_EXTS_GOTO(ctx, ext_p->exts, ext_p->compiled->exts, *ext, LYEXT_PAR_EXT, ret, done);
+
+        lysc_update_path(ctx, NULL, NULL);
+        lysc_update_path(ctx, NULL, NULL);
+
+        /* find extension definition plugin */
+        ext_p->compiled->plugin = lyext_get_plugin(ext_p->compiled);
+    }
+
+    *ext = lysc_ext_dup(ext_p->compiled);
+
+done:
+    return ret;
+}
+
+/**
  * @brief Fill in the prepared compiled extension instance structure according to the parsed extension instance.
  *
  * @param[in] ctx Compilation context.
@@ -458,7 +494,6 @@
     LY_ERR ret = LY_EVALID;
     const char *name;
     unsigned int u;
-    struct lysc_ext **elist = NULL;
     const char *prefixed_name = NULL;
 
     DUP_STRING(ctx->ctx, ext_p->argument, ext->argument);
@@ -516,15 +551,11 @@
     }
     name = &prefixed_name[u];
 
-    /* find the extension definition there */
-    if (ext_mod->off_extensions) {
-        elist = ext_mod->off_extensions;
-    } else {
-        elist = ext_mod->compiled->extensions;
-    }
-    LY_ARRAY_FOR(elist, u) {
-        if (!strcmp(name, elist[u]->name)) {
-            ext->def = lysc_ext_dup(elist[u]);
+    /* find the parsed extension definition there */
+    LY_ARRAY_FOR(ext_mod->parsed->extensions, u) {
+        if (!strcmp(name, ext_mod->parsed->extensions[u].name)) {
+            /* compile extension definition and assign it */
+            LY_CHECK_RET(lys_compile_extension(ctx, ext_mod, &ext_mod->parsed->extensions[u], &ext->def));
             break;
         }
     }
@@ -601,82 +632,6 @@
 }
 
 /**
- * @brief Fill in the prepared compiled extensions definition structure according to the parsed extension definition.
- */
-static LY_ERR
-lys_compile_extension(struct lysc_ctx *ctx, struct lysp_ext *ext_p, struct lysc_ext **ext)
-{
-    LY_ERR ret = LY_SUCCESS;
-
-    *ext = calloc(1, sizeof **ext);
-    (*ext)->refcount = 1;
-    DUP_STRING(ctx->ctx, ext_p->name, (*ext)->name);
-    DUP_STRING(ctx->ctx, ext_p->argument, (*ext)->argument);
-    (*ext)->module = ctx->mod_def;
-    COMPILE_EXTS_GOTO(ctx, ext_p->exts, (*ext)->exts, *ext, LYEXT_PAR_EXT, ret, done);
-
-done:
-    return ret;
-}
-
-/**
- * @brief Link the extensions definitions with the available extension plugins.
- *
- * This is done only in the compiled (implemented) module. Extensions of a non-implemented modules
- * are not connected with even available extension plugins.
- *
- * @param[in] extensions List of pointers to extensions to be processed ([sized array](@ref sizedarrays)).
- */
-static void
-lys_compile_extension_plugins(struct lysc_ext **extensions)
-{
-    unsigned int u;
-
-    LY_ARRAY_FOR(extensions, u) {
-        extensions[u]->plugin = lyext_get_plugin(extensions[u]);
-    }
-}
-
-LY_ERR
-lys_extension_precompile(struct lysc_ctx *ctx_sc, struct ly_ctx *ctx, struct lys_module *module,
-                         struct lysp_ext *extensions_p, struct lysc_ext ***extensions)
-{
-    unsigned int offset = 0, u;
-    struct lysc_ctx context = {0};
-
-    assert(ctx_sc || ctx);
-
-    if (!ctx_sc) {
-        context.ctx = ctx;
-        context.mod = module;
-        context.mod_def = module;
-        context.path_len = 1;
-        context.path[0] = '/';
-        ctx_sc = &context;
-    }
-
-    if (!extensions_p) {
-        return LY_SUCCESS;
-    }
-    if (*extensions) {
-        offset = LY_ARRAY_SIZE(*extensions);
-    }
-
-    lysc_update_path(ctx_sc, NULL, "{extension}");
-    LY_ARRAY_CREATE_RET(ctx_sc->ctx, *extensions, LY_ARRAY_SIZE(extensions_p), LY_EMEM);
-    LY_ARRAY_FOR(extensions_p, u) {
-        lysc_update_path(ctx_sc, NULL, extensions_p[u].name);
-        LY_ARRAY_INCREMENT(*extensions);
-        LY_CHECK_RET(lys_compile_extension(ctx_sc, &extensions_p[u], &(*extensions)[offset + u]));
-        COMPILE_CHECK_UNIQUENESS_PARRAY(ctx_sc, *extensions, name, &(*extensions)[offset + u], "extension", extensions_p[u].name);
-        lysc_update_path(ctx_sc, NULL, NULL);
-    }
-    lysc_update_path(ctx_sc, NULL, NULL);
-
-    return LY_SUCCESS;
-}
-
-/**
  * @brief Compile information from the if-feature statement
  * @param[in] ctx Compile context.
  * @param[in] value The if-feature argument to process. It is pointer-to-pointer-to-char just to unify the compile functions.
@@ -6836,11 +6791,6 @@
         ret = lys_feature_precompile(ctx, NULL, NULL, submod->features, &mainmod->features);
         LY_CHECK_GOTO(ret, error);
     }
-    if (!mainmod->mod->off_extensions) {
-        /* extensions are compiled directly into the compiled module structure, compilation is finished in the main module (lys_compile()). */
-        ret = lys_extension_precompile(ctx, NULL, NULL, submod->extensions, &mainmod->extensions);
-        LY_CHECK_GOTO(ret, error);
-    }
 
     lysc_update_path(ctx, NULL, "{identity}");
     COMPILE_ARRAY_UNIQUE_GOTO(ctx, submod->identities, mainmod->identities, u, lys_compile_identity, ret, error);
@@ -7328,20 +7278,6 @@
     }
     lysc_update_path(&ctx, NULL, NULL);
 
-    /* extensions */
-    /* 2-steps: a) prepare compiled structures and ... */
-    if (mod->off_extensions) {
-        /* there is already precompiled array of extension definitions */
-        mod_c->extensions = mod->off_extensions;
-        mod->off_extensions = NULL;
-    } else {
-        /* extension definitions are compiled directly into the compiled module structure */
-        ret = lys_extension_precompile(&ctx, NULL, NULL, sp->extensions, &mod_c->extensions);
-        LY_CHECK_GOTO(ret, error);
-    }
-    /* ... b) connect the extension definitions with the appropriate extension plugins */
-    lys_compile_extension_plugins(mod_c->extensions);
-
     /* identities */
     lysc_update_path(&ctx, NULL, "{identity}");
     COMPILE_ARRAY_UNIQUE_GOTO(&ctx, sp->identities, mod_c->identities, u, lys_compile_identity, ret, error);
diff --git a/src/tree_schema_free.c b/src/tree_schema_free.c
index deaf20c..79d46ba 100644
--- a/src/tree_schema_free.c
+++ b/src/tree_schema_free.c
@@ -25,6 +25,7 @@
 
 void lysp_grp_free(struct ly_ctx *ctx, struct lysp_grp *grp);
 void lysp_node_free(struct ly_ctx *ctx, struct lysp_node *node);
+void lysc_extension_free(struct ly_ctx *ctx, struct lysc_ext **ext);
 
 static void
 lysp_stmt_free(struct ly_ctx *ctx, struct lysp_stmt *stmt)
@@ -93,6 +94,9 @@
     FREE_STRING(ctx, ext->dsc);
     FREE_STRING(ctx, ext->ref);
     FREE_ARRAY(ctx, ext->exts, lysp_ext_instance_free);
+    if (ext->compiled) {
+        lysc_extension_free(ctx, &ext->compiled);
+    }
 }
 
 void
@@ -837,8 +841,6 @@
     }
     FREE_ARRAY(ctx, module->rpcs, lysc_action_free);
     FREE_ARRAY(ctx, module->notifs, lysc_notif_free);
-
-    FREE_ARRAY(ctx, module->extensions, lysc_extension_free);
     FREE_ARRAY(ctx, module->exts, lysc_ext_instance_free);
 
     free(module);
@@ -864,7 +866,6 @@
 
     lysc_module_free(module->compiled, private_destructor);
     FREE_ARRAY(module->ctx, module->off_features, lysc_feature_free);
-    FREE_ARRAY(module->ctx, module->off_extensions, lysc_extension_free);
     lysp_module_free(module->parsed);
 
     FREE_STRING(module->ctx, module->name);
diff --git a/src/tree_schema_internal.h b/src/tree_schema_internal.h
index 5efbb1e..457a596 100644
--- a/src/tree_schema_internal.h
+++ b/src/tree_schema_internal.h
@@ -674,21 +674,6 @@
                                     const struct lysc_node **target);
 
 /**
- * @brief Internal wrapper around lys_compile_extension() to be able to prepare list of compiled extension definitions
- * even for the parsed (not-implemented) module - see lys_module::off_extensions.
- *
- * @param[in] ctx_sc Compile context - alternative to the combination of @p ctx and @p module.
- * @param[in] ctx libyang context.
- * @param[in] module Module of the extensions.
- * @param[in] extensions_p Array of the parsed extension definitions to precompile.
- * @param[in,out] extensions Pointer to the storage of the (pre)compiled extensions array where the new extensions are
- * supposed to be added. The storage is supposed to be initiated to NULL when the first parsed extensions are going
- * to be processed.
- * @return LY_ERR value.
- */
-LY_ERR lys_extension_precompile(struct lysc_ctx *ctx_sc, struct ly_ctx *ctx, struct lys_module *module,
-                                struct lysp_ext *extensions_p, struct lysc_ext ***extensions);
-/**
  * @brief Macro to free [sized array](@ref sizedarrays) of items using the provided free function. The ARRAY itself is also freed,
  * but the memory is not sanitized.
  */