extensions CHANGE base for the extensions plugins API
diff --git a/src/extensions.h b/src/extensions.h
index 588f63a..6b8076b 100644
--- a/src/extensions.h
+++ b/src/extensions.h
@@ -15,10 +15,14 @@
 #ifndef LY_EXTENSIONS_H_
 #define LY_EXTENSIONS_H_
 
+#include "set.h"
+#include "tree_schema.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+
 /**
  * @defgroup extensions YANG Extensions
  *
@@ -26,80 +30,101 @@
  */
 
 /**
- * @brief Extension instance structure parent enumeration
+ * @defgroup extensionscompile YANG Extensions - Compilation Helpers
+ * @ingroup extensions
+ * @brief Helper functions to compile (via lyext_clb_compile callback) statements inside the extension instance.
+ *
+ * NOTE: There is a lot of useful static functions in the tree_schema_compile.c which could be provided here. Since we don't want
+ * to have a large API with functions which will be never used, we provide here just the functions which are evidently needed.
+ * If you, as an extension plugin author, need to make some of the compile functions available, please contact libyang maintainers
+ * via the GITHUB issue tracker.
+ *
+ * @{
  */
-typedef enum {
-    LYEXT_PAR_MODULE, /**< ::lys_module or ::lys_submodule */
-    LYEXT_PAR_NODE, /**< ::lys_node (and the derived structures) */
-    LYEXT_PAR_TPDF, /**< ::lys_tpdf */
-    LYEXT_PAR_TYPE, /**< ::lys_type */
-    LYEXT_PAR_TYPE_BIT, /**< ::lys_type_bit */
-    LYEXT_PAR_TYPE_ENUM, /**< ::lys_type_enum */
-    LYEXT_PAR_FEATURE, /**< ::lys_feature */
-    LYEXT_PAR_RESTR, /**< ::lys_restr - YANG's must, range, length and pattern statements */
-    LYEXT_PAR_WHEN, /**< ::lys_when */
-    LYEXT_PAR_IDENT, /**< ::lys_ident */
-    LYEXT_PAR_EXT, /**< ::lys_ext */
-    LYEXT_PAR_EXTINST, /**< ::lys_ext_instance */
-    LYEXT_PAR_REFINE, /**< ::lys_refine */
-    LYEXT_PAR_DEVIATION, /**< ::lys_deviation */
-    LYEXT_PAR_DEVIATE, /**< ::lys_deviate */
-    LYEXT_PAR_IMPORT, /**< ::lys_import */
-    LYEXT_PAR_INCLUDE,           /**< ::lysp_include */
-    LYEXT_PAR_REVISION,          /**< ::lysc_revision */
-} LYEXT_PARENT;
 
 /**
- * @brief Enum of substatements in which extension instances can appear.
+ * @brief internal context for compilation
  */
