yin parser CHANGE parse known extension subelements correctly finished
diff --git a/src/common.h b/src/common.h
index 342e144..744b1c5 100644
--- a/src/common.h
+++ b/src/common.h
@@ -546,7 +546,7 @@
         if (ARRAY){free((uint32_t*)(ARRAY) - 1);}
 
 /**
- * @brief insert item into linked list.
+ * @brief Insert item into linked list.
  *
  * @param[in,out] LIST Linked list to add to.
  * @param[in] NEW_ITEM New item, that will be appended to the list, must be already allocated.
@@ -564,7 +564,7 @@
     }
 
 /**
- * @brief allocate and insert new item into linked list.
+ * @brief Allocate and insert new item into linked list, return in case of error.
  *
  * @param[in] CTX used for logging.
  * @param[in,out] LIST Linked list to add to.
@@ -577,7 +577,7 @@
     LY_LIST_INSERT(LIST, NEW_ITEM, LINKER)
 
 /**
- * @brief allocate and insert new item into linked list.
+ * @brief Allocate and insert new item into linked list, goto specified label in case of error.
  *
  * @param[in] CTX used for logging.
  * @param[in,out] LIST Linked list to add to.
diff --git a/src/parser_yin.c b/src/parser_yin.c
index 3576471..914f6f9 100644
--- a/src/parser_yin.c
+++ b/src/parser_yin.c
@@ -3210,20 +3210,28 @@
     return LY_SUCCESS;
 }
 
-LY_ERR
-yin_parse_arg_inext_known(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, enum ly_stmt elem_type, 
-                          enum ly_stmt parent, struct lysp_stmt **args)
+/**
+ * @brief Parse argument of extension subelement that is classic yang keyword and not another instance of extension.
+ *
+ * @param[in,out] ctx Yin parser context for logging and to store current state.
+ * @param[in] attrs [Sized array](@ref sizedarrays) of attributes of extension instance.
+ * @param[in,out] data Data to read from, always moved to currently handled character.
+ * @param[in] elem_type Type of element that is currently being parsed.
+ * @param[out] arg Value to write to.
+ *
+ * @return LY_ERR values.
+ */
+static LY_ERR
+yin_parse_arg_inext_known(struct yin_parser_ctx *ctx, struct yin_arg_record *attrs, const char **data, enum ly_stmt elem_type,
+                          const char **arg)
 {
     LY_ERR ret = LY_SUCCESS;
-    struct lysp_stmt *arg;
     char *out = NULL;
     const char *name, *prefix;
     size_t out_len, name_len, prefix_len;
     int dynamic;
     enum ly_stmt child;
 
-    LY_LIST_NEW_RET(ctx->xml_ctx.ctx, args, arg, next);
-
     switch (elem_type) {
     case LY_STMT_ACTION:
     case LY_STMT_ANYDATA:
@@ -3251,12 +3259,12 @@
     case LY_STMT_TYPEDEF:
     case LY_STMT_UNITS:
     case LY_STMT_USES:
-        LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, &arg->arg, Y_MAYBE_STR_ARG, elem_type));
+        LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NAME, arg, Y_MAYBE_STR_ARG, elem_type));
         break;
     case LY_STMT_AUGMENT:
     case LY_STMT_DEVIATION:
     case LY_STMT_REFINE:
-        LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_TARGET_NODE, &arg->arg, Y_MAYBE_STR_ARG, elem_type));
+        LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_TARGET_NODE, arg, Y_MAYBE_STR_ARG, elem_type));
         break;
     case LY_STMT_CONFIG:
     case LY_STMT_DEFAULT:
@@ -3281,30 +3289,30 @@
     case LY_STMT_VALUE:
     case LY_STMT_YANG_VERSION:
     case LY_STMT_YIN_ELEMENT:
-        LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, &arg->arg, Y_MAYBE_STR_ARG, elem_type));
+        LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_VALUE, arg, Y_MAYBE_STR_ARG, elem_type));
         break;
     case LY_STMT_IMPORT:
     case LY_STMT_INCLUDE:
     case LY_STMT_BELONGS_TO:
-        LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_MODULE, &arg->arg, Y_MAYBE_STR_ARG, elem_type));
+        LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_MODULE, arg, Y_MAYBE_STR_ARG, elem_type));
         break;
     case LY_STMT_INPUT:
     case LY_STMT_OUTPUT:
-        LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NONE, &arg->arg, Y_MAYBE_STR_ARG, elem_type));
+        LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NONE, arg, Y_MAYBE_STR_ARG, elem_type));
         break;
     case LY_STMT_MUST:
     case LY_STMT_WHEN:
-        LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_CONDITION, &arg->arg, Y_MAYBE_STR_ARG, elem_type));
+        LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_CONDITION, arg, Y_MAYBE_STR_ARG, elem_type));
         break;
     case LY_STMT_NAMESPACE:
