all CHANGE validation error messages updated

Now all SPEC errors should be preceded with
one that sets the vecode to a specific error.
diff --git a/src/parser.c b/src/parser.c
index 6c69b13..7f0b537 100644
--- a/src/parser.c
+++ b/src/parser.c
@@ -136,6 +136,7 @@
                 return result;
             } else {
                 /* there is already another revision of the submodule */
+                LOGVAL(LYE_INARG, 0, LY_VLOG_NONE, NULL, result->rev[0].date, "revision");
                 LOGVAL(LYE_SPEC, 0, 0, NULL, "Multiple revisions of a submodule included.");
                 return NULL;
             }
@@ -1116,7 +1117,8 @@
                 !strcmp(id, "leafref") || !strcmp(id, "string") ||
                 !strcmp(id, "uint8") || !strcmp(id, "uint16") ||
                 !strcmp(id, "uint32") || !strcmp(id, "uint64") || !strcmp(id, "union")) {
-            LOGVAL(LYE_SPEC, line, 0, NULL, "Typedef name duplicates built-in type.");
+            LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, id, "typedef");
+            LOGVAL(LYE_SPEC, 0, 0, NULL, "Typedef name duplicates a built-in type.");
             return EXIT_FAILURE;
         }
 
@@ -1319,7 +1321,8 @@
         return 4;
     } else {
         /* out of range */
-        LOGVAL(LYE_SPEC, line, 0, NULL, "Invalid UTF-8 value 0x%08x", value);
+        LOGVAL(LYE_XML_INCHAR, line, LY_VLOG_NONE, NULL, value);
+        LOGVAL(LYE_SPEC, 0, 0, NULL, "Invalid UTF-8 value 0x%08x", value);
         return 0;
     }
 }
diff --git a/src/parser_yin.c b/src/parser_yin.c
index 8997684..2621b6c 100644
--- a/src/parser_yin.c
+++ b/src/parser_yin.c
@@ -304,7 +304,7 @@
         }
         if (!type->der->type.der && !type->info.bits.count) {
             /* type is derived directly from buit-in bits type and bit statement is required */
-            LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_NONE, NULL, "bit", "type");
+            LOGVAL(LYE_MISSCHILDSTMT, LOGLINE(yin), LY_VLOG_NONE, NULL, "bit", "type");
             goto error;
         }
         if (type->der->type.der && type->info.bits.count) {
@@ -325,7 +325,6 @@
 
             GETVAL(value, next, "name");
             if (lyp_check_identifier(value, LY_IDENT_SIMPLE, LOGLINE(next), NULL, NULL)) {
-                LOGVAL(LYE_PATH, 0, LY_VLOG_NONE, NULL);
                 goto error;
             }
 
@@ -460,7 +459,7 @@
         /* mandatory sub-statement(s) check */
         if (!type->info.dec64.dig && !type->der->type.der) {
             /* decimal64 type directly derived from built-in type requires fraction-digits */
-            LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_NONE, NULL, "fraction-digits", "type");
+            LOGVAL(LYE_MISSCHILDSTMT, LOGLINE(yin), LY_VLOG_NONE, NULL, "fraction-digits", "type");
             goto error;
         }
         if (type->info.dec64.dig && type->der->type.der) {
@@ -490,7 +489,7 @@
         }
         if (!type->der->type.der && !type->info.enums.count) {
             /* type is derived directly from buit-in enumeartion type and enum statement is required */
-            LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_NONE, NULL, "enum", "type");
+            LOGVAL(LYE_MISSCHILDSTMT, LOGLINE(yin), LY_VLOG_NONE, NULL, "enum", "type");
             goto error;
         }
         if (type->der->type.der && type->info.enums.count) {
@@ -511,7 +510,8 @@
 
             GETVAL(value, next, "name");
             if (!value[0]) {
-                LOGVAL(LYE_SPEC, LOGLINE(next), LY_VLOG_NONE, NULL, "Enum name must not be empty.");
+                LOGVAL(LYE_INARG, LOGLINE(next), LY_VLOG_NONE, NULL, value, "enum name");
+                LOGVAL(LYE_SPEC, 0, 0, NULL, "Enum name must not be empty.");
                 goto error;
             }
             type->info.enums.enm[i].name = lydict_insert(module->ctx, value, strlen(value));
@@ -612,7 +612,7 @@
                 /* this is just a derived type with no base specified/required */
                 break;
             }
-            LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_NONE, NULL, "base", "type");
+            LOGVAL(LYE_MISSCHILDSTMT, LOGLINE(yin), LY_VLOG_NONE, NULL, "base", "type");
             goto error;
         }
         if (yin->child->next) {
@@ -754,7 +754,7 @@
         }
 
         if (!type->info.lref.path && !type->der->type.der) {
-            LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_NONE, NULL, "path", "type");
+            LOGVAL(LYE_MISSCHILDSTMT, LOGLINE(yin), LY_VLOG_NONE, NULL, "path", "type");
             goto error;
         }
         break;