-typedef enum {
-    LYEXT_SUBSTMT_SELF = 0,      /**< extension of the structure itself, not substatement's */
-    LYEXT_SUBSTMT_ARGUMENT,      /**< extension of the argument statement, can appear in lys_ext */
-    LYEXT_SUBSTMT_BASE,          /**< extension of the base statement, can appear (repeatedly) in lys_type and lys_ident */
-    LYEXT_SUBSTMT_BELONGSTO,     /**< extension of the belongs-to statement, can appear in lys_submodule */
-    LYEXT_SUBSTMT_CONTACT,       /**< extension of the contact statement, can appear in lys_module */
-    LYEXT_SUBSTMT_DEFAULT,       /**< extension of the default statement, can appear in lys_node_leaf, lys_node_leaflist,
-                                      lys_node_choice and lys_deviate */
-    LYEXT_SUBSTMT_DESCRIPTION,   /**< extension of the description statement, can appear in lys_module, lys_submodule,
-                                      lys_node, lys_import, lys_include, lys_ext, lys_feature, lys_tpdf, lys_restr,
-                                      lys_ident, lys_deviation, lys_type_enum, lys_type_bit, lys_when and lys_revision */
-    LYEXT_SUBSTMT_ERRTAG,        /**< extension of the error-app-tag statement, can appear in lys_restr */
-    LYEXT_SUBSTMT_ERRMSG,        /**< extension of the error-message statement, can appear in lys_restr */
-    LYEXT_SUBSTMT_KEY,           /**< extension of the key statement, can appear in lys_node_list */
-    LYEXT_SUBSTMT_NAMESPACE,     /**< extension of the namespace statement, can appear in lys_module */
-    LYEXT_SUBSTMT_ORGANIZATION,  /**< extension of the organization statement, can appear in lys_module and lys_submodule */
-    LYEXT_SUBSTMT_PATH,          /**< extension of the path statement, can appear in lys_type */
-    LYEXT_SUBSTMT_PREFIX,        /**< extension of the prefix statement, can appear in lys_module, lys_submodule (for
-                                      belongs-to's prefix) and lys_import */
-    LYEXT_SUBSTMT_PRESENCE,      /**< extension of the presence statement, can appear in lys_node_container */
-    LYEXT_SUBSTMT_REFERENCE,     /**< extension of the reference statement, can appear in lys_module, lys_submodule,
-                                      lys_node, lys_import, lys_include, lys_revision, lys_tpdf, lys_restr, lys_ident,
-                                      lys_ext, lys_feature, lys_deviation, lys_type_enum, lys_type_bit and lys_when */
-    LYEXT_SUBSTMT_REVISIONDATE,  /**< extension of the revision-date statement, can appear in lys_import and lys_include */
-    LYEXT_SUBSTMT_UNITS,         /**< extension of the units statement, can appear in lys_tpdf, lys_node_leaf,
-                                      lys_node_leaflist and lys_deviate */
-    LYEXT_SUBSTMT_VALUE,         /**< extension of the value statement, can appear in lys_type_enum */
-    LYEXT_SUBSTMT_VERSION,       /**< extension of the yang-version statement, can appear in lys_module and lys_submodule */
-    LYEXT_SUBSTMT_MODIFIER,      /**< extension of the modifier statement, can appear in lys_restr */
-    LYEXT_SUBSTMT_REQINSTANCE,   /**< extension of the require-instance statement, can appear in lys_type */
-    LYEXT_SUBSTMT_YINELEM,       /**< extension of the yin-element statement, can appear in lys_ext */
-    LYEXT_SUBSTMT_CONFIG,        /**< extension of the config statement, can appear in lys_node and lys_deviate */
-    LYEXT_SUBSTMT_MANDATORY,     /**< extension of the mandatory statement, can appear in lys_node_leaf, lys_node_choice,
-                                      lys_node_anydata and lys_deviate */
-    LYEXT_SUBSTMT_ORDEREDBY,     /**< extension of the ordered-by statement, can appear in lys_node_list and lys_node_leaflist */
-    LYEXT_SUBSTMT_STATUS,        /**< extension of the status statement, can appear in lys_tpdf, lys_node, lys_ident,
-                                      lys_ext, lys_feature, lys_type_enum and lys_type_bit */
-    LYEXT_SUBSTMT_FRACDIGITS,    /**< extension of the fraction-digits statement, can appear in lys_type */
-    LYEXT_SUBSTMT_MAX,           /**< extension of the max-elements statement, can appear in lys_node_list,
-                                      lys_node_leaflist and lys_deviate */
-    LYEXT_SUBSTMT_MIN,           /**< extension of the min-elements statement, can appear in lys_node_list,
-                                      lys_node_leaflist and lys_deviate */
-    LYEXT_SUBSTMT_POSITION,      /**< extension of the position statement, can appear in lys_type_bit */
-    LYEXT_SUBSTMT_UNIQUE,        /**< extension of the unique statement, can appear in lys_node_list and lys_deviate */
-    LYEXT_SUBSTMT_IFFEATURE,     /**< extension of the if-feature statement */
-} LYEXT_SUBSTMT;
+struct lysc_ctx {
+    struct ly_ctx *ctx;
+    struct lys_module *mod;
+    struct lys_module *mod_def; /**< context module for the definitions of the nodes being currently
+                                     processed - groupings are supposed to be evaluated in place where
+                                     defined, but its content instances are supposed to be placed into
+                                     the target module (mod) */
+    struct ly_set groupings;    /**< stack for groupings circular check */
+    struct ly_set unres;        /**< to validate leafref's target and xpath of when/must */
+    struct ly_set dflts;        /**< set of incomplete default values */
+    struct ly_set tpdf_chain;
+    uint16_t path_len;
+    int options;                /**< various @ref scflags. */
+#define LYSC_CTX_BUFSIZE 4078
+    char path[LYSC_CTX_BUFSIZE];
+};
 