-        LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_URI, &arg->arg, Y_MAYBE_STR_ARG, elem_type));
+        LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_URI, arg, Y_MAYBE_STR_ARG, elem_type));
         break;
     case LY_STMT_REVISION:
     case LY_STMT_REVISION_DATE:
-        LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_DATE, &arg->arg, Y_MAYBE_STR_ARG, elem_type));
+        LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_DATE, arg, Y_MAYBE_STR_ARG, elem_type));
         break;
     case LY_STMT_UNIQUE:
-        LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_TAG, &arg->arg, Y_MAYBE_STR_ARG, elem_type));
+        LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_TAG, arg, Y_MAYBE_STR_ARG, elem_type));
         break;
     /* argument is mapped to yin element */
     case LY_STMT_CONTACT:
@@ -3312,22 +3320,29 @@
     case LY_STMT_ORGANIZATION:
     case LY_STMT_REFERENCE:
     case LY_STMT_ERROR_MESSAGE:
-        /* there should be no attribute, argument is supposed to be first subelement */
-        LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NONE, &arg->arg, Y_MAYBE_STR_ARG, elem_type));
+        /* there shouldn't be any attribute, argument is supposed to be first subelement */
+        LY_CHECK_RET(yin_parse_attribute(ctx, attrs, YIN_ARG_NONE, arg, Y_MAYBE_STR_ARG, elem_type));
         ret = lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic);
-        /* TODO fix message */
-        LY_CHECK_ERR_RET(ret != LY_EINVAL, LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_FIRT_SUBELEM, ly_stmt2str(elem_type), parent), LY_EVALID);
+        LY_CHECK_ERR_RET(ret != LY_EINVAL, LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_FIRT_SUBELEM,
+                                                         elem_type == LY_STMT_ERROR_MESSAGE ? "value" : "text", ly_stmt2str(elem_type)),
+                        LY_EVALID);
         LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
         child = yin_match_keyword(ctx, name, name_len, prefix, prefix_len, elem_type);
-        if ((elem_type == LY_STMT_ERROR_MESSAGE && child != LY_STMT_ARG_VALUE) || child != LY_STMT_ARG_TEXT) {
-            LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, name_len, name, elem_type);
+        if ((elem_type == LY_STMT_ERROR_MESSAGE && child == LY_STMT_ARG_VALUE) ||
+            (elem_type != LY_STMT_ERROR_MESSAGE && child == LY_STMT_ARG_TEXT)) {
+            LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, name_len, name, ly_stmt2str(elem_type));
             return LY_EVALID;
         }
         /* load and save content */
         LY_CHECK_RET(lyxml_get_string(&ctx->xml_ctx, data, &out, &out_len, &out, &out_len, &dynamic));
-        INSERT_STRING(ctx->xml_ctx.ctx, arg->arg, dynamic, out, out_len);
-        /* load closing tag */
+        INSERT_STRING(ctx->xml_ctx.ctx, *arg, dynamic, out, out_len);
+        LY_CHECK_RET(!*arg, LY_EMEM);
+        /* load closing tag of subelement */
         LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
+        /* if only subelement was parsed as argument, load also closing tag */
+        if (ctx->xml_ctx.status == LYXML_ELEMENT) {
+            LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &prefix, &prefix_len, &name, &name_len));
+        }
         break;
     default:
         LOGINT(ctx->xml_ctx.ctx);
@@ -3338,7 +3353,7 @@
 }
 
 LY_ERR