@@ -855,7 +855,7 @@
                 /* this is just a derived type with no additional type specified/required */
                 break;
             }
-            LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_NONE, NULL, "type", "(union) type");
+            LOGVAL(LYE_MISSCHILDSTMT, LOGLINE(yin), LY_VLOG_NONE, NULL, "type", "(union) type");
             goto error;
         }
 
@@ -985,7 +985,7 @@
 
     /* check mandatory value */
     if (!has_type) {
-        LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_NONE, NULL, "type", yin->name);
+        LOGVAL(LYE_MISSCHILDSTMT, LOGLINE(yin), LY_VLOG_NONE, NULL, "type", yin->name);
         goto error;
     }
 
@@ -1268,7 +1268,8 @@
         goto error;
     }
     if (dev_target->module == lys_module(module)) {
-        LOGVAL(LYE_SPEC, LOGLINE(yin), LY_VLOG_NONE, NULL, "Deviating own module is not allowed.");
+        LOGVAL(LYE_INARG, LOGLINE(yin), LY_VLOG_NONE, NULL, dev->target_name, yin->name);
+        LOGVAL(LYE_SPEC, 0, 0, NULL, "Deviating own module is not allowed.");
         goto error;
     }
     /* mark the target module as deviated */
@@ -1954,7 +1955,8 @@
             if (rc == -1) {
                 goto error;
             } else if (rc == EXIT_FAILURE) {
-                LOGVAL(LYE_SPEC, LOGLINE(yin), 0, NULL, "Leaf \"%s\" default value no longer matches its type.", dev->target_name);
+                LOGVAL(LYE_INARG, LOGLINE(yin), LY_VLOG_NONE, NULL, leaf_dflt_check[i]->dflt, "default");
+                LOGVAL(LYE_SPEC, 0, 0, NULL, "Leaf \"%s\" default value no longer matches its type.", dev->target_name);
                 goto error;
             }
         }