-/** @} */
+/**
+ * @brief Update path in the compile context, which is used for logging where the compilation failed.
+ *
+ * @param[in] ctx Compile context with the path.
+ * @param[in] parent Parent of the current node to check difference of the node's module. The current module is taken from lysc_ctx::mod.
+ * @param[in] name Name of the node to update path with. If NULL, the last segment is removed. If the format is `{keyword}`, the following
+ * call updates the segment to the form `{keyword='name'}` (to remove this compound segment, 2 calls with NULL @p name must be used).
+ */
+void lysc_update_path(struct lysc_ctx *ctx, struct lysc_node *parent, const char *name);
+
+/** @} extensionscompile */
+
+/**
+ * @brief Callback to compile extension from the lysp_ext_instance to the lysc_ext_instance. The later structure is generally prepared
+ * and only the extension specific data are supposed to be added (if any).
+ *
+ * @param[in] cctx Current compile context.
+ * @param[in] p_ext Parsed extension instance data.
+ * @param[in,out] c_ext Prepared compiled extension instance structure where an addition, extension-specific, data are supposed to be placed
+ * for later use (data validation or use of external tool).
+ * @return LY_SUCCESS in case of success.
+ * @return LY_EVALID in case of non-conforming parsed data.
+ */
+typedef LY_ERR (*lyext_clb_compile)(struct lysc_ctx *cctx, const struct lysp_ext_instance *p_ext, struct lysc_ext_instance *c_ext);
+
+/**
+ * @brief Callback to free the extension specific data created by the lyext_clb_compile callback of the same extension plugin.
+ *
+ * @param[in,out] ext Compiled extension structure where the data to free are placed.
+ */
+typedef void (*lyext_clb_free)(struct lysc_ext_instance *ext);
+
+/**
+ * @brief Callback to decide if data instance is valid according to the schema.
+ *
+ * The callback is used only for the extension instances placed in the following parent statements
+ * (which is specified as lysc_ext_instance::parent_type):
+ *     - LYEXT_PAR_NODE - @p node is instance of the schema node where the extension instance was specified.
+ *     - LYEXT_PAR_TPDF - @p node is instance of the schema node with the value of the typedef's type where the extension instance was specified.
+ *     - LYEXT_PAR_TYPE - @p node is instance of the schema node with the value of the type where the extension instance was specified.
+ *     - LYEXT_PAR_TYPE_BIT - @p node is instance of the schema node with the value of the bit where the extension instance was specified.
+ *     - LYEXT_PAR_TYPE_ENUM - @p node is instance of the schema node with the value of the enum where the extension instance was specified.
+ *
+ * @param[in] ext Extension instance to be checked.
+ * @param[in] node Data node, where the extension data are supposed to be placed.
+ *
+ * @return LY_SUCCESS on data validation success.
+ * @return LY_EVALID in case the validation fails.
+ */
+typedef LY_ERR (*lyext_clb_data_validation)(struct lysc_ext_instance *ext, struct lyd_node *node);
+
+/**
+ * @brief Extension plugin implementing various aspects of a YANG extension
+ */
+struct lyext_plugin {
+    const char *id;                     /**< Plugin identification (mainly for distinguish incompatible versions of the plugins for external tools) */
+    lyext_clb_compile compile;          /**< Callback to compile extension instance from the parsed data */
+    lyext_clb_data_validation validate; /**< Callback to decide if data instance is valid according to the schema. */
+    /* TODO printers? (schema/data) */
+    lyext_clb_free free;                /**< Free the extension instance specific data created by lyext_plugin::compile callback */
+};
+
+/** @} extensions */
 
 #ifdef __cplusplus
 }
