schema parser CHANGE improve circular dependency detection

It took a long time to detect circular dependency. The reviewed code
should be able to detect it earlier without other confusing messages.
diff --git a/src/common.h b/src/common.h
index 315e170..51cb24e 100644
--- a/src/common.h
+++ b/src/common.h
@@ -164,6 +164,8 @@
     LYE_INRESOLV,
     LYE_INSTATUS,
     LYE_CIRC_LEAFREFS,
+    LYE_CIRC_IMPORTS,
+    LYE_CIRC_INCLUDES,
 
     LYE_OBSDATA,
     LYE_OBSTYPE,
diff --git a/src/context.h b/src/context.h
index f1481e8..a75afe2 100644
--- a/src/context.h
+++ b/src/context.h
@@ -25,6 +25,8 @@
     int used;
     struct lys_module **list;
     const char **parsing;
+    uint8_t parsing_size;
+    uint8_t parsing_number;
     uint16_t module_set_id;
 };
 
diff --git a/src/libyang.h b/src/libyang.h
index 71823b2..ea2c65c 100644
--- a/src/libyang.h
+++ b/src/libyang.h
@@ -1169,6 +1169,8 @@
     LYVE_INRESOLV,     /**< no resolvents found (schema) */
     LYVE_INSTATUS,     /**< invalid derivation because of status (schema) */
     LYVE_CIRC_LEAFREFS,/**< circular chain of leafrefs detected (schema) */
+    LYVE_CIRC_IMPORTS, /**< circular chain of imports detected (schema) */
+    LYVE_CIRC_INCLUDES,/**< circular chain of includes detected (schema) */
 
     LYVE_OBSDATA,      /**< obsolete data instantiation (data) */
     /* */
diff --git a/src/log.c b/src/log.c
index 46cff05..272ca39 100644
--- a/src/log.c
+++ b/src/log.c
@@ -161,6 +161,8 @@
 /* LYE_INRESOLV */     "Failed to resolve %s \"%s\".",
 /* LYE_INSTATUS */     "A \"%s\" definition %s references \"%s\" definition %s.",
 /* LYE_CIRC_LEAFREFS */"A circular chain of leafrefs detected.",
+/* LYE_CIRC_IMPORTS */ "A circular dependency (import) for module \"%s\".",
+/* LYE_CIRC_INCLUDES */"A circular dependency (include) for submodule \"%s\".",
 
 /* LYE_OBSDATA */      "Obsolete data \"%s\" instantiated.",
 /* LYE_OBSTYPE */      "Data node \"%s\" with obsolete type \"%s\" instantiated.",
@@ -241,6 +243,8 @@
     LYVE_INRESOLV,     /* LYE_INRESOLV */
     LYVE_INSTATUS,     /* LYE_INSTATUS */
     LYVE_CIRC_LEAFREFS,/* LYE_CIRC_LEAFREFS */
+    LYVE_CIRC_IMPORTS, /* LYE_CIRC_IMPORTS */
+    LYVE_CIRC_INCLUDES,/* LYE_CIRC_INCLUDES */
 
     LYVE_OBSDATA,      /* LYE_OBSDATA */
     LYVE_OBSDATA,      /* LYE_OBSTYPE */
diff --git a/src/parser.c b/src/parser.c
index 4cc1032..5543a9b 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -1491,6 +1491,71 @@
     return EXIT_SUCCESS;
 }
 
+static void
+lyp_check_circmod_pop(struct lys_module *module)
+{
+    struct ly_modules_list *models = &module->ctx->models;
+
+    /* update the list of currently being parsed modules */
+    models->parsing_number--;
+    if (models->parsing_number == 1) {
+        free(models->parsing);
+        models->parsing = NULL;
+        models->parsing_number = models->parsing_size = 0;
+    } else {
+        models->parsing[models->parsing_number] = NULL;
+    }
+}
+
+/*
+ * types: 0 - include, 1 - import
+ */
+static int
+lyp_check_circmod(struct lys_module *module, const char *value, int type)
+{
+    LY_ECODE code = type ? LYE_CIRC_IMPORTS : LYE_CIRC_INCLUDES;
+    struct ly_modules_list *models = &module->ctx->models;
+    int i;
+
+    /* circular import check */
+    if (!models->parsing_size) {
+        if (ly_strequal(module->name, value, 1)) {
+            LOGVAL(code, LY_VLOG_NONE, NULL, value);
+            return -1;
+        }
+
+        /* storing - first import, besides the module being imported, add also the starting module */
+        models->parsing_size = models->parsing_number = 2;
+        models->parsing = malloc(2 * sizeof *models->parsing);
+        if (!models->parsing) {
+            LOGMEM;
+            return -1;
+        }
+        models->parsing[0] = module->name;
+        models->parsing[1] = value;
+    } else {
+        for (i = 0; i < models->parsing_number; i++) {
+            if (ly_strequal(models->parsing[i], value, 1)) {
+                LOGVAL(code, LY_VLOG_NONE, NULL, value);
+                return -1;
+            }
+        }
+        /* storing - enlarge the list of modules being currently parsed */
+        models->parsing_number++;
+        if (models->parsing_number >= models->parsing_size) {
+            models->parsing_size++;
+            models->parsing = ly_realloc(models->parsing, models->parsing_size * sizeof *models->parsing);
+            if (!models->parsing) {
+                LOGMEM;
+                return -1;
+            }
+        }
+        models->parsing[models->parsing_number - 1] = value;
+    }
+
+    return 0;
+}
+
 /* returns:
  *  0 - inc successfully filled
  * -1 - error, inc is cleaned
@@ -1548,26 +1613,10 @@
         }
     }
 
-    /* check for circular include, store it if passed */
-    if (!module->ctx->models.parsing) {
-        count = 0;
-    } else {
-        for (count = 0; module->ctx->models.parsing[count]; ++count) {
-            if (ly_strequal(value, module->ctx->models.parsing[count], 1)) {
-                LOGERR(LY_EVALID, "Circular include dependency on the submodule \"%s\".", value);
-                goto error;
-            }
-        }
+    /* circular include check */
+    if (lyp_check_circmod(module, value, 0)) {
+        return -1;
     }
-    ++count;
-    module->ctx->models.parsing =
-        ly_realloc(module->ctx->models.parsing, (count + 1) * sizeof *module->ctx->models.parsing);
-    if (!module->ctx->models.parsing) {
-        LOGMEM;
-        goto error;
-    }
-    module->ctx->models.parsing[count - 1] = value;
-    module->ctx->models.parsing[count] = NULL;
 
     /* try to load the submodule */
     inc->submodule = (struct lys_submodule *)ly_ctx_get_submodule2(module, value);
@@ -1576,6 +1625,7 @@
             if (!inc->submodule->rev_size || !ly_strequal(inc->rev, inc->submodule->rev[0].date, 1)) {
                 LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, inc->rev[0], "revision");
                 LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Multiple revisions of the same submodule included.");
+                lyp_check_circmod_pop(module);
                 goto error;
             }
         }
@@ -1599,17 +1649,8 @@
         }
     }
 
-    /* remove the new submodule name now that its parsing is finished (even if failed) */
-    if (module->ctx->models.parsing[count] || !ly_strequal(module->ctx->models.parsing[count - 1], value, 1)) {
-        LOGINT;
-    }
-    --count;
-    if (count) {
-        module->ctx->models.parsing[count] = NULL;
-    } else {
-        free(module->ctx->models.parsing);
-        module->ctx->models.parsing = NULL;
-    }
+    /* update the list of currently being parsed modules */
+    lyp_check_circmod_pop(module);
 
     /* check the result */
     if (!inc->submodule) {