@@ -2123,7 +2125,8 @@
             if (rfn->target_type) {
                 rfn->target_type &= (LYS_LEAF | LYS_CHOICE);
                 if (!rfn->target_type) {
-                    LOGVAL(LYE_SPEC, LOGLINE(sub), LY_VLOG_NONE, NULL, "invalid combination of refine substatements");
+                    LOGVAL(LYE_MISSCHILDSTMT, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name, yin->name);
+                    LOGVAL(LYE_SPEC, 0, 0, NULL, "Invalid refine target nodetype for the substatements.");
                     goto error;
                 }
             } else {
@@ -2147,7 +2150,8 @@
             if (rfn->target_type) {
                 rfn->target_type &= (LYS_LEAF | LYS_CHOICE | LYS_ANYXML);
                 if (!rfn->target_type) {
-                    LOGVAL(LYE_SPEC, LOGLINE(sub), LY_VLOG_NONE, NULL, "invalid combination of refine substatements");
+                    LOGVAL(LYE_MISSCHILDSTMT, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name, yin->name);
+                    LOGVAL(LYE_SPEC, 0, 0, NULL, "Invalid refine target nodetype for the substatements.");
                     goto error;
                 }
             } else {
@@ -2175,7 +2179,8 @@
             if (rfn->target_type) {
                 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
                 if (!rfn->target_type) {
-                    LOGVAL(LYE_SPEC, LOGLINE(sub), LY_VLOG_NONE, NULL, "invalid combination of refine substatements");
+                    LOGVAL(LYE_MISSCHILDSTMT, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name, yin->name);
+                    LOGVAL(LYE_SPEC, 0, 0, NULL, "Invalid refine target nodetype for the substatements.");
                     goto error;
                 }
             } else {
@@ -2211,7 +2216,8 @@
             if (rfn->target_type) {
                 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST);
                 if (!rfn->target_type) {
-                    LOGVAL(LYE_SPEC, LOGLINE(sub), LY_VLOG_NONE, NULL, "invalid combination of refine substatements");
+                    LOGVAL(LYE_MISSCHILDSTMT, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name, yin->name);
+                    LOGVAL(LYE_SPEC, 0, 0, NULL, "Invalid refine target nodetype for the substatements.");
                     goto error;
                 }
             } else {
@@ -2250,7 +2256,8 @@
             if (rfn->target_type) {
                 rfn->target_type &= LYS_CONTAINER;
                 if (!rfn->target_type) {
-                    LOGVAL(LYE_SPEC, LOGLINE(sub), LY_VLOG_NONE, NULL, "invalid combination of refine substatements");
+                    LOGVAL(LYE_MISSCHILDSTMT, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name, yin->name);
+                    LOGVAL(LYE_SPEC, 0, 0, NULL, "Invalid refine target nodetype for the substatements.");
                     goto error;
                 }
             } else {
@@ -2265,7 +2272,8 @@
             if (rfn->target_type) {
                 rfn->target_type &= (LYS_LIST | LYS_LEAFLIST | LYS_CONTAINER | LYS_ANYXML);
                 if (!rfn->target_type) {
-                    LOGVAL(LYE_SPEC, LOGLINE(sub), LY_VLOG_NONE, NULL, "invalid combination of refine substatements");
+                    LOGVAL(LYE_MISSCHILDSTMT, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name, yin->name);
+                    LOGVAL(LYE_SPEC, 0, 0, NULL, "Invalid refine target nodetype for the substatements.");
                     goto error;
                 }
             } else {
@@ -2344,7 +2352,7 @@
 
     /* check mandatory information */
     if (!imp->prefix) {
-        LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_NONE, NULL, "prefix", yin->name);
+        LOGVAL(LYE_MISSCHILDSTMT, LOGLINE(yin), LY_VLOG_NONE, NULL, "prefix", yin->name);
         goto error;
     }
 
@@ -2489,8 +2497,8 @@
     if (inc->submodule) {
         if (inc->rev[0]) {
             if (!inc->submodule->rev_size || !ly_strequal(inc->rev, inc->submodule->rev[0].date, 1)) {
-                LOGVAL(LYE_SPEC, LOGLINE(yin), LY_VLOG_NONE, NULL,
-                       "Multiple revisions of the same submodule included.");
+                LOGVAL(LYE_INARG, LOGLINE(yin), LY_VLOG_NONE, NULL, inc->rev[0], "revision");
+                LOGVAL(LYE_SPEC, 0, 0, NULL, "Multiple revisions of the same submodule included.");
                 goto error;
             }
         }
@@ -2984,8 +2992,8 @@
 
     /* check - default is prohibited in combination with mandatory */
     if (dflt_str && (choice->flags & LYS_MAND_TRUE)) {
-        LOGVAL(LYE_SPEC, LOGLINE(yin), LY_VLOG_NONE, NULL,
-               "The \"default\" statement MUST NOT be present on choices where \"mandatory\" is true.");
+        LOGVAL(LYE_INCHILDSTMT, LOGLINE(yin), LY_VLOG_NONE, NULL, "default", "choice");
+        LOGVAL(LYE_SPEC, 0, 0, NULL, "The \"default\" statement is forbidden on choices with \"mandatory\".");
         goto error;
     }
 
@@ -3244,7 +3252,7 @@
 
     /* check mandatory parameters */
     if (!has_type) {
-        LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_NONE, NULL, "type", yin->name);
+        LOGVAL(LYE_MISSCHILDSTMT, LOGLINE(yin), LY_VLOG_NONE, NULL, "type", yin->name);
         goto error;
     }
     if (leaf->dflt) {
@@ -3410,6 +3418,11 @@
                 goto error;
             }
             llist->min = (uint32_t) val;
+            if (llist->max && (llist->min > llist->max)) {
+                LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_NONE, NULL, value, sub->name);
+                LOGVAL(LYE_SPEC, 0, 0, NULL, "\"min-elements\" is bigger than \"max-elements\".");
+                goto error;
+            }
         } else if (!strcmp(sub->name, "max-elements")) {
             if (f_max) {
                 LOGVAL(LYE_TOOMANY, LOGLINE(sub), LY_VLOG_NONE, NULL, sub->name, yin->name);
@@ -3434,6 +3447,11 @@
                     goto error;
                 }
                 llist->max = (uint32_t) val;
+                if (llist->min > llist->max) {
+                    LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_NONE, NULL, value, sub->name);
+                    LOGVAL(LYE_SPEC, 0, 0, NULL, "\"max-elements\" is smaller than \"min-elements\".");
+                    goto error;
+                }
             }
         } else if (!strcmp(sub->name, "when")) {
             if (llist->when) {
@@ -3455,11 +3473,7 @@
 
     /* check constraints */
     if (!has_type) {
-        LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_NONE, NULL, "type", yin->name);
-        goto error;
-    }
-    if (llist->max && llist->min > llist->max) {
-        LOGVAL(LYE_SPEC, LOGLINE(yin), LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
+        LOGVAL(LYE_MISSCHILDSTMT, LOGLINE(yin), LY_VLOG_NONE, NULL, "type", yin->name);
         goto error;
     }
 
@@ -3643,6 +3657,12 @@
                 goto error;
             }
             list->min = (uint32_t) val;
+            if (list->max && (list->min > list->max)) {
+                LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_NONE, NULL, value, sub->name);
+                LOGVAL(LYE_SPEC, 0, 0, NULL, "\"min-elements\" is bigger than \"max-elements\".");
+                lyxml_free(module->ctx, sub);
+                goto error;
+            }
             lyxml_free(module->ctx, sub);
         } else if (!strcmp(sub->name, "max-elements")) {
             if (f_max) {
@@ -3668,6 +3688,11 @@
                     goto error;
                 }
                 list->max = (uint32_t) val;
+                if (list->min > list->max) {
+                    LOGVAL(LYE_INARG, LOGLINE(sub), LY_VLOG_NONE, NULL, value, sub->name);
+                    LOGVAL(LYE_SPEC, 0, 0, NULL, "\"max-elements\" is smaller than \"min-elements\".");
+                    goto error;
+                }
             }
             lyxml_free(module->ctx, sub);
         } else if (!strcmp(sub->name, "when")) {
@@ -3690,11 +3715,7 @@
 
     /* check - if list is configuration, key statement is mandatory */
     if ((list->flags & LYS_CONFIG_W) && !key_str) {
-        LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_NONE, NULL, "key", "list");
-        goto error;
-    }
-    if (list->max && list->min > list->max) {
-        LOGVAL(LYE_SPEC, LOGLINE(yin), LY_VLOG_NONE, NULL, "\"min-elements\" is bigger than \"max-elements\".");
+        LOGVAL(LYE_MISSCHILDSTMT, LOGLINE(yin), LY_VLOG_NONE, NULL, "key", "list");
         goto error;
     }
 
