yin parser: support identityref type
diff --git a/src/log.c b/src/log.c
index aaa2b85..198b5ee 100644
--- a/src/log.c
+++ b/src/log.c
@@ -70,7 +70,7 @@
"Missing argument \"%s\" to keyword \"%s\"."},
{LY_VERB_ERR, /* LY_VERR_TOOMANY */
"Too many instances of \"%s\" in \"%s\"."},
- {LY_VERB_ERR, /* LY_VERR_UNEXP_ARG */
+ {LY_VERB_ERR, /* LY_VERR_UNEXP_VAL */
"Unexpected value \"%s\" of \"%s\"."},
{LY_VERB_ERR, /* LY_VERR_BAD_RESTR */
"Restriction \"%s\" not allowed for this base type."},
diff --git a/src/print.c b/src/print.c
index 2f7819e..1a4658c 100644
--- a/src/print.c
+++ b/src/print.c
@@ -94,7 +94,7 @@
yang_print_mnode_common(f, level, mnode);
}
-static void yang_print_type(FILE *f, int level, struct ly_type *type)
+static void yang_print_type(FILE *f, int level, struct ly_module *module, struct ly_type *type)
{
int i;
@@ -115,6 +115,13 @@
fprintf(f, "%*s}\n", LEVEL, INDENT);
}
break;
+ case LY_TYPE_IDENT:
+ if (module == type->info.ident.ref->module) {
+ fprintf(f, "%*sbase %s;\n", LEVEL, INDENT, type->info.ident.ref->name);
+ } else {
+ fprintf(f, "%*sbase %s:%s;\n", LEVEL, INDENT, type->info.ident.ref->module->prefix, type->info.ident.ref->name);
+ }
+ break;
default:
/* TODO other cases */
break;
@@ -123,13 +130,13 @@
fprintf(f, "%*s}\n", LEVEL, INDENT);
}
-static void yang_print_typedef(FILE *f, int level, struct ly_tpdf *tpdf)
+static void yang_print_typedef(FILE *f, int level, struct ly_module *module, struct ly_tpdf *tpdf)
{
fprintf(f, "%*stypedef %s {\n", LEVEL, INDENT, tpdf->name);
level++;
yang_print_mnode_common(f, level, (struct ly_mnode *)tpdf);
- yang_print_type(f, level, &tpdf->type);
+ yang_print_type(f, level, module, &tpdf->type);
level--;
fprintf(f, "%*s}\n", LEVEL, INDENT);
@@ -165,7 +172,7 @@
yang_print_mnode_common2(f, level, mnode);
for (i = 0; i < cont->tpdf_size; i++) {
- yang_print_typedef(f, level, &cont->tpdf[i]);
+ yang_print_typedef(f, level, mnode->module, &cont->tpdf[i]);
}
LY_TREE_FOR(mnode->child, sub) {
@@ -200,7 +207,7 @@
fprintf(f, "%*sleaf %s {\n", LEVEL, INDENT, mnode->name);
level++;
yang_print_mnode_common2(f, level, mnode);
- yang_print_type(f, level, &leaf->type);
+ yang_print_type(f, level, mnode->module, &leaf->type);
level--;
fprintf(f, "%*s}\n", LEVEL, INDENT);
}
@@ -212,7 +219,7 @@
fprintf(f, "%*sleaf-list %s {\n", LEVEL, INDENT, mnode->name);
level++;
yang_print_mnode_common2(f, level, mnode);
- yang_print_type(f, level, &llist->type);
+ yang_print_type(f, level, mnode->module, &llist->type);
level--;
fprintf(f, "%*s}\n", LEVEL, INDENT);
}
@@ -228,7 +235,7 @@
yang_print_mnode_common2(f, level, mnode);
for (i = 0; i < list->tpdf_size; i++) {
- yang_print_typedef(f, level, &list->tpdf[i]);
+ yang_print_typedef(f, level, list->module, &list->tpdf[i]);
}
LY_TREE_FOR(mnode->child, sub) {
@@ -251,7 +258,7 @@
yang_print_mnode_common(f, level, mnode);
for (i = 0; i < grp->tpdf_size; i++) {
- yang_print_typedef(f, level, &grp->tpdf[i]);
+ yang_print_typedef(f, level, mnode->module, &grp->tpdf[i]);
}
LY_TREE_FOR(mnode->child, node) {
@@ -363,7 +370,7 @@
}
for (i = 0; i < module->tpdf_size; i++) {
- yang_print_typedef(f, level, &module->tpdf[i]);
+ yang_print_typedef(f, level, module, &module->tpdf[i]);
}
LY_TREE_FOR(module->data, mnode) {
diff --git a/src/tree.h b/src/tree.h
index 760ad5a..e9d60ef 100644
--- a/src/tree.h
+++ b/src/tree.h
@@ -127,8 +127,7 @@
/* LY_TYPE_IDENT */
struct {
- char *base;
- struct ly_ident *ident;
+ struct ly_ident *ref;
} ident;
/* LY_TYPE_INST */
diff --git a/src/yin.c b/src/yin.c
index 32879ac..4e29eed 100644
--- a/src/yin.c
+++ b/src/yin.c
@@ -144,6 +144,117 @@
return NULL;
}
+static struct ly_ident *find_base_ident(struct ly_module *module, struct ly_ident *ident, const char *basename)
+{
+ const char *name;
+ int prefix_len = 0;
+ int i, found = 0;
+ struct ly_ident *base_iter;
+ struct ly_ident_der *der;
+
+ if (!basename) {
+ ly_verr(LY_VERR_MISS_ARG, "name", "base");
+ return NULL;
+ }
+
+ /* search for the base identity */
+ name = strchr(basename, ':');
+ if (name) {
+ /* set name to correct position after colon */
+ prefix_len = name - basename;
+ name++;
+
+ if (!strncmp(basename, module->prefix, prefix_len) && !module->prefix[prefix_len]) {
+ /* prefix refers to the current module, ignore it */
+ prefix_len = 0;
+ }
+ } else {
+ name = basename;
+ }
+
+ if (prefix_len) {
+ /* get module where to search */
+ for (i = 0; i < module->imp_size; i++) {
+ if (!strncmp(module->imp[i].prefix, basename, prefix_len)
+ && !module->imp[i].prefix[prefix_len]) {
+ module = module->imp[i].module;
+ found = 1;
+ break;
+ }
+ }
+ if (!found) {
+ /* identity refers unknown data model */
+ ly_verr(LY_VERR_UNEXP_PREFIX, basename);
+ return NULL;
+ }
+ }
+
+ /* search in the identified module */
+ /* TODO what about submodules? */
+ for (i = 0; i < module->ident_size; i++) {
+ if (!strcmp(name, module->ident[i].name)) {
+ /* we are done */
+
+ if (!ident) {
+ /* just search for type, so do not modify anything, just return
+ * the base identity pointer
+ */
+ return &module->ident[i];
+ }
+
+ /* we are resolving identity definition, so now update structures */
+ ident->base = base_iter = &module->ident[i];
+
+ while (base_iter) {
+ for (der = base_iter->der; der && der->next; der = der->next);
+ if (der) {
+ der->next = malloc(sizeof *der);
+ der = der->next;
+ } else {
+ ident->base->der = der = malloc(sizeof *der);
+ }
+ der->next = NULL;
+ der->ident = ident;
+
+ base_iter = base_iter->base;
+ }
+ return ident->base;
+ }
+ }
+
+ ly_verr(LY_VERR_UNEXP_VAL, basename, ident ? "identity" : "type");
+ return NULL;
+}
+
+static int fill_yin_identity(struct ly_module *module, struct lyxml_elem *yin, struct ly_ident *ident)
+{
+ struct lyxml_elem *node, *next;
+
+ if (read_yin_common(module, NULL, (struct ly_mnode *)ident, yin, 0)) {
+ return EXIT_FAILURE;
+ }
+ ident->module = module;
+
+ LY_TREE_FOR_SAFE(yin->child, next, node) {
+ if (!strcmp(node->name, "base")) {
+ if (ident->base) {
+ ly_verr(LY_VERR_TOOMANY, "base", "identity");
+ return EXIT_FAILURE;
+ }
+ if (!find_base_ident(module, ident, lyxml_get_attr(node, "name", NULL))) {
+ return EXIT_FAILURE;
+ }
+ } else {
+ ly_verr(LY_VERR_UNEXP_STMT, node->name, "identity");
+ return EXIT_FAILURE;
+ }
+
+ lyxml_free_elem(module->ctx, node);
+ }
+
+ return EXIT_SUCCESS;
+}
+
static int fill_yin_type(struct ly_module *module, struct ly_mnode *parent,
struct lyxml_elem *yin, struct ly_type *type)
{
@@ -164,7 +275,8 @@
switch (type->base) {
case LY_TYPE_BINARY:
/* length, 9.4.4
- * - optional, 0..1, rekurzivni - omezuje, string (podobne jako range), hodnoty se musi vejit do 64b, podelementy
+ * - optional, 0..1, rekurzivni - omezuje, string (podobne jako range),
+ * hodnoty se musi vejit do 64b, podelementy
*/
break;
case LY_TYPE_BITS:
@@ -179,10 +291,7 @@
break;
case LY_TYPE_ENUM:
/* RFC 6020 9.6 */
- if (type->der->module) {
- ly_verr(LY_VERR_BAD_RESTR, "enum");
- goto error;
- }
+
/* get enum specification, at least one must be present */
LY_TREE_FOR_SAFE(yin->child, next, node) {
if (!strcmp(node->name, "enum")) {
@@ -269,8 +378,25 @@
}
break;
case LY_TYPE_IDENT:
- /* base, 9.10.2
- * - 1, nerekurzivni. string */
+ /* RFC 6020 9.10 */
+
+ /* get base specification, exactly one must be present */
+ if (!yin->child) {
+ ly_verr(LY_VERR_MISS_STMT2, "base", "type");
+ goto error;
+ }
+ if (strcmp(yin->child->name, "base")) {
+ ly_verr(LY_VERR_UNEXP_STMT, yin->child->name);
+ goto error;
+ }
+ if (yin->child->next) {
+ ly_verr(LY_VERR_UNEXP_STMT, yin->child->next->name);
+ goto error;
+ }
+ type->info.ident.ref = find_base_ident(module, NULL, lyxml_get_attr(yin->child, "name", NULL));
+ if (!type->info.ident.ref) {
+ return EXIT_FAILURE;
+ }
break;
case LY_TYPE_INST:
/* require-instance, 9.13.2
@@ -435,100 +561,6 @@
return EXIT_SUCCESS;
}
-static int fill_yin_identity(struct ly_module *module, struct lyxml_elem *yin, struct ly_ident *ident)
-{
- const char *basename;
- struct lyxml_elem *node, *next;
- const char *name;
- int prefix_len = 0;
- int i, found = 0;
- struct ly_ident *bident;
- struct ly_ident_der *der;
-
- if (read_yin_common(module, NULL, (struct ly_mnode *)ident, yin, 0)) {
- return EXIT_FAILURE;
- }
- ident->module = module;
-
- LY_TREE_FOR_SAFE(yin->child, next, node) {
- if (!strcmp(node->name, "base")) {
- if (ident->base) {
- ly_verr(LY_VERR_TOOMANY, "base", "identity");
- return EXIT_FAILURE;
- }
-
- basename = lyxml_get_attr(node, "name", NULL);
-
- /* search for the base identity */
- name = strchr(basename, ':');
- if (name) {
- /* set name to correct position after colon */
- prefix_len = name - basename;
- name++;
-
- if (!strncmp(basename, module->prefix, prefix_len) && !module->prefix[prefix_len]) {
- /* prefix refers to the current module, ignore it */
- prefix_len = 0;
- }
- } else {
- name = basename;
- }
-
- if (prefix_len) {
- /* get module where to search */
- for (i = 0; i < module->imp_size; i++) {
- if (!strncmp(module->imp[i].prefix, basename, prefix_len)
- && !module->imp[i].prefix[prefix_len]) {
- module = module->imp[i].module;
- found = 1;
- break;
- }
- }
- if (!found) {
- /* identity refers unknown data model */
- ly_verr(LY_VERR_UNEXP_PREFIX, basename);
- return EXIT_FAILURE;
- }
- }
-
- /* search in the identified module */
- /* TODO what about submodules? */
- found = 0;
- for (i = 0; i < module->ident_size; i++) {
- if (!strcmp(name, module->ident[i].name)) {
- /* we are done, now update structures */
- found = 1;
-
- ident->base = bident = &module->ident[i];
-
- while (bident) {
- for (der = bident->der; der && der->next; der = der->next);
- if (der) {
- der->next = malloc(sizeof *der);
- der = der->next;
- } else {
- ident->base->der = der = malloc(sizeof *der);
- }
- der->next = NULL;
- der->ident = ident;
-
- bident = bident->base;
- }
- break;
- }
- }
-
- } else {
- ly_verr(LY_VERR_UNEXP_STMT, node->name, "identity");
- return EXIT_FAILURE;
- }
-
- lyxml_free_elem(module->ctx, node);
- }
-
- return EXIT_SUCCESS;
-}
-
static struct ly_mnode *read_yin_choice(struct ly_module *module,
struct ly_mnode *parent,
struct lyxml_elem *node)