plugins exts CHANGE ext parsing isolated into a callback

Lots of refactoring and finishing up included.
diff --git a/src/tree_schema_common.c b/src/tree_schema_common.c
index 427d404..e82f6b9 100644
--- a/src/tree_schema_common.c
+++ b/src/tree_schema_common.c
@@ -40,6 +40,87 @@
 #include "tree_schema.h"
 #include "tree_schema_internal.h"
 
+/**
+ * @brief information about YANG statements
+ */
+struct stmt_info_s stmt_attr_info[] = {
+    [LY_STMT_NONE] = {NULL, NULL, 0},
+    [LY_STMT_ACTION] = {"action", "name", STMT_FLAG_ID},
+    [LY_STMT_ANYDATA] = {"anydata", "name", STMT_FLAG_ID},
+    [LY_STMT_ANYXML] = {"anyxml", "name", STMT_FLAG_ID},
+    [LY_STMT_ARGUMENT] = {"argument", "name", STMT_FLAG_ID},
+    [LY_STMT_ARG_TEXT] = {"text", NULL, 0},
+    [LY_STMT_ARG_VALUE] = {"value", NULL, 0},
+    [LY_STMT_AUGMENT] = {"augment", "target-node", STMT_FLAG_ID},
+    [LY_STMT_BASE] = {"base", "name", STMT_FLAG_ID},
+    [LY_STMT_BELONGS_TO] = {"belongs-to", "module", STMT_FLAG_ID},
+    [LY_STMT_BIT] = {"bit", "name", STMT_FLAG_ID},
+    [LY_STMT_CASE] = {"case", "name", STMT_FLAG_ID},
+    [LY_STMT_CHOICE] = {"choice", "name", STMT_FLAG_ID},
+    [LY_STMT_CONFIG] = {"config", "value", STMT_FLAG_ID},
+    [LY_STMT_CONTACT] = {"contact", "text", STMT_FLAG_YIN},
+    [LY_STMT_CONTAINER] = {"container", "name", STMT_FLAG_ID},
+    [LY_STMT_DEFAULT] = {"default", "value", 0},
+    [LY_STMT_DESCRIPTION] = {"description", "text", STMT_FLAG_YIN},
+    [LY_STMT_DEVIATE] = {"deviate", "value", STMT_FLAG_ID},
+    [LY_STMT_DEVIATION] = {"deviation", "target-node", STMT_FLAG_ID},
+    [LY_STMT_ENUM] = {"enum", "name", STMT_FLAG_ID},
+    [LY_STMT_ERROR_APP_TAG] = {"error-app-tag", "value", 0},
+    [LY_STMT_ERROR_MESSAGE] = {"error-message", "value", STMT_FLAG_YIN},
+    [LY_STMT_EXTENSION] = {"extension", "name", STMT_FLAG_ID},
+    [LY_STMT_EXTENSION_INSTANCE] = {NULL, NULL, 0},
+    [LY_STMT_FEATURE] = {"feature", "name", STMT_FLAG_ID},
+    [LY_STMT_FRACTION_DIGITS] = {"fraction-digits", "value", STMT_FLAG_ID},
+    [LY_STMT_GROUPING] = {"grouping", "name", STMT_FLAG_ID},
+    [LY_STMT_IDENTITY] = {"identity", "name", STMT_FLAG_ID},
+    [LY_STMT_IF_FEATURE] = {"if-feature", "name", 0},
+    [LY_STMT_IMPORT] = {"import", "module", STMT_FLAG_ID},
+    [LY_STMT_INCLUDE] = {"include", "module", STMT_FLAG_ID},
+    [LY_STMT_INPUT] = {"input", NULL, 0},
+    [LY_STMT_KEY] = {"key", "value", 0},
+    [LY_STMT_LEAF] = {"leaf", "name", STMT_FLAG_ID},
+    [LY_STMT_LEAF_LIST] = {"leaf-list", "name", STMT_FLAG_ID},
+    [LY_STMT_LENGTH] = {"length", "value", 0},
+    [LY_STMT_LIST] = {"list", "name", STMT_FLAG_ID},
+    [LY_STMT_MANDATORY] = {"mandatory", "value", STMT_FLAG_ID},
+    [LY_STMT_MAX_ELEMENTS] = {"max-elements", "value", STMT_FLAG_ID},
+    [LY_STMT_MIN_ELEMENTS] = {"min-elements", "value", STMT_FLAG_ID},
+    [LY_STMT_MODIFIER] = {"modifier", "value", STMT_FLAG_ID},
+    [LY_STMT_MODULE] = {"module", "name", STMT_FLAG_ID},
+    [LY_STMT_MUST] = {"must", "condition", 0},
+    [LY_STMT_NAMESPACE] = {"namespace", "uri", 0},
+    [LY_STMT_NOTIFICATION] = {"notification", "name", STMT_FLAG_ID},
+    [LY_STMT_ORDERED_BY] = {"ordered-by", "value", STMT_FLAG_ID},
+    [LY_STMT_ORGANIZATION] = {"organization", "text", STMT_FLAG_YIN},
+    [LY_STMT_OUTPUT] = {"output", NULL, 0},
+    [LY_STMT_PATH] = {"path", "value", 0},
+    [LY_STMT_PATTERN] = {"pattern", "value", 0},
+    [LY_STMT_POSITION] = {"position", "value", STMT_FLAG_ID},
+    [LY_STMT_PREFIX] = {"prefix", "value", STMT_FLAG_ID},
+    [LY_STMT_PRESENCE] = {"presence", "value", 0},
+    [LY_STMT_RANGE] = {"range", "value", 0},
+    [LY_STMT_REFERENCE] = {"reference", "text", STMT_FLAG_YIN},
+    [LY_STMT_REFINE] = {"refine", "target-node", STMT_FLAG_ID},
+    [LY_STMT_REQUIRE_INSTANCE] = {"require-instance", "value", STMT_FLAG_ID},
+    [LY_STMT_REVISION] = {"revision", "date", STMT_FLAG_ID},
+    [LY_STMT_REVISION_DATE] = {"revision-date", "date", STMT_FLAG_ID},
+    [LY_STMT_RPC] = {"rpc", "name", STMT_FLAG_ID},
+    [LY_STMT_STATUS] = {"status", "value", STMT_FLAG_ID},
+    [LY_STMT_SUBMODULE] = {"submodule", "name", STMT_FLAG_ID},
+    [LY_STMT_SYNTAX_LEFT_BRACE] = {"{", NULL, 0},
+    [LY_STMT_SYNTAX_RIGHT_BRACE] = {"}", NULL, 0},
+    [LY_STMT_SYNTAX_SEMICOLON] = {";", NULL, 0},
+    [LY_STMT_TYPE] = {"type", "name", STMT_FLAG_ID},
+    [LY_STMT_TYPEDEF] = {"typedef", "name", STMT_FLAG_ID},
+    [LY_STMT_UNIQUE] = {"unique", "tag", 0},
+    [LY_STMT_UNITS] = {"units", "name", 0},
+    [LY_STMT_USES] = {"uses", "name", STMT_FLAG_ID},
+    [LY_STMT_VALUE] = {"value", "value", STMT_FLAG_ID},
+    [LY_STMT_WHEN] = {"when", "condition", 0},
+    [LY_STMT_YANG_VERSION] = {"yang-version", "value", STMT_FLAG_ID},
+    [LY_STMT_YIN_ELEMENT] = {"yin-element", "value", STMT_FLAG_ID},
+};
+
 LY_ERR
 lysp_check_prefix(struct lysp_ctx *ctx, struct lysp_import *imports, const char *module_prefix, const char **value)
 {
@@ -256,7 +337,7 @@
 {
     const char *str, *name;
     struct lysp_tpdf *typedefs;
-    const struct lysp_tpdf **ext_typedefs;
+    const struct lysp_tpdf *ext_typedefs;
     const struct lys_module *mod;
     const struct lysp_module *local_module;
     LY_ARRAY_COUNT_TYPE u, v;
@@ -300,8 +381,8 @@
 
         if (ext) {
             /* search typedefs directly in the extension */
-            ext_typedefs = (void *)lys_compile_ext_instance_get_storage(ext, LY_STMT_TYPEDEF);
-            if (ext_typedefs && (*tpdf = lysp_typedef_match(name, *ext_typedefs))) {
+            lyplg_ext_parsed_get_storage(ext, LY_STMT_TYPEDEF, (const void **)&ext_typedefs);
+            if ((*tpdf = lysp_typedef_match(name, ext_typedefs))) {
                 /* match */
                 return LY_SUCCESS;
             }
@@ -1348,43 +1429,6 @@
     }
 }
 
-LIBYANG_API_DEF enum ly_stmt
-lys_nodetype2stmt(uint16_t nodetype)
-{
-    switch (nodetype) {
-    case LYS_CONTAINER:
-        return LY_STMT_CONTAINER;
-    case LYS_CHOICE:
-        return LY_STMT_CHOICE;
-    case LYS_LEAF:
-        return LY_STMT_LEAF;
-    case LYS_LEAFLIST:
-        return LY_STMT_LEAF_LIST;
-    case LYS_LIST:
-        return LY_STMT_LIST;
-    case LYS_ANYXML:
-        return LY_STMT_ANYXML;
-    case LYS_ANYDATA:
-        return LY_STMT_ANYDATA;
-    case LYS_CASE:
-        return LY_STMT_CASE;
-    case LYS_RPC:
-        return LY_STMT_RPC;
-    case LYS_ACTION:
-        return LY_STMT_ACTION;
-    case LYS_NOTIF:
-        return LY_STMT_NOTIFICATION;
-    case LYS_USES:
-        return LY_STMT_USES;
-    case LYS_INPUT:
-        return LY_STMT_INPUT;
-    case LYS_OUTPUT:
-        return LY_STMT_OUTPUT;
-    default:
-        return LY_STMT_NONE;
-    }
-}
-
 const char *
 lys_datatype2str(LY_DATA_TYPE basetype)
 {
@@ -2092,11 +2136,8 @@
     const struct lys_module *mod = NULL;
     const struct lysp_submodule *submod;
 
-    assert(ext_def);
-
-    *ext_def = NULL;
-    if (ext_mod) {
-        *ext_mod = NULL;
+    if (ext_def) {
+        *ext_def = NULL;
     }
 
     /* parse the prefix, the nodeid was previously already parsed and checked */
@@ -2104,7 +2145,7 @@
     ly_parse_nodeid(&tmp, &prefix, &pref_len, &name, &name_len);
 
     /* get module where the extension definition should be placed */
-    mod = ly_resolve_prefix(ctx, prefix, pref_len, ext->format, ext->prefix_data);
+    *ext_mod = mod = ly_resolve_prefix(ctx, prefix, pref_len, ext->format, ext->prefix_data);
     if (!mod) {
         LOGVAL(ctx, LYVE_REFERENCE, "Invalid prefix \"%.*s\" used for extension instance identifier.", (int)pref_len, prefix);
         return LY_EVALID;
@@ -2114,6 +2155,11 @@
         return LY_EVALID;
     }
 
+    if (!ext_def) {
+        /* we are done */
+        return LY_SUCCESS;
+    }
+
     /* find the parsed extension definition there */
     LY_ARRAY_FOR(mod->parsed->extensions, v) {
         if (!strcmp(name, mod->parsed->extensions[v].name)) {
@@ -2138,25 +2184,24 @@
         return LY_EVALID;
     }
 
-    if (ext_mod) {
-        *ext_mod = mod;
-    }
     return LY_SUCCESS;
 }
 
 LY_ERR
-lysp_ext_instance_resolve_argument(struct ly_ctx *ctx, struct lysp_ext_instance *ext_p, struct lysp_ext *ext_def)
+lysp_ext_instance_resolve_argument(struct ly_ctx *ctx, struct lysp_ext_instance *ext_p)
 {
-    if (!ext_def->argname || ext_p->argument) {
+    assert(ext_p->def);
+
+    if (!ext_p->def->argname || ext_p->argument) {
         /* nothing to do */
         return LY_SUCCESS;
     }
 
     if (ext_p->format == LY_VALUE_XML) {
-        /* Schema was parsed from YIN and an argument is expected, ... */
+        /* schema was parsed from YIN and an argument is expected, ... */
         struct lysp_stmt *stmt = NULL;
 
-        if (ext_def->flags & LYS_YINELEM_TRUE) {
+        if (ext_p->def->flags & LYS_YINELEM_TRUE) {
             /* ... argument was the first XML child element */
             for (stmt = ext_p->child; stmt && (stmt->flags & LYS_YIN_ATTR); stmt = stmt->next) {}
             if (stmt) {
@@ -2167,9 +2212,9 @@
 
                 arg = stmt->stmt;
                 ly_parse_nodeid(&arg, &prefix_arg, &prefix_arg_len, &name_arg, &name_arg_len);
-                if (ly_strncmp(ext_def->argname, name_arg, name_arg_len)) {
+                if (ly_strncmp(ext_p->def->argname, name_arg, name_arg_len)) {
                     LOGVAL(ctx, LYVE_SEMANTICS, "Extension instance \"%s\" expects argument element \"%s\" as its first XML child, "
-                            "but \"%.*s\" element found.", ext_p->name, ext_def->argname, (int)name_arg_len, name_arg);
+                            "but \"%.*s\" element found.", ext_p->name, ext_p->def->argname, (int)name_arg_len, name_arg);
                     return LY_EVALID;
                 }
 
@@ -2181,15 +2226,14 @@
                 if (ly_resolve_prefix(ctx, prefix_ext, prefix_ext_len, ext_p->format, ext_p->prefix_data) !=
                         ly_resolve_prefix(ctx, prefix_arg, prefix_arg_len, stmt->format, stmt->prefix_data)) {
                     LOGVAL(ctx, LYVE_SEMANTICS, "Extension instance \"%s\" element and its argument element \"%s\" are "
-                            "expected in the same namespace, but they differ.", ext_p->name, ext_def->argname);
+                            "expected in the same namespace, but they differ.", ext_p->name, ext_p->def->argname);
                     return LY_EVALID;
                 }
             }
         } else {
-            /* ... argument was one of the XML attributes which are represented as child stmt
-             * with LYS_YIN_ATTR flag */
+            /* ... argument was one of the XML attributes which are represented as child stmt with LYS_YIN_ATTR flag */
             for (stmt = ext_p->child; stmt && (stmt->flags & LYS_YIN_ATTR); stmt = stmt->next) {
-                if (!strcmp(stmt->stmt, ext_def->argname)) {
+                if (!strcmp(stmt->stmt, ext_p->def->argname)) {
                     /* this is the extension's argument */
                     break;
                 }
@@ -2204,8 +2248,8 @@
 
     if (!ext_p->argument) {
         /* missing extension's argument */
-        LOGVAL(ctx, LYVE_SEMANTICS, "Extension instance \"%s\" misses argument %s\"%s\".",
-                ext_p->name, (ext_def->flags & LYS_YINELEM_TRUE) ? "element " : "", ext_def->argname);
+        LOGVAL(ctx, LYVE_SEMANTICS, "Extension instance \"%s\" missing argument %s\"%s\".",
+                ext_p->name, (ext_p->def->flags & LYS_YINELEM_TRUE) ? "element " : "", ext_p->def->argname);
         return LY_EVALID;
     }