@@ -4720,7 +4741,7 @@
 
             /* get the prefix substatement, start with checks */
             if (!child->child) {
-                LOGVAL(LYE_MISSSTMT2, LOGLINE(child), LY_VLOG_NONE, NULL, "prefix", child->name);
+                LOGVAL(LYE_MISSCHILDSTMT, LOGLINE(child), LY_VLOG_NONE, NULL, "prefix", child->name);
                 goto error;
             } else if (strcmp(child->child->name, "prefix")) {
                 LOGVAL(LYE_INSTMT, LOGLINE(child->child), LY_VLOG_NONE, NULL, child->child->name);
@@ -4866,15 +4887,15 @@
 
     /* check for mandatory statements */
     if (submodule && !submodule->prefix) {
-        LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_NONE, NULL, "belongs-to", "submodule");
+        LOGVAL(LYE_MISSCHILDSTMT, LOGLINE(yin), LY_VLOG_NONE, NULL, "belongs-to", "submodule");
         goto error;
     } else if (!submodule) {
         if (!module->ns) {
-            LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_NONE, NULL, "namespace", "module");
+            LOGVAL(LYE_MISSCHILDSTMT, LOGLINE(yin), LY_VLOG_NONE, NULL, "namespace", "module");
             goto error;
         }
         if (!module->prefix) {
-            LOGVAL(LYE_MISSSTMT2, LOGLINE(yin), LY_VLOG_NONE, NULL, "prefix", "module");
+            LOGVAL(LYE_MISSCHILDSTMT, LOGLINE(yin), LY_VLOG_NONE, NULL, "prefix", "module");
             goto error;
         }
     }
@@ -4954,7 +4975,8 @@
             /* check duplicities in imported modules */
             for (i = 0; i < trg->imp_size - 1; i++) {
                 if (!strcmp(trg->imp[i].module->name, trg->imp[trg->imp_size - 1].module->name)) {
-                    LOGVAL(LYE_SPEC, LOGLINE(child), LY_VLOG_NONE, NULL, "Importing module \"%s\" repeatedly.", trg->imp[i].module->name);
+                    LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_NONE, NULL, trg->imp[i].module->name, "import");
+                    LOGVAL(LYE_SPEC, 0, 0, NULL, "Importing module \"%s\" repeatedly.", trg->imp[i].module->name);
                     goto error;
                 }
             }
@@ -4974,8 +4996,8 @@
             /* check duplications in include submodules */
             for (i = 0; i < inc_size_aux - 1; i++) {
                 if (trg->inc[i].submodule && !strcmp(trg->inc[i].submodule->name, trg->inc[inc_size_aux - 1].submodule->name)) {
-                    LOGVAL(LYE_SPEC, LOGLINE(child), LY_VLOG_NONE, NULL, "Including submodule \"%s\" repeatedly.",
-                        trg->inc[i].submodule->name);
+                    LOGVAL(LYE_INARG, LOGLINE(child), LY_VLOG_NONE, NULL, trg->inc[i].submodule->name, "include");
+                    LOGVAL(LYE_SPEC, 0, 0, NULL, "Including submodule \"%s\" repeatedly.", trg->inc[i].submodule->name);
                     goto error;
                 }
             }