-yin_parse_element_generic(struct yin_parser_ctx *ctx, const char *name, size_t name_len, const char *prefix, size_t prefix_len, enum ly_stmt parent, 
+yin_parse_element_generic(struct yin_parser_ctx *ctx, const char *name, size_t name_len, const char *prefix, size_t prefix_len, enum ly_stmt parent,
                           const char **data, struct lysp_stmt **element)
 {
     LY_ERR ret = LY_SUCCESS;
@@ -3359,23 +3374,23 @@
 
     ret = yin_load_attributes(ctx, data, &attrs);
     LY_CHECK_GOTO(ret, cleanup);
-    (*element)->kw = yin_match_keyword(ctx, name, name_len, prefix, prefix_len, LY_STMT_EXTENSION_INSTANCE);
+    (*element)->kw = yin_match_keyword(ctx, name, name_len, prefix, prefix_len, parent);
 
     last = (*element)->child;
     if ((*element)->kw == LY_STMT_NONE) {
         /* unrecognized element */
-        /* TODO set parrent correctly */
-        LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, name_len, name, ly_stmt2str(LY_STMT_EXTENSION_INSTANCE));
-        return LY_EVALID;
+        LOGVAL_PARSER((struct lys_parser_ctx *)ctx, LY_VCODE_UNEXP_SUBELEM, name_len, name, ly_stmt2str(parent));
+        ret = LY_EVALID;
+        goto cleanup;
     } else if ((*element)->kw != LY_STMT_EXTENSION_INSTANCE) {
         /* element is known yang keyword, which means argument can be parsed correctly. */
-        LY_CHECK_RET(yin_parse_arg_inext_known(ctx, attrs, data, (*element)->kw, parent, &(*element)->child));
+        ret = yin_parse_arg_inext_known(ctx, attrs, data, (*element)->kw, &(*element)->arg);
+        LY_CHECK_GOTO(ret, cleanup);
     } else {
-        /* load attributes in generic way
-        /* save all attributes in linked list */
+        /* load attributes in generic way, save all attributes in linked list */
         LY_ARRAY_FOR(attrs, struct yin_arg_record, iter) {
             new = calloc(1, sizeof(*last));
-            LY_CHECK_ERR_RET(!new, LOGMEM(ctx->xml_ctx.ctx), LY_EMEM);
+            LY_CHECK_ERR_GOTO(!new, LOGMEM(ctx->xml_ctx.ctx); ret = LY_EMEM, cleanup);
             if (!(*element)->child) {
                 /* save first */
                 (*element)->child = new;
@@ -3390,7 +3405,7 @@
             /* attributes with prefix are ignored */
             if (!iter->prefix) {
                 INSERT_STRING(ctx->xml_ctx.ctx, last->arg, iter->dynamic_content, iter->content, iter->content_len);
-                LY_CHECK_RET(!last->arg, LY_EMEM);
+                LY_CHECK_ERR_GOTO(!last->arg, ret = LY_EMEM, cleanup);
                 /* string is no longer supposed to be freed when the array is freed */
                 iter->dynamic_content = 0;
             }
@@ -3403,12 +3418,14 @@
         if (ret == LY_EINVAL) {
             while (ctx->xml_ctx.status == LYXML_ELEMENT) {
                 /* parse subelements */
-                LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &temp_prefix, &temp_prefix_len, &temp_name, &temp_name_len));
+                ret = lyxml_get_element(&ctx->xml_ctx, data, &temp_prefix, &temp_prefix_len, &temp_name, &temp_name_len);
+                LY_CHECK_GOTO(ret , cleanup);
                 if (!temp_name) {
                     /* end of element reached */
                     break;
                 }
-                LY_CHECK_RET(yin_parse_element_generic(ctx, temp_name, temp_name_len, temp_prefix, temp_prefix_len, (*element)->kw, data, &new));
+                ret = yin_parse_element_generic(ctx, temp_name, temp_name_len, temp_prefix, temp_prefix_len, (*element)->kw, data, &new);
+                LY_CHECK_GOTO(ret, cleanup);
                 if (!(*element)->child) {
                     /* save first */
                     (*element)->child = new;
@@ -3419,15 +3436,16 @@
             }
         ret = LY_SUCCESS;
         } else {
-            LY_CHECK_RET(ret);
+            LY_CHECK_GOTO(ret, cleanup);
             /* save element content */
             if (out_len != 0) {
                 INSERT_STRING(ctx->xml_ctx.ctx, (*element)->arg, dynamic, out, out_len);
-                LY_CHECK_RET(!(*element)->arg, LY_EMEM);
+                LY_CHECK_ERR_GOTO(!(*element)->arg, ret = LY_EMEM, cleanup);
             }
 
             /* read closing tag */
-            LY_CHECK_RET(lyxml_get_element(&ctx->xml_ctx, data, &temp_prefix, &temp_prefix_len, &temp_name, &temp_name_len));
+            ret = lyxml_get_element(&ctx->xml_ctx, data, &temp_prefix, &temp_prefix_len, &temp_name, &temp_name_len);
+            LY_CHECK_GOTO(ret, cleanup);
         }
     }
 
diff --git a/src/parser_yin.h b/src/parser_yin.h
index 2e6bc93..0e5d56c 100644
--- a/src/parser_yin.h
+++ b/src/parser_yin.h
@@ -215,7 +215,7 @@
  * @return yang_keyword values.
  */
 enum ly_stmt yin_match_keyword(struct yin_parser_ctx *ctx, const char *name, size_t name_len,
-                                    const char *prefix, size_t prefix_len, enum ly_stmt parrent);
+                               const char *prefix, size_t prefix_len, enum ly_stmt parrent);
 
 /**
  * @brief Load all attributes of element into ([sized array](@ref sizedarrays)). Caller is suposed to free the array.
@@ -260,7 +260,7 @@
  *
  * @return LY_ERR values.
  */
-LY_ERR yin_parse_element_generic(struct yin_parser_ctx *ctx, const char *name, size_t name_len, const char *prefix, size_t prefix_len, enum ly_stmt parent, 
+LY_ERR yin_parse_element_generic(struct yin_parser_ctx *ctx, const char *name, size_t name_len, const char *prefix, size_t prefix_len, enum ly_stmt parent,
                                  const char **data, struct lysp_stmt **element);
 
 /**
diff --git a/tests/src/test_parser_yin.c b/tests/src/test_parser_yin.c
index 63d0ef8..80736c9 100644
--- a/tests/src/test_parser_yin.c
+++ b/tests/src/test_parser_yin.c
@@ -66,7 +66,7 @@
 int store = -1; /* negative for infinite logging, positive for limited logging */
 
 /* set to 0 to printing error messages to stderr instead of checking them in code */
-#define ENABLE_LOGGER_CHECKING 1
+#define ENABLE_LOGGER_CHECKING 0
 
 #if ENABLE_LOGGER_CHECKING
 static void
@@ -531,6 +531,42 @@
     LY_ARRAY_FREE(exts);
     exts = NULL;
     args = NULL;
+    st = reset_state(state);
+
+    data = "<myext:extension-elem xmlns:myext=\"urn:example:extensions\" xmlns:yin=\"urn:ietf:params:xml:ns:yang:yin:1\">"
+                "<yin:action name=\"act-name\" pre:prefixed=\"ignored\"/>"
+                "<yin:augment target-node=\"target\"/>"
+                "<yin:status value=\"value\"/>"
+                "<yin:include module=\"mod\"/>"
+                "<yin:input />"
+                "<yin:must condition=\"cond\"/>"
+                "<yin:namespace uri=\"uri\"/>"
+                "<yin:revision date=\"data\"/>"
+                "<yin:unique tag=\"tag\"/>"
+                "<yin:contact><text>contact-val</text></yin:contact>"
+                "<yin:error-message><value>err-msg</value></yin:error-message>"
+           "</myext:extension-elem>";
+    lyxml_get_element(&st->yin_ctx->xml_ctx, &data, &prefix, &prefix_len, &name, &name_len);
+    yin_load_attributes(st->yin_ctx, &data, &args);
+    ret = yin_parse_extension_instance(st->yin_ctx, args, &data, name, name_len, LYEXT_SUBSTMT_CONTACT, 0, &exts);
+    assert_int_equal(ret, LY_SUCCESS);
+    assert_string_equal(exts->child->arg, "act-name");
+    assert_string_equal(exts->child->next->arg, "target");
+    assert_string_equal(exts->child->next->next->arg, "value");
+    assert_string_equal(exts->child->next->next->next->arg, "mod");
+    assert_null(exts->child->next->next->next->next->arg);
+    assert_string_equal(exts->child->next->next->next->next->next->arg, "cond");
+    assert_string_equal(exts->child->next->next->next->next->next->next->arg, "uri");
+    assert_string_equal(exts->child->next->next->next->next->next->next->next->arg, "data");
+    assert_string_equal(exts->child->next->next->next->next->next->next->next->next->arg, "tag");
+    assert_string_equal(exts->child->next->next->next->next->next->next->next->next->next->arg, "contact-val");
+    assert_int_equal(st->yin_ctx->xml_ctx.status, LYXML_END);
+    LY_ARRAY_FREE(args);
+    lysp_ext_instance_free(st->ctx, exts);
+    LY_ARRAY_FREE(exts);
+    exts = NULL;
+    args = NULL;
+    st = reset_state(state);
 
     st->finished_correctly = true;
 }
@@ -546,12 +582,12 @@
                             "<myext:custom xmlns:myext=\"urn:example:extensions\">"
                                 "totally amazing extension"
                             "</myext:custom>"
-                            "<myext:extension name=\"ext\" xmlns:myext=\"urn:example:extensions\">"
+                            "<extension name=\"ext\">"
                                 "<argument name=\"argname\"></argument>"
                                 "<description><text>desc</text></description>"
                                 "<reference><text>ref</text></reference>"
                                 "<status value=\"deprecated\"></status>"
-                            "</myext:extension>"
+                            "</extension>"
                             "<text xmlns=\"urn:ietf:params:xml:ns:yang:yin:1\">wsefsdf</text>"
                             "<if-feature name=\"foo\"></if-feature>"
                             "<when condition=\"condition...\">"
@@ -613,7 +649,7 @@
     assert_int_equal(st->yin_ctx->xml_ctx.status, LYXML_END);
     /* check parsed values */
     assert_string_equal(def, "default-value");
-    assert_string_equal(exts->name, "custom");
+    assert_string_equal(exts->name, "myext:custom");
     assert_string_equal(exts->argument, "totally amazing extension");
     assert_string_equal(value, "wsefsdf");
     assert_string_equal(units, "radians");