diff --git a/src/tree_schema.h b/src/tree_schema.h
index 9c3346f..9ba9db3 100644
--- a/src/tree_schema.h
+++ b/src/tree_schema.h
@@ -23,7 +23,6 @@
 
 #include "log.h"
 #include "tree.h"
-#include "extensions.h"
 #include "tree_data.h"
 
 struct ly_ctx;
@@ -79,6 +78,80 @@
 #define LYS_AUGMENT 0x2000
 
 /**
+ * @brief Extension instance structure parent enumeration
+ */
+typedef enum {
+    LYEXT_PAR_MODULE, /**< ::lys_module or ::lys_submodule */
+    LYEXT_PAR_NODE, /**< ::lys_node (and the derived structures) */
+    LYEXT_PAR_TPDF, /**< ::lys_tpdf */
+    LYEXT_PAR_TYPE, /**< ::lys_type */
+    LYEXT_PAR_TYPE_BIT, /**< ::lys_type_bit */
+    LYEXT_PAR_TYPE_ENUM, /**< ::lys_type_enum */
+    LYEXT_PAR_FEATURE, /**< ::lys_feature */
+    LYEXT_PAR_RESTR, /**< ::lys_restr - YANG's must, range, length and pattern statements */
+    LYEXT_PAR_WHEN, /**< ::lys_when */
+    LYEXT_PAR_IDENT, /**< ::lys_ident */
+    LYEXT_PAR_EXT, /**< ::lys_ext */
+    LYEXT_PAR_EXTINST, /**< ::lys_ext_instance */
+    LYEXT_PAR_REFINE, /**< ::lys_refine */
+    LYEXT_PAR_DEVIATION, /**< ::lys_deviation */
+    LYEXT_PAR_DEVIATE, /**< ::lys_deviate */
+    LYEXT_PAR_IMPORT, /**< ::lys_import */
+    LYEXT_PAR_INCLUDE,           /**< ::lysp_include */
+    LYEXT_PAR_REVISION,          /**< ::lysc_revision */
+} LYEXT_PARENT;
+
+/**
+ * @brief Enum of substatements in which extension instances can appear.
+ */
+typedef enum {
+    LYEXT_SUBSTMT_SELF = 0,      /**< extension of the structure itself, not substatement's */
+    LYEXT_SUBSTMT_ARGUMENT,      /**< extension of the argument statement, can appear in lys_ext */
+    LYEXT_SUBSTMT_BASE,          /**< extension of the base statement, can appear (repeatedly) in lys_type and lys_ident */
+    LYEXT_SUBSTMT_BELONGSTO,     /**< extension of the belongs-to statement, can appear in lys_submodule */
+    LYEXT_SUBSTMT_CONTACT,       /**< extension of the contact statement, can appear in lys_module */
+    LYEXT_SUBSTMT_DEFAULT,       /**< extension of the default statement, can appear in lys_node_leaf, lys_node_leaflist,
+                                      lys_node_choice and lys_deviate */
+    LYEXT_SUBSTMT_DESCRIPTION,   /**< extension of the description statement, can appear in lys_module, lys_submodule,
+                                      lys_node, lys_import, lys_include, lys_ext, lys_feature, lys_tpdf, lys_restr,
+                                      lys_ident, lys_deviation, lys_type_enum, lys_type_bit, lys_when and lys_revision */
+    LYEXT_SUBSTMT_ERRTAG,        /**< extension of the error-app-tag statement, can appear in lys_restr */
+    LYEXT_SUBSTMT_ERRMSG,        /**< extension of the error-message statement, can appear in lys_restr */
+    LYEXT_SUBSTMT_KEY,           /**< extension of the key statement, can appear in lys_node_list */
+    LYEXT_SUBSTMT_NAMESPACE,     /**< extension of the namespace statement, can appear in lys_module */
+    LYEXT_SUBSTMT_ORGANIZATION,  /**< extension of the organization statement, can appear in lys_module and lys_submodule */
+    LYEXT_SUBSTMT_PATH,          /**< extension of the path statement, can appear in lys_type */
+    LYEXT_SUBSTMT_PREFIX,        /**< extension of the prefix statement, can appear in lys_module, lys_submodule (for
+                                      belongs-to's prefix) and lys_import */
+    LYEXT_SUBSTMT_PRESENCE,      /**< extension of the presence statement, can appear in lys_node_container */
+    LYEXT_SUBSTMT_REFERENCE,     /**< extension of the reference statement, can appear in lys_module, lys_submodule,
+                                      lys_node, lys_import, lys_include, lys_revision, lys_tpdf, lys_restr, lys_ident,
+                                      lys_ext, lys_feature, lys_deviation, lys_type_enum, lys_type_bit and lys_when */
+    LYEXT_SUBSTMT_REVISIONDATE,  /**< extension of the revision-date statement, can appear in lys_import and lys_include */
+    LYEXT_SUBSTMT_UNITS,         /**< extension of the units statement, can appear in lys_tpdf, lys_node_leaf,
+                                      lys_node_leaflist and lys_deviate */
+    LYEXT_SUBSTMT_VALUE,         /**< extension of the value statement, can appear in lys_type_enum */
+    LYEXT_SUBSTMT_VERSION,       /**< extension of the yang-version statement, can appear in lys_module and lys_submodule */
+    LYEXT_SUBSTMT_MODIFIER,      /**< extension of the modifier statement, can appear in lys_restr */
+    LYEXT_SUBSTMT_REQINSTANCE,   /**< extension of the require-instance statement, can appear in lys_type */
+    LYEXT_SUBSTMT_YINELEM,       /**< extension of the yin-element statement, can appear in lys_ext */
+    LYEXT_SUBSTMT_CONFIG,        /**< extension of the config statement, can appear in lys_node and lys_deviate */
+    LYEXT_SUBSTMT_MANDATORY,     /**< extension of the mandatory statement, can appear in lys_node_leaf, lys_node_choice,
+                                      lys_node_anydata and lys_deviate */
+    LYEXT_SUBSTMT_ORDEREDBY,     /**< extension of the ordered-by statement, can appear in lys_node_list and lys_node_leaflist */
+    LYEXT_SUBSTMT_STATUS,        /**< extension of the status statement, can appear in lys_tpdf, lys_node, lys_ident,
+                                      lys_ext, lys_feature, lys_type_enum and lys_type_bit */
+    LYEXT_SUBSTMT_FRACDIGITS,    /**< extension of the fraction-digits statement, can appear in lys_type */
+    LYEXT_SUBSTMT_MAX,           /**< extension of the max-elements statement, can appear in lys_node_list,
+                                      lys_node_leaflist and lys_deviate */
+    LYEXT_SUBSTMT_MIN,           /**< extension of the min-elements statement, can appear in lys_node_list,
+                                      lys_node_leaflist and lys_deviate */
+    LYEXT_SUBSTMT_POSITION,      /**< extension of the position statement, can appear in lys_type_bit */
+    LYEXT_SUBSTMT_UNIQUE,        /**< extension of the unique statement, can appear in lys_node_list and lys_deviate */
+    LYEXT_SUBSTMT_IFFEATURE,     /**< extension of the if-feature statement */
+} LYEXT_SUBSTMT;
+
+/**
  * @brief YANG import-stmt
  */
 struct lysp_import {
@@ -837,10 +910,23 @@
 void lysp_module_free(struct lysp_module *module);
 
 /**
+ * @brief Compiled YANG extension-stmt
+ */
+struct lysc_ext {
+    const char *name;                /**< extension name */
+    const char *argument;            /**< argument name, NULL if not specified */
+    const char *dsc;                 /**< description statement */
+    const char *ref;                 /**< reference statement */
+    struct lysc_ext_instance *exts;  /**< list of the extension instances ([sized array](@ref sizedarrays)) */
+    struct lyext_plugin *plugin;     /**< Plugin implementing the specific extension */
+    uint16_t flags;                  /**< LYS_STATUS_* value (@ref snodeflags) */
+};
+
+/**
  * @brief YANG extension instance
  */
 struct lysc_ext_instance {
-    struct lyext_plugin *plugin;     /**< pointer to the plugin implementing the extension (if present) */
+    struct lysc_ext *ext;            /**< pointer to the extension definition */
     void *parent;                    /**< pointer to the parent element holding the extension instance(s), use
                                           ::lysc_ext_instance#parent_type to access the schema element */
     const char *argument;            /**< optional value of the extension's argument */
@@ -848,14 +934,8 @@
     uint32_t insubstmt_index;        /**< in case the instance is in a substatement that can appear multiple times,
                                           this identifies the index of the substatement for this extension instance */
     LYEXT_PARENT parent_type;        /**< type of the parent structure */
-#if 0
-    uint8_t ext_type;                /**< extension type (#LYEXT_TYPE) */
-    uint8_t padding;                 /**< 32b padding */
-    struct lys_module *module;       /**< pointer to the extension instance's module (mandatory) */
-    LYS_NODE nodetype;               /**< LYS_EXT */
-#endif
     struct lysc_ext_instance *exts;  /**< list of the extension instances ([sized array](@ref sizedarrays)) */
-    void *priv;                      /**< private caller's data, not used by libyang */
+    void *data;                      /**< private plugins's data, not used by libyang */
 };
 
 /**
diff --git a/src/tree_schema_compile.c b/src/tree_schema_compile.c
index bea32c1..6259161 100644
--- a/src/tree_schema_compile.c
+++ b/src/tree_schema_compile.c
@@ -26,6 +26,7 @@
 #include "log.h"
 #include "set.h"
 #include "plugins_types.h"
+#include "extensions.h"
 #include "tree.h"
 #include "tree_schema.h"
 #include "tree_schema_internal.h"
@@ -153,15 +154,7 @@
     }
 }
 
-/**
- * @brief Update path in the compile context.
- *
- * @param[in] ctx Compile context with the path.
- * @param[in] parent Parent of the current node to check difference of the node's module. The current module is taken from lysc_ctx::mod.
- * @param[in] name Name of the node to update path with. If NULL, the last segment is removed. If the format is `{keyword}`, the following
- * call updates the segment to the form `{keyword='name'}` (to remove this compound segment, 2 calls with NULL @p name must be used).
- */
-static void
+void
 lysc_update_path(struct lysc_ctx *ctx, struct lysc_node *parent, const char *name)
 {
     int len;
diff --git a/src/tree_schema_internal.h b/src/tree_schema_internal.h
index 9069361..c81a9fc 100644
--- a/src/tree_schema_internal.h
+++ b/src/tree_schema_internal.h
@@ -19,6 +19,7 @@
 
 #include "set.h"
 #include "tree_schema.h"
+#include "extensions.h"
 
 #define LOGVAL_YANG(CTX, ...) LOGVAL((CTX)->ctx, LY_VLOG_LINE, &(CTX)->line, __VA_ARGS__)
 
@@ -67,26 +68,6 @@
 };
 
 /**
- * @brief internal context for compilation
- */
-struct lysc_ctx {
-    struct ly_ctx *ctx;
-    struct lys_module *mod;
-    struct lys_module *mod_def; /**< context module for the definitions of the nodes being currently
-                                     processed - groupings are supposed to be evaluated in place where
-                                     defined, but its content instances are supposed to be placed into
-                                     the target module (mod) */
-    struct ly_set groupings;    /**< stack for groupings circular check */
-    struct ly_set unres;        /**< to validate leafref's target and xpath of when/must */
-    struct ly_set dflts;        /**< set of incomplete default values */
-    struct ly_set tpdf_chain;
-    uint16_t path_len;
-    int options;                /**< various @ref scflags. */
-#define LYSC_CTX_BUFSIZE 4078
-    char path[LYSC_CTX_BUFSIZE];
-};
-
-/**
  * @brief Internal structure for lys_get_prefix().
  */
 struct lys_get_prefix_data {