diff --git a/src/resolve.c b/src/resolve.c
index 205d0ac..5fa8258 100644
--- a/src/resolve.c
+++ b/src/resolve.c
@@ -2901,7 +2901,8 @@
      */
     if (!aug->parent && (lys_node_module((struct lys_node *)aug) != lys_node_module(aug->target))
             && lyp_check_mandatory((struct lys_node *)aug)) {
-        LOGVAL(LYE_SPEC, line, LY_VLOG_LYS, aug, "When augmenting data in another module, mandatory nodes are not allowed.");
+        LOGVAL(LYE_INCHILDSTMT, line, LY_VLOG_LYS, aug, "mandatory", "augment node");
+        LOGVAL(LYE_SPEC, 0, 0, NULL, "When augmenting data in another module, mandatory nodes are not allowed.");
         return -1;
     }
 
@@ -2909,7 +2910,8 @@
     if (aug->target->nodetype & (LYS_CONTAINER | LYS_LIST | LYS_CASE | LYS_INPUT | LYS_OUTPUT | LYS_NOTIF)) {
         LY_TREE_FOR(aug->child, sub) {
             if (!(sub->nodetype & (LYS_ANYXML | LYS_CONTAINER | LYS_LEAF | LYS_LIST | LYS_LEAFLIST | LYS_USES | LYS_CHOICE))) {
-                LOGVAL(LYE_SPEC, line, LY_VLOG_LYS, aug, "Cannot augment \"%s\" with a \"%s\".",
+                LOGVAL(LYE_INCHILDSTMT, line, LY_VLOG_LYS, aug, strnodetype(sub->nodetype), "augment");
+                LOGVAL(LYE_SPEC, 0, 0, NULL, "Cannot augment \"%s\" with a \"%s\".",
                        strnodetype(aug->target->nodetype), strnodetype(sub->nodetype));
                 return -1;
             }
@@ -2917,13 +2919,15 @@
     } else if (aug->target->nodetype == LYS_CHOICE) {
         LY_TREE_FOR(aug->child, sub) {
             if (!(sub->nodetype & (LYS_CASE | LYS_ANYXML | LYS_CONTAINER | LYS_LEAF | LYS_LIST | LYS_LEAFLIST))) {
-                LOGVAL(LYE_SPEC, line, LY_VLOG_LYS, aug, "Cannot augment \"%s\" with a \"%s\".",
+                LOGVAL(LYE_INCHILDSTMT, line, LY_VLOG_LYS, aug, strnodetype(sub->nodetype), "augment");
+                LOGVAL(LYE_SPEC, 0, 0, NULL, "Cannot augment \"%s\" with a \"%s\".",
                        strnodetype(aug->target->nodetype), strnodetype(sub->nodetype));
                 return -1;
             }
         }
     } else {
-        LOGVAL(LYE_SPEC, line, LY_VLOG_LYS, aug, "Invalid augment target node type \"%s\".", strnodetype(aug->target->nodetype));
+        LOGVAL(LYE_INARG, line, LY_VLOG_LYS, aug, aug->target_name, "target-node");
+        LOGVAL(LYE_SPEC, 0, 0, NULL, "Invalid augment target node type \"%s\".", strnodetype(aug->target->nodetype));
         return -1;
     }
 
@@ -2982,7 +2986,8 @@
     LY_TREE_FOR(uses->grp->child, node_aux) {
         node = lys_node_dup(uses->module, (struct lys_node *)uses, node_aux, uses->flags, uses->nacm, unres, 0);
         if (!node) {
-            LOGVAL(LYE_SPEC, line, LY_VLOG_LYS, uses, "Copying data from grouping failed.");
+            LOGVAL(LYE_INARG, line, LY_VLOG_LYS, uses, uses->grp->name, "uses");
+            LOGVAL(LYE_SPEC, 0, 0, NULL, "Copying data from grouping failed.");
             return -1;
         }
     }
@@ -3001,7 +3006,8 @@
         }
 
         if (rfn->target_type && !(node->nodetype & rfn->target_type)) {
-            LOGVAL(LYE_SPEC, line, LY_VLOG_LYS, uses, "Refine substatements not applicable to the target-node.");
+            LOGVAL(LYE_INARG, line, LY_VLOG_LYS, uses, rfn->target_name, "refine");
+            LOGVAL(LYE_SPEC, 0, 0, NULL, "Refine substatements not applicable to the target-node.");
             return -1;
         }
 
@@ -3191,7 +3197,8 @@
         /* check for circular reference */
         for (base_iter = base; base_iter; base_iter = base_iter->base) {
             if (ident == base_iter) {
-                LOGVAL(LYE_SPEC, 0, 0, NULL, "Circular reference of \"%s\" identity", basename);
+                LOGVAL(LYE_INARG, 0, LY_VLOG_NONE, NULL, base_iter->name, "base");
+                LOGVAL(LYE_SPEC, 0, 0, NULL, "Circular reference of \"%s\" identity.", basename);
                 return EXIT_FAILURE;
             }
         }
@@ -3952,7 +3959,6 @@
     } while (res_count && (res_count < unres_count));
 
     if (res_count < unres_count) {
-        LOGVAL(LYE_SPEC, 0, 0, NULL, "There are unresolved uses left.");
         return -1;
     }
 
@@ -3973,7 +3979,6 @@
     }
 
     if (resolved < unres->count) {
-        LOGVAL(LYE_SPEC, 0, 0, NULL, "There are unresolved schema items left.");
         return -1;
     }
 
