yin parser CHANGE support for multiple bases in identity
YANG 1.1
diff --git a/src/resolve.c b/src/resolve.c
index 99bba94..12aa5ff 100644
--- a/src/resolve.c
+++ b/src/resolve.c
@@ -4282,6 +4282,29 @@
return EXIT_SUCCESS;
}
+static int
+identity_backlink_update(struct lys_ident *der, struct lys_ident *base)
+{
+ int i;
+
+ assert(der && base);
+
+ base->der = ly_realloc(base->der, (base->der_size + 1) * sizeof *(base->der));
+ if (!base->der) {
+ LOGMEM;
+ return EXIT_FAILURE;
+ }
+ base->der[base->der_size++] = der;
+
+ for (i = 0; i < base->base_size; i++) {
+ if (identity_backlink_update(der, base->base[i])) {
+ return EXIT_FAILURE;
+ }
+ }
+
+ return EXIT_SUCCESS;
+}
+
/**
* @brief Resolve base identity recursively. Does not log.
*
@@ -4294,10 +4317,10 @@
*/
static int
resolve_base_ident_sub(const struct lys_module *module, struct lys_ident *ident, const char *basename,
- struct lys_ident **ret)
+ struct unres_schema *unres, struct lys_ident **ret)
{
uint32_t i, j;
- struct lys_ident *base = NULL, *base_iter;
+ struct lys_ident *base = NULL;
assert(ret);
@@ -4336,38 +4359,33 @@
matchfound:
/* we found it somewhere */
if (base) {
- /* check for circular reference */
- for (base_iter = base; base_iter; base_iter = base_iter->base) {
- if (ident == base_iter) {
- LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, base_iter->name, "base");
- LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Circular reference of \"%s\" identity.", basename);
- return EXIT_FAILURE;
+ /* is it already completely resolved? */
+ for (i = 0; i < unres->count; i++) {
+ if ((unres->item[i] == ident) && (unres->type[i] == UNRES_IDENT) && (unres->str_snode[i] != basename)) {
+ /* identity found, but not yet resolved, so do not return it in *res and try it again later */
+
+ /* simple check for circular reference,
+ * the complete check is done as a side effect of using only completely
+ * resolved identities (previous check of unres content) */
+ if (ly_strequal((const char *)unres->str_snode[i], ident->name, 1)) {
+ LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, basename, "base");
+ LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Circular reference of \"%s\" identity.", basename);
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
}
}
+
/* checks done, store the result */
- ident->base = base;
+ ident->base[ident->base_size++] = base;
+ *ret = base;
- /* maintain backlinks to the derived identitise */
- while (base) {
- /* 1. get current number of backlinks */
- if (base->der) {
- for (i = 0; base->der[i]; i++);
- } else {
- i = 0;
- }
- base->der = ly_realloc(base->der, (i + 2) * sizeof *(base->der));
- if (!base->der) {
- LOGMEM;
- return EXIT_FAILURE;
- }
- base->der[i] = ident;
- base->der[i + 1] = NULL; /* array termination */
+ /* maintain backlinks to the derived identities */
+ return identity_backlink_update(ident, base);
- base = base->base;
- }
-
- *ret = ident->base;
- return EXIT_SUCCESS;
+ } else if (!ident) {
+ return EXIT_FAILURE;
}
return EXIT_SUCCESS;
@@ -4386,10 +4404,10 @@
*/
static int
resolve_base_ident(const struct lys_module *module, struct lys_ident *ident, const char *basename, const char* parent,
- struct lys_type *type)
+ struct lys_type *type, struct unres_schema *unres)
{
const char *name;
- int i, mod_name_len = 0;
+ int mod_name_len = 0;
struct lys_ident *target, **ret;
uint16_t flags;
struct lys_module *mod;
@@ -4433,19 +4451,11 @@
}
/* search in the identified module ... */
- if (resolve_base_ident_sub(module, ident, name, ret)) {
- return EXIT_FAILURE;
+ if (resolve_base_ident_sub(module, ident, name, unres, ret)) {
+ return -1;
} else if (*ret) {
goto success;
}
- /* and all its submodules */
- for (i = 0; i < module->inc_size && module->inc[i].submodule; i++) {
- if (resolve_base_ident_sub((struct lys_module *)module->inc[i].submodule, ident, name, ret)) {
- return EXIT_FAILURE;
- } else if (*ret) {
- goto success;
- }
- }
LOGVAL(LYE_INRESOLV, LY_VLOG_NONE, NULL, parent, basename);
return EXIT_FAILURE;
@@ -4496,14 +4506,14 @@
goto match;
}
- if (base->der) {
- for (der = base->der[i = 0]; base->der[i]; der = base->der[++i]) {
- if (!strcmp(der->name, name) &&
- (!mod_name || (!strncmp(der->module->name, mod_name, mod_name_len) && !der->module->name[mod_name_len]))) {
- /* we have match */
- goto match;
- }
+ for (i = 0; i < base->der_size; i++) {
+ der = base->der[i]; /* shortcut */
+ if (!strcmp(der->name, name) &&
+ (!mod_name || (!strncmp(der->module->name, mod_name, mod_name_len) && !der->module->name[mod_name_len]))) {
+ /* we have match */
+ goto match;
}
+
}
LOGVAL(LYE_INRESOLV, LY_VLOG_LYD, node, "identityref", ident_name);
@@ -5002,14 +5012,14 @@
has_str = 1;
ident = item;
- rc = resolve_base_ident(mod, ident, expr, "identity", NULL);
+ rc = resolve_base_ident(mod, ident, expr, "identity", NULL, unres);
break;
case UNRES_TYPE_IDENTREF:
expr = str_snode;
has_str = 1;
stype = item;
- rc = resolve_base_ident(mod, NULL, expr, "type", stype);
+ rc = resolve_base_ident(mod, NULL, expr, "type", stype, unres);
break;
case UNRES_TYPE_LEAFREF:
node = str_snode;
@@ -5278,14 +5288,14 @@
res_count = 0;
for (i = 0; i < unres->count; ++i) {
- /* we do not need to have UNRES_TYPE_IDENTREF resolved, we need its type's base only,
- * but UNRES_TYPE_LEAFREF must be resolved (for storing leafref target pointers);
+ /* UNRES_TYPE_LEAFREF must be resolved (for storing leafref target pointers);
* if-features are resolved here to make sure that we will have all if-features for
* later check of feature circular dependency */
- if ((unres->type[i] != UNRES_USES) && (unres->type[i] != UNRES_IFFEAT) && (unres->type[i] != UNRES_TYPE_DER)
- && (unres->type[i] != UNRES_TYPE_DER_TPDF) && (unres->type[i] != UNRES_TYPE_LEAFREF)) {
+ if (unres->type[i] > UNRES_IDENT) {
continue;
}
+ /* processes UNRES_USES, UNRES_IFFEAT, UNRES_TYPE_DER, UNRES_TYPE_DER_TPDF, UNRES_TYPE_LEAFREF,
+ * UNRES_IDENT */
++unres_count;
rc = resolve_unres_schema_item(mod, unres->item[i], unres->type[i], unres->str_snode[i], unres);
@@ -5311,8 +5321,7 @@
ly_vlog_hide(0);
for (i = 0; i < unres->count; ++i) {
- if ((unres->type[i] != UNRES_USES) && (unres->type[i] != UNRES_IFFEAT) && (unres->type[i] != UNRES_TYPE_DER)
- && (unres->type[i] != UNRES_TYPE_DER_TPDF) && (unres->type[i] != UNRES_TYPE_LEAFREF)) {
+ if (unres->type[i] > UNRES_IDENT) {
continue;
}
resolve_unres_schema_item(mod, unres->item[i], unres->type[i], unres->str_snode[i], unres);