extensions CHANGE support for restrictions in extension instance

- length, pattern, range and must
diff --git a/src/parser_yin.c b/src/parser_yin.c
index fc71930..58a919d 100644
--- a/src/parser_yin.c
+++ b/src/parser_yin.c
@@ -415,7 +415,7 @@
 
 /* logs directly */
 static int
-read_restr_substmt(struct lys_module *module, LYEXT_PAR restr_type, struct lys_restr *restr, struct lyxml_elem *yin,
+read_restr_substmt(struct lys_module *module, struct lys_restr *restr, struct lyxml_elem *yin,
                    struct unres_schema *unres)
 {
     struct lyxml_elem *child, *next;
@@ -427,7 +427,7 @@
             continue;
         } else if (strcmp(child->ns->value, LY_NSYIN)) {
             /* extension */
-            if (lyp_yin_parse_subnode_ext(module, restr, restr_type, child, LYEXT_SUBSTMT_SELF, 0, unres)) {
+            if (lyp_yin_parse_subnode_ext(module, restr, LYEXT_PAR_RESTR, child, LYEXT_SUBSTMT_SELF, 0, unres)) {
                 return EXIT_FAILURE;
             }
         } else if (!strcmp(child->name, "description")) {
@@ -435,7 +435,7 @@
                 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
                 return EXIT_FAILURE;
             }
-            if (lyp_yin_parse_subnode_ext(module, restr, restr_type, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
+            if (lyp_yin_parse_subnode_ext(module, restr, LYEXT_PAR_RESTR, child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
                 return EXIT_FAILURE;
             }
             restr->dsc = read_yin_subnode(module->ctx, child, "text");
@@ -447,7 +447,7 @@
                 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
                 return EXIT_FAILURE;
             }
-            if (lyp_yin_parse_subnode_ext(module, restr, restr_type, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
+            if (lyp_yin_parse_subnode_ext(module, restr, LYEXT_PAR_RESTR, child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
                 return EXIT_FAILURE;
             }
             restr->ref = read_yin_subnode(module->ctx, child, "text");
@@ -459,7 +459,7 @@
                 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
                 return EXIT_FAILURE;
             }
-            if (lyp_yin_parse_subnode_ext(module, restr, restr_type, child, LYEXT_SUBSTMT_ERRTAG, 0, unres)) {
+            if (lyp_yin_parse_subnode_ext(module, restr, LYEXT_PAR_RESTR, child, LYEXT_SUBSTMT_ERRTAG, 0, unres)) {
                 return EXIT_FAILURE;
             }
             GETVAL(value, child, "value");
@@ -469,7 +469,7 @@
                 LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
                 return EXIT_FAILURE;
             }
-            if (lyp_yin_parse_subnode_ext(module, restr, restr_type, child, LYEXT_SUBSTMT_ERRMSG, 0, unres)) {
+            if (lyp_yin_parse_subnode_ext(module, restr, LYEXT_PAR_RESTR, child, LYEXT_SUBSTMT_ERRMSG, 0, unres)) {
                 return EXIT_FAILURE;
             }
             restr->emsg = read_yin_subnode(module->ctx, child, "value");
@@ -836,7 +836,7 @@
                 type->info.dec64.range->expr = lydict_insert(module->ctx, value, 0);
 
                 /* get possible substatements */
-                if (read_restr_substmt(module, LYEXT_PAR_RESTR, type->info.dec64.range, node, unres)) {
+                if (read_restr_substmt(module, type->info.dec64.range, node, unres)) {
                     goto error;
                 }
             } else if (!strcmp(node->name, "fraction-digits")) {
@@ -1228,7 +1228,7 @@
                 (*restrs)->expr = lydict_insert(module->ctx, value, 0);
 
                 /* get possible substatements */
-                if (read_restr_substmt(module, LYEXT_PAR_RESTR, *restrs, node, unres)) {
+                if (read_restr_substmt(module, *restrs, node, unres)) {
                     goto error;
                 }
             } else {
@@ -1345,7 +1345,7 @@
                 type->info.str.length->expr = lydict_insert(module->ctx, value, 0);
 
                 /* get possible sub-statements */
-                if (read_restr_substmt(module, LYEXT_PAR_RESTR, type->info.str.length, node, unres)) {
+                if (read_restr_substmt(module, type->info.str.length, node, unres)) {
                     goto error;
                 }
                 lyxml_free(module->ctx, node);
@@ -1391,8 +1391,8 @@
                             }
                             /* get extensions of the modifier */
                             if (lyp_yin_parse_subnode_ext(module, restr, LYEXT_PAR_RESTR, child,
-                                                     LYEXT_SUBSTMT_MODIFIER, 0, unres)) {
-                                return EXIT_FAILURE;
+                                                          LYEXT_SUBSTMT_MODIFIER, 0, unres)) {
+                                goto error;
                             }
 
                             lyxml_free(module->ctx, child);
@@ -1408,7 +1408,7 @@
                 restr->expr = lydict_insert_zc(module->ctx, buf);
 
                 /* get possible sub-statements */
-                if (read_restr_substmt(module, LYEXT_PAR_RESTR, restr, node, unres)) {
+                if (read_restr_substmt(module, restr, node, unres)) {
                     free(type->info.str.patterns);
                     type->info.str.patterns = NULL;
                     goto error;
@@ -1817,7 +1817,7 @@
         goto error;
     }
 
-    return read_restr_substmt(module, LYEXT_PAR_RESTR, must, yin, unres);
+    return read_restr_substmt(module, must, yin, unres);
 
 error:
     return EXIT_FAILURE;
@@ -7528,21 +7528,17 @@
 lyp_yin_parse_complex_ext(struct lys_module *mod, struct lys_ext_instance_complex *ext, struct lyxml_elem *yin,
                           struct unres_schema *unres)
 {
-    struct lyxml_elem *next, *node;
+    struct lyxml_elem *next, *node, *child;
     struct lys_type **type;
     void **pp, *p, *reallocated;
-    const char *value;
-    char *endptr;
+    const char *value, *name;
+    char *endptr, modifier;
     struct lyext_substmt *info;
     long int v;
     long long int ll;
     unsigned long u;
     int i;
 
-#define YIN_EXTCOMPLEX_PARSE_SNODE(STMT, FUNC, ARGS...)                              \
-    pp = (void**)yin_getplace_for_extcomplex_node(node, ext, STMT);                  \
-    if (!pp) { goto error; }                                                         \
-    if (!FUNC(mod, (struct lys_node*)ext, node, ##ARGS, unres)) { goto error; }
 #define YIN_EXTCOMPLEX_GETPLACE(STMT, TYPE)                                          \
     p = lys_ext_complex_get_substmt(STMT, ext, &info);                               \
     if (!p) {                                                                        \
@@ -7575,7 +7571,19 @@
         *pp = reallocated;                                   \
         (*(TYPE**)pp)[i + 1] = 0;                            \
     }
-
+#define YIN_EXTCOMPLEX_PARSE_SNODE(STMT, FUNC, ARGS...)                              \
+    pp = (void**)yin_getplace_for_extcomplex_node(node, ext, STMT);                  \
+    if (!pp) { goto error; }                                                         \
+    if (!FUNC(mod, (struct lys_node*)ext, node, ##ARGS, unres)) { goto error; }
+#define YIN_EXTCOMPLEX_PARSE_RESTR(STMT)                                             \
+    YIN_EXTCOMPLEX_GETPLACE(STMT, struct lys_restr*);                                \
+    GETVAL(value, node, "value");                                                    \
+    *(struct lys_restr **)p = calloc(1, sizeof(struct lys_restr));                   \
+    (*(struct lys_restr **)p)->expr = lydict_insert(mod->ctx, value, 0);             \
+    if (read_restr_substmt(mod, *(struct lys_restr **)p, node, unres)) {             \
+        goto error;                                                                  \
+    }                                                                                \
+    YIN_EXTCOMPLEX_ENLARGE(struct lys_restr*);
 
     LY_TREE_FOR_SAFE(yin->child, next, node) {
         if (!node->ns) {
@@ -7895,6 +7903,69 @@
             YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_NOTIFICATION, read_yin_notif);
         } else if (!strcmp(node->name, "uses")) {
             YIN_EXTCOMPLEX_PARSE_SNODE(LY_STMT_USES, read_yin_uses);
+        } else if (!strcmp(node->name, "length")) {
+            YIN_EXTCOMPLEX_PARSE_RESTR(LY_STMT_LENGTH);
+        } else if (!strcmp(node->name, "must")) {
+            pp = yin_getplace_for_extcomplex_struct(node, ext, LY_STMT_MUST);
+            if (!pp) {
+                goto error;
+            }
+            /* allocate structure for must */
+            (*pp) = calloc(1, sizeof(struct lys_restr));
+
+            if (fill_yin_must(mod, node, *((struct lys_restr **)pp), unres)) {
+                goto error;
+            }
+        } else if (!strcmp(node->name, "pattern")) {
+            YIN_EXTCOMPLEX_GETPLACE(LY_STMT_PATTERN, struct lys_restr*);
+            GETVAL(value, node, "value");
+            if (lyp_check_pattern(value, NULL)) {
+                goto error;
+            }
+
+            *(struct lys_restr **)p = calloc(1, sizeof(struct lys_restr));
+            (*(struct lys_restr **)p)->expr = lydict_insert(mod->ctx, value, 0);
+
+            modifier = 0x06; /* ACK */
+            if (mod->version >= 2) {
+                name = NULL;
+                LY_TREE_FOR(node->child, child) {
+                    if (child->ns && !strcmp(child->ns->value, LY_NSYIN) && !strcmp(child->name, "modifier")) {
+                        if (name) {
+                            LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "modifier", node->name);
+                            goto error;
+                        }
+
+                        GETVAL(name, child, "value");
+                        if (!strcmp(name, "invert-match")) {
+                            modifier = 0x15; /* NACK */
+                        } else {
+                            LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, name, "modifier");
+                            goto error;
+                        }
+                        /* get extensions of the modifier */
+                        if (lyp_yin_parse_subnode_ext(mod, *(struct lys_restr **)p, LYEXT_PAR_RESTR, child,
+                                                      LYEXT_SUBSTMT_MODIFIER, 0, unres)) {
+                            goto error;
+                        }
+                    }
+                }
+            }
+
+            /* store the value: modifier byte + value + terminating NULL byte */
+            (*(struct lys_restr **)p)->expr = malloc((strlen(value) + 2) * sizeof(char));
+            ((char *)(*(struct lys_restr **)p)->expr)[0] = modifier;
+            strcpy(&((char *)(*(struct lys_restr **)p)->expr)[1], value);
+            lydict_insert_zc(mod->ctx, (char *)(*(struct lys_restr **)p)->expr);
+
+            /* get possible sub-statements */
+            if (read_restr_substmt(mod, *(struct lys_restr **)p, node, unres)) {
+                goto error;
+            }
+
+            YIN_EXTCOMPLEX_ENLARGE(struct lys_restr*);
+        } else if (!strcmp(node->name, "range")) {
+            YIN_EXTCOMPLEX_PARSE_RESTR(LY_STMT_RANGE);
         } else {
             LOGERR(LY_SUCCESS, "Extension's substatement \"%s\" not yet supported.", node->name);
             //LOGERR(LY_EINT, "Extension's substatement \"%s\" not yet supported.", node->name);