schema parsers CHANGE check for prefix duplicity
diff --git a/src/log.h b/src/log.h
index d1b159e..b5d6834 100644
--- a/src/log.h
+++ b/src/log.h
@@ -161,6 +161,8 @@
     LYVE_SUCCESS = 0,  /**< no error */
     LYVE_SYNTAX,       /**< generic syntax error */
     LYVE_SYNTAX_YANG,  /**< YANG-related syntax error */
+    LYVE_REFERENCE,    /**< invalid referencing or using an item */
+    LYVE_SEMANTICS     /**< generic semantic error */
 } LY_VECODE;
 
 /**
diff --git a/src/parser_yang.c b/src/parser_yang.c
index f69a3bb..b098a45 100644
--- a/src/parser_yang.c
+++ b/src/parser_yang.c
@@ -27,12 +27,7 @@
 #include "common.h"
 #include "context.h"
 #include "libyang.h"
-
-struct ly_parser_ctx {
-    struct ly_ctx *ctx;
-    uint64_t line;      /* line number */
-    uint64_t indent;    /* current position on the line for indentation */
-};
+#include "tree_schema_internal.h"
 
 /* Macro to check YANG's yang-char grammar rule */
 #define is_yangutf8char(c) ((c >= 0x20 && c <= 0xd77) || c == 0x09 || c == 0x0a || c == 0x0d || \
@@ -1340,7 +1335,7 @@
  * @return LY_ERR values.
  */
 static LY_ERR
-parse_import(struct ly_parser_ctx *ctx, const char **data, struct lysp_import **imports)
+parse_import(struct ly_parser_ctx *ctx, const char **data, struct lysp_module *module)
 {
     LY_ERR ret = 0;
     char *buf, *word;
@@ -1348,7 +1343,7 @@
     enum yang_keyword kw;
     struct lysp_import *imp;
 
-    LYSP_ARRAY_NEW_RET(ctx, imports, imp, LY_EVALID);
+    LYSP_ARRAY_NEW_RET(ctx, &module->imports, imp, LY_EVALID);
 
     /* get value */
     ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
@@ -1361,6 +1356,7 @@
         switch (kw) {
         case YANG_PREFIX:
             ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, &imp->prefix, Y_IDENTIF_ARG, &imp->exts);
+            LY_CHECK_RET(lysp_check_prefix(ctx, module, &imp->prefix), LY_EVALID);
             break;
         case YANG_DESCRIPTION:
             ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_DESCRIPTION, 0, &imp->dsc, Y_STR_ARG, &imp->exts);
@@ -4507,6 +4503,7 @@
             break;
         case YANG_PREFIX:
             ret = parse_text_field(ctx, data, LYEXT_SUBSTMT_PREFIX, 0, &mod->prefix, Y_IDENTIF_ARG, &mod->exts);
+            LY_CHECK_RET(lysp_check_prefix(ctx, mod, &mod->prefix), LY_EVALID);
             break;
         case YANG_BELONGS_TO:
             ret = parse_belongsto(ctx, data, &mod->belongsto, &mod->prefix, &mod->exts);
@@ -4517,7 +4514,7 @@
             ret = parse_include(ctx, data, &mod->includes);
             break;
         case YANG_IMPORT:
-            ret = parse_import(ctx, data, &mod->imports);
+            ret = parse_import(ctx, data, mod);
             break;
 
         /* meta */
diff --git a/src/tree_schema.c b/src/tree_schema.c
index 489e965..1df393f 100644
--- a/src/tree_schema.c
+++ b/src/tree_schema.c
@@ -14,6 +14,7 @@
 
 #include "libyang.h"
 #include "common.h"
+#include "tree_schema_internal.h"
 
 #define FREE_ARRAY(CTX, ARRAY, ITER, FUNC) LY_ARRAY_FOR(ARRAY, ITER){FUNC(CTX, &ARRAY[ITER]);}free(ARRAY);
 #define FREE_MEMBER(CTX, MEMBER, FUNC) if (MEMBER) {FUNC(CTX, MEMBER);free(MEMBER);}
@@ -486,3 +487,25 @@
 
     free(module);
 }
