schema tree CHANGE better checking of name collisions
diff --git a/src/parser_yang.c b/src/parser_yang.c
index 5435eab..ab6f7ac 100644
--- a/src/parser_yang.c
+++ b/src/parser_yang.c
@@ -46,6 +46,16 @@
#define is_yangidentchar(c) ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') || \
c == '_' || c == '-' || c == '.')
+#define CHECK_UNIQUENESS(CTX, ARRAY, MEMBER, STMT, IDENT) \
+ if (ARRAY) { \
+ for (unsigned int u = 0; u < LY_ARRAY_SIZE(ARRAY) - 1; ++u) { \
+ if (!strcmp((ARRAY)[u].MEMBER, IDENT)) { \
+ LOGVAL_YANG(CTX, LY_VCODE_DUPIDENT, IDENT, STMT); \
+ return LY_EVALID; \
+ } \
+ } \
+ }
+
#define INSERT_WORD(CTX, BUF, TARGET, WORD, LEN) \
if (BUF) {(TARGET) = lydict_insert_zc((CTX)->ctx, WORD);}\
else {(TARGET) = lydict_insert((CTX)->ctx, WORD, LEN);}
@@ -1305,6 +1315,13 @@
INSERT_WORD(ctx, buf, inc->name, word, word_len);
+ /* submodules share the namespace with the module names, so there must not be
+ * a module of the same name in the context, no need for revision matching */
+ if (!strcmp(ctx->mod->name, inc->name) || ly_ctx_get_module_latest(ctx->ctx, inc->name)) {
+ LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Name collision between module and submodule of name \"%s\".", inc->name);
+ return LY_EVALID;
+ }
+
YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
switch (kw) {
case YANG_DESCRIPTION:
@@ -4304,8 +4321,10 @@
/* get value */
ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
LY_CHECK_RET(ret);
-
INSERT_WORD(ctx, buf, feat->name, word, word_len);
+
+ CHECK_UNIQUENESS(ctx, *features, name, "feature", feat->name);
+
YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
LY_CHECK_RET(ret);
@@ -4359,8 +4378,10 @@
/* get value */
ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
LY_CHECK_RET(ret);
-
INSERT_WORD(ctx, buf, ident->name, word, word_len);
+
+ CHECK_UNIQUENESS(ctx, *identities, name, "identity", ident->name);
+
YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
LY_CHECK_RET(ret);
@@ -4414,8 +4435,16 @@
/* (sub)module name */
ret = get_argument(ctx, data, Y_IDENTIF_ARG, &word, &buf, &word_len);
LY_CHECK_RET(ret);
-
INSERT_WORD(ctx, buf, mod->name, word, word_len);
+
+ /* submodules share the namespace with the module names, so there must not be
+ * a submodule of the same name in the context, no need for revision matching */
+ if (ly_ctx_get_submodule(ctx->ctx, NULL, mod->name, NULL)) {
+ LOGVAL_YANG(ctx, LYVE_SYNTAX_YANG, "Name collision between %s of name \"%s\".",
+ mod->submodule ? "submodules" : "module and submodule", mod->name);
+ return LY_EVALID;
+ }
+
YANG_READ_SUBSTMT_FOR(ctx, data, kw, word, word_len, ret) {
LY_CHECK_RET(ret);
@@ -4641,6 +4670,7 @@
mod->submodule = 1;
}
mod->ctx = ctx;
+ context.mod = mod;
/* substatements */
ret = parse_sub_module(&context, &data, mod);