@@ -4246,8 +4251,8 @@
         if (!leaf->value.leafref) {
             /* reference not found */
             if (!first) {
-                LOGVAL(LYE_SPEC, line, LY_VLOG_LYD, leaf, "Leafref \"%s\" value \"%s\" did not match any node value.",
-                       sleaf->type.info.lref.path, leaf->value_str);
+                LOGVAL(LYE_NORESOLV, line, LY_VLOG_LYD, leaf, sleaf->type.info.lref.path);
+                LOGVAL(LYE_SPEC, 0, 0, NULL, "Leafref value \"%s\" did not match any node value.", leaf->value_str);
             }
             return EXIT_FAILURE;
         }
@@ -4262,7 +4267,7 @@
                 return -1;
             } else if (sleaf->type.info.inst.req > -1) {
                 if (!first) {
-                    LOGVAL(LYE_SPEC, line, LY_VLOG_LYD, leaf, "There is no instance of \"%s\".", leaf->value_str);
+                    LOGVAL(LYE_NORESOLV, line, LY_VLOG_LYD, leaf, leaf->value_str);
                 }
                 return EXIT_FAILURE;
             } else {
@@ -4355,7 +4360,6 @@
     for (i = 0; i < unres->count; ++i) {
         rc = resolve_unres_data_item(unres->node[i], unres->type[i], 0, LOGLINE_IDX(unres, i));
         if (rc) {
-            LOGVAL(LYE_SPEC, 0, 0, NULL, "There are unresolved data items left.");
             return -1;
         }
     }
diff --git a/src/tree_data.c b/src/tree_data.c
index 1b580e5..70277fb 100644
--- a/src/tree_data.c
+++ b/src/tree_data.c
@@ -711,7 +711,8 @@
             schema = ly_check_mandatory(NULL, ctx->models.list[i]->data);
             if (schema) {
                 if (schema->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
-                    LOGVAL(LYE_SPEC, 0, LY_VLOG_LYS, schema,
+                    LOGVAL(LYE_TOOMANY, 0, LY_VLOG_LYS, schema, schema->name, schema->parent ? schema->parent->name : "module");
+                    LOGVAL(LYE_SPEC, 0, 0, NULL,
                            "Number of \"%s\" instances in \"%s\" does not follow min-elements constraint.",
                            schema->name, schema->parent ? schema->parent->name : ctx->models.list[i]->name);
                 } else {
diff --git a/src/tree_schema.c b/src/tree_schema.c
index f68d16b..11ea27b 100644
--- a/src/tree_schema.c
+++ b/src/tree_schema.c
@@ -800,8 +800,7 @@
 
             if (iter->nodetype & (LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_CONTAINER | LYS_CHOICE | LYS_ANYXML)) {
                 if (iter->module == node->module && ly_strequal(iter->name, node->name, 1)) {
-                    LOGVAL(LYE_SPEC, 0, LY_VLOG_LYS, node, "Duplicated child identifier \"%s\" in \"%s\".", node->name,
-                           stop ? stop->name : "(sub)module");
+                    LOGVAL(LYE_DUPID, 0, LY_VLOG_LYS, node, strnodetype(node->nodetype), node->name);
                     return EXIT_FAILURE;
                 }
             }
@@ -887,8 +886,7 @@
         if (!(child->nodetype &
                 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_GROUPING | LYS_LEAF |
                  LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
-            LOGVAL(LYE_SPEC, 0, LY_VLOG_LYS, parent, "Unexpected substatement \"%s\" in \"%s\" (%s).",
-                   strnodetype(child->nodetype), strnodetype(parent->nodetype), parent->name);
+            LOGVAL(LYE_INCHILDSTMT, 0, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
             return EXIT_FAILURE;
         }
 
@@ -896,38 +894,35 @@
     case LYS_CHOICE:
         if (!(child->nodetype &
                 (LYS_ANYXML | LYS_CASE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST))) {
-            LOGVAL(LYE_SPEC, 0, LY_VLOG_LYS, parent, "Unexpected substatement \"%s\" in \"choice\" %s.",
-                   strnodetype(child->nodetype), parent->name);
+            LOGVAL(LYE_INCHILDSTMT, 0, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "choice");
             return EXIT_FAILURE;
         }
         break;
     case LYS_CASE:
         if (!(child->nodetype &
                 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
-            LOGVAL(LYE_SPEC, 0, LY_VLOG_LYS, parent, "Unexpected substatement \"%s\" in \"case\" %s.",
-                   strnodetype(child->nodetype), parent->name);
+            LOGVAL(LYE_INCHILDSTMT, 0, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "case");
             return EXIT_FAILURE;
         }
         break;
     case LYS_RPC:
         if (!(child->nodetype & (LYS_INPUT | LYS_OUTPUT | LYS_GROUPING))) {
-            LOGVAL(LYE_SPEC, 0, LY_VLOG_LYS, parent, "Unexpected substatement \"%s\" in \"rpc\" %s.",
-                   strnodetype(child->nodetype), parent->name);
+            LOGVAL(LYE_INCHILDSTMT, 0, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "rpc");
             return EXIT_FAILURE;
         }
         break;
     case LYS_LEAF:
     case LYS_LEAFLIST:
     case LYS_ANYXML:
-        LOGVAL(LYE_SPEC, 0, LY_VLOG_LYS, parent, "The \"%s\" statement (%s) cannot have any data substatement.",
-               strnodetype(parent->nodetype), parent->name);
+        LOGVAL(LYE_INCHILDSTMT, 0, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
+        LOGVAL(LYE_SPEC, 0, 0, NULL, "The \"%s\" statement cannot have any data substatement.",
+               strnodetype(parent->nodetype));
         return EXIT_FAILURE;
     case LYS_AUGMENT:
         if (!(child->nodetype &
                 (LYS_ANYXML | LYS_CASE | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF
                 | LYS_LEAFLIST | LYS_LIST | LYS_USES))) {
-            LOGVAL(LYE_SPEC, 0, LY_VLOG_LYS, parent, "Unexpected substatement \"%s\" in \"%s\" (%s).",
-                   strnodetype(child->nodetype), strnodetype(parent->nodetype), parent->name);
+            LOGVAL(LYE_INCHILDSTMT, 0, LY_VLOG_LYS, parent, strnodetype(child->nodetype), strnodetype(parent->nodetype));
             return EXIT_FAILURE;
         }
         break;
@@ -936,8 +931,7 @@
         if (!(child->nodetype &
                 (LYS_ANYXML | LYS_CHOICE | LYS_CONTAINER | LYS_LEAF | LYS_GROUPING
                 | LYS_LEAFLIST | LYS_LIST | LYS_USES | LYS_RPC | LYS_NOTIF | LYS_AUGMENT))) {
-            LOGVAL(LYE_SPEC, 0, LY_VLOG_LYS, parent, "Unexpected substatement \"%s\" in (sub)module \"%s\"",
-                   strnodetype(child->nodetype), module->name);
+            LOGVAL(LYE_INCHILDSTMT, 0, LY_VLOG_LYS, parent, strnodetype(child->nodetype), "(sub)module");
             return EXIT_FAILURE;
         }
 
diff --git a/src/validation.c b/src/validation.c
index 5b85c60..bf9d642 100644
--- a/src/validation.c
+++ b/src/validation.c
@@ -416,9 +416,7 @@
             siter = ly_check_mandatory(node, NULL);
             if (siter) {
                 if (siter->nodetype & (LYS_LIST | LYS_LEAFLIST)) {
-                    LOGVAL(LYE_SPEC, line, LY_VLOG_LYD, node,
-                           "Number of \"%s\" instances in \"%s\" does not follow min/max constraints.",
-                           siter->name, siter->parent->name);
+                    LOGVAL(LYE_INCOUNT, line, LY_VLOG_LYD, node, siter->name, siter->parent->name);
                 } else {
                     LOGVAL(LYE_MISSELEM, line, LY_VLOG_LYD, node, siter->name, siter->parent->name);
                 }
diff --git a/src/xml.c b/src/xml.c
index 91e7299..46eca05 100644
--- a/src/xml.c
+++ b/src/xml.c
@@ -999,8 +999,8 @@
 
                         /* look for the prefix in namespaces */
                         if (memcmp(prefix, c, e - c)) {
-                            LOGVAL(LYE_SPEC, lineno, LY_VLOG_XML, elem,
-                                   "Mixed opening (%s) and closing element tags (different namespaces).", elem->name);
+                            LOGVAL(LYE_XML_INVAL, lineno, LY_VLOG_XML, elem,
+                                   "(different namespaces) opening (%s) and closing element tags", elem->name);
                             goto error;
                         }
                         c = start;
@@ -1023,8 +1023,8 @@
                 memcpy(str, c, e - c);
                 str[e - c] = '\0';
                 if (size != strlen(elem->name) || memcmp(str, elem->name, size)) {
-                    LOGVAL(LYE_SPEC, lineno, LY_VLOG_XML, elem,
-                           "Mixed opening (%s) and closing (%s) element tags.", elem->name, str);
+                    LOGVAL(LYE_XML_INVAL, lineno, LY_VLOG_XML, elem,
+                           "(mixed names) opening (%s) and closing (%s) element tags", elem->name, str);
                     free(str);
                     goto error;
                 }
@@ -1033,8 +1033,8 @@
 
                 ign_xmlws(c);
                 if (*c != '>') {
-                    LOGVAL(LYE_SPEC, lineno, LY_VLOG_XML, elem,
-                           "Close element tag \"%s\" contain additional data.", elem->name);
+                    LOGVAL(LYE_XML_INVAL, lineno, LY_VLOG_XML, elem,
+                           "data after closing element tag \"%s\"", elem->name);
                     goto error;
                 }
                 c++;
diff --git a/src/xpath.c b/src/xpath.c
index 6a4799d..67e8ce5 100644
--- a/src/xpath.c
+++ b/src/xpath.c
@@ -5584,7 +5584,8 @@
         }
 
         if (!xpath_func) {
-            LOGVAL(LYE_SPEC, line, 0, NULL,
+            LOGVAL(LYE_XPATH_INTOK, line, LY_VLOG_NONE, NULL, "Unknown", &exp->expr[exp->expr_pos[*exp_idx]]);
+            LOGVAL(LYE_SPEC, 0, 0, NULL,
                    "Unknown XPath function \"%.*s\".", exp->tok_len[*exp_idx], &exp->expr[exp->expr_pos[*exp_idx]]);
             return -1;
         }
@@ -5679,11 +5680,13 @@
         errno = 0;
         num = strtold(&exp->expr[exp->expr_pos[*exp_idx]], &endptr);
         if (errno) {
-            LOGVAL(LYE_SPEC, line, 0, NULL, "Failed to convert \"%.*s\" into a long double (%s).",
+            LOGVAL(LYE_XPATH_INTOK, line, LY_VLOG_NONE, NULL, "Unknown", &exp->expr[exp->expr_pos[*exp_idx]]);
+            LOGVAL(LYE_SPEC, 0, 0, NULL, "Failed to convert \"%.*s\" into a long double (%s).",
                    exp->tok_len[*exp_idx], &exp->expr[exp->expr_pos[*exp_idx]], strerror(errno));
             return -1;
         } else if (endptr - &exp->expr[exp->expr_pos[*exp_idx]] != exp->tok_len[*exp_idx]) {
-            LOGVAL(LYE_SPEC, line, 0, NULL, "Failed to convert \"%.*s\" into a long double.",
+            LOGVAL(LYE_XPATH_INTOK, line, LY_VLOG_NONE, NULL, "Unknown", &exp->expr[exp->expr_pos[*exp_idx]]);
+            LOGVAL(LYE_SPEC, 0, 0, NULL, "Failed to convert \"%.*s\" into a long double.",
                    exp->tok_len[*exp_idx], &exp->expr[exp->expr_pos[*exp_idx]]);
             return -1;
         }
@@ -6464,7 +6467,8 @@
         exp_idx = 0;
         rc = reparse_expr(exp, &exp_idx, line);
         if (!rc && (exp->used > exp_idx)) {
-            LOGVAL(LYE_SPEC, line, 0, NULL, "Unparsed characters \"%s\" left at the end of an XPath expression.",
+            LOGVAL(LYE_XPATH_INTOK, line, LY_VLOG_NONE, NULL, "Unknown", &exp->expr[exp->expr_pos[exp_idx]]);
+            LOGVAL(LYE_SPEC, 0, 0, NULL, "Unparsed characters \"%s\" left at the end of an XPath expression.",
                    &exp->expr[exp->expr_pos[exp_idx]]);
             rc = -1;
         }
@@ -6507,7 +6511,8 @@
         exp_idx = 0;
         rc = reparse_expr(exp, &exp_idx, line);
         if (!rc && (exp->used > exp_idx)) {
-            LOGVAL(LYE_SPEC, line, 0, NULL, "Unparsed characters \"%s\" left at the end of an XPath expression.",
+            LOGVAL(LYE_XPATH_INTOK, line, LY_VLOG_NONE, NULL, "Unknown", &exp->expr[exp->expr_pos[exp_idx]]);
+            LOGVAL(LYE_SPEC, 0, 0, NULL, "Unparsed characters \"%s\" left at the end of an XPath expression.",
                    &exp->expr[exp->expr_pos[exp_idx]]);
             rc = -1;
         }