+
+LY_ERR
+lysp_check_prefix(struct ly_parser_ctx *ctx, struct lysp_module *module, const char **value)
+{
+    unsigned int u;
+
+    if (module->prefix && &module->prefix != value && !strcmp(module->prefix, *value)) {
+        LOGVAL(ctx->ctx, LY_VLOG_LINE, &ctx->line, LYVE_REFERENCE,
+               "Prefix \"%s\" already used as module prefix.", *value);
+        return LY_EEXIST;
+    }
+    if (module->imports) {
+        LY_ARRAY_FOR(module->imports, u) {
+            if (module->imports[u].prefix && &module->imports[u].prefix != value && !strcmp(module->imports[u].prefix, *value)) {
+                LOGVAL(ctx->ctx, LY_VLOG_LINE, &ctx->line, LYVE_REFERENCE,
+                       "Prefix \"%s\" already used to import \"%s\" module.", *value, module->imports[u].name);
+                return LY_EEXIST;
+            }
+        }
+    }
+    return LY_SUCCESS;
+}
diff --git a/src/tree_schema.h b/src/tree_schema.h
index 6266427..ffd188a 100644
--- a/src/tree_schema.h
+++ b/src/tree_schema.h
@@ -17,6 +17,10 @@
 
 #include <stdint.h>
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 /**
  * @defgroup schematree Schema Tree
  * @{
@@ -745,4 +749,8 @@
 
 /** @} */
 
+#ifdef __cplusplus
+}
+#endif
+
 #endif /* LY_TREE_SCHEMA_H_ */
diff --git a/src/tree_schema_internal.h b/src/tree_schema_internal.h
new file mode 100644
index 0000000..dda9593
--- /dev/null
+++ b/src/tree_schema_internal.h
@@ -0,0 +1,37 @@
+/**
+ * @file tree_schema_internal.h
+ * @author Radek Krejci <rkrejci@cesnet.cz>
+ * @brief internal functions for YANG schema trees.
+ *
+ * Copyright (c) 2015 - 2018 CESNET, z.s.p.o.
+ *
+ * This source code is licensed under BSD 3-Clause License (the "License").
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://opensource.org/licenses/BSD-3-Clause
+ */
+
+#ifndef LY_TREE_SCHEMA_INTERNAL_H_
+#define LY_TREE_SCHEMA_INTERNAL_H_
+
+/**
+ * @brief internal context for schema parsers
+ */
+struct ly_parser_ctx {
+    struct ly_ctx *ctx;
+    uint64_t line;      /* line number */
+    uint64_t indent;    /* current position on the line for YANG indentation */
+};
+
+/**
+ * @brief Check the currently present prefixes in the module for collision with the new one.
+ *
+ * @param[in] ctx yang parser context.
+ * @param[in] module Schema tree to check.
+ * @param[in] value Newly added prefix value (including its location to distinguish collision with itself).
+ * @return LY_EEXIST when prefix is already used in the module, LY_SUCCESS otherwise
+ */
+LY_ERR lysp_check_prefix(struct ly_parser_ctx *ctx, struct lysp_module *module, const char **value);
+
+#endif /* LY_TREE_SCHEMA_INTERNAL_H_ */
diff --git a/tests/src/test_parser_yang.c b/tests/src/test_parser_yang.c
index 3c98be1..24035a9 100644
--- a/tests/src/test_parser_yang.c
+++ b/tests/src/test_parser_yang.c
@@ -29,7 +29,7 @@
 char logbuf[BUFSIZE] = {0};
 
 /* set to 0 to printing error messages to stderr instead of checking them in code */
-#define ENABLE_LOGGER_CHECKING 0
+#define ENABLE_LOGGER_CHECKING 1
 
 #if ENABLE_LOGGER_CHECKING
 static void
@@ -705,6 +705,12 @@
     logbuf_assert("Duplicate keyword \"prefix\". Line number 1.");
     mod = mod_renew(&ctx, mod);
 
+    /* not allowed in module (submodule-specific) */
+    str = SCHEMA_BEGINNING "belongs-to master {prefix m;}}";
+    assert_int_equal(LY_EVALID, parse_sub_module(&ctx, &str, mod));
+    logbuf_assert("Invalid keyword \"belongs-to\" as a child of \"module\". Line number 1.");
+    mod = mod_renew(&ctx, mod);
+
     /* anydata */
     TEST_NODE(LYS_ANYDATA, "anydata test;}", "test");
     /* anyxml */
@@ -740,13 +746,13 @@
     /* import */
     TEST_GENERIC("import test {prefix z;}}", mod->imports,
                  assert_string_equal("test", mod->imports[0].name));
-#if 0
+
     /* import - prefix collision */
     str = SCHEMA_BEGINNING "import test {prefix x;}}";
     assert_int_equal(LY_EVALID, parse_sub_module(&ctx, &str, mod));
-    logbuf_assert("Duplicate keyword \"namespace\". Line number 1.");
+    logbuf_assert("Prefix \"x\" already used as module prefix. Line number 2.");
     mod = mod_renew(&ctx, mod);
-#endif
+
     /* include */
     TEST_GENERIC("rpc test;}", mod->rpcs,
                  assert_string_equal("test", mod->rpcs[0].name));