extensions CHANGE support for revision statement in extension instances
diff --git a/src/extensions/ext_test.c b/src/extensions/ext_test.c
index e5ccccb..3dd56b4 100644
--- a/src/extensions/ext_test.c
+++ b/src/extensions/ext_test.c
@@ -97,8 +97,8 @@
{LY_STMT_PATTERN, 30 * sizeof(void*) + 5 * sizeof(uint8_t), LY_STMT_CARD_OPT}, /* struct lys_restr* */
{LY_STMT_RANGE, 31 * sizeof(void*) + 5 * sizeof(uint8_t), LY_STMT_CARD_OPT}, /* struct lys_restr* */
{LY_STMT_WHEN, 32 * sizeof(void*) + 5 * sizeof(uint8_t), LY_STMT_CARD_OPT}, /* struct lys_when* */
-/* {LY_STMT_REVISION, 66 * sizeof(void *), LY_STMT_CARD_OPT},
-*/ {0, 0, 0} /* terminating item */
+ {LY_STMT_REVISION, 33 * sizeof(void*) + 5 * sizeof(uint8_t), LY_STMT_CARD_OPT}, /* struct lys_revision* */
+ {0, 0, 0} /* terminating item */
};
struct lyext_substmt libyang_ext_test_substmt_arrays[] = {
@@ -152,8 +152,8 @@
{LY_STMT_PATTERN, 31 * sizeof(void*), LY_STMT_CARD_ANY}, /* struct lys_restr** */
{LY_STMT_RANGE, 32 * sizeof(void*), LY_STMT_CARD_ANY}, /* struct lys_restr** */
{LY_STMT_WHEN, 33 * sizeof(void*), LY_STMT_CARD_ANY}, /* struct lys_when** */
-/* {LY_STMT_REVISION, 66 * sizeof(void *), LY_STMT_CARD_ANY},
-*/ {0, 0, 0} /* terminating item */
+ {LY_STMT_REVISION, 34 * sizeof(void*), LY_STMT_CARD_ANY}, /* struct lys_revision** */
+ {0, 0, 0} /* terminating item */
};
/**
diff --git a/src/parser_yin.c b/src/parser_yin.c
index cd34ae0..ce72f13 100644
--- a/src/parser_yin.c
+++ b/src/parser_yin.c
@@ -1824,6 +1824,67 @@
}
static int
+fill_yin_revision(struct lys_module *module, struct lyxml_elem *yin, struct lys_revision *rev,
+ struct unres_schema *unres)
+{
+ struct lyxml_elem *next, *child;
+ const char *value;
+
+ GETVAL(value, yin, "date");
+ if (lyp_check_date(value)) {
+ goto error;
+ }
+ memcpy(rev->date, value, LY_REV_SIZE - 1);
+
+ LY_TREE_FOR_SAFE(yin->child, next, child) {
+ if (!child->ns) {
+ /* garbage */
+ continue;
+ } else if (strcmp(child->ns->value, LY_NSYIN)) {
+ /* possible extension instance */
+ if (lyp_yin_parse_subnode_ext(module, rev, LYEXT_PAR_REVISION,
+ child, LYEXT_SUBSTMT_SELF, 0, unres)) {
+ goto error;
+ }
+ } else if (!strcmp(child->name, "description")) {
+ if (rev->dsc) {
+ LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
+ goto error;
+ }
+ if (lyp_yin_parse_subnode_ext(module, rev, LYEXT_PAR_REVISION,
+ child, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
+ goto error;
+ }
+ rev->dsc = read_yin_subnode(module->ctx, child, "text");
+ if (!rev->dsc) {
+ goto error;
+ }
+ } else if (!strcmp(child->name, "reference")) {
+ if (rev->ref) {
+ LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child->name, yin->name);
+ goto error;
+ }
+ if (lyp_yin_parse_subnode_ext(module, rev, LYEXT_PAR_REVISION,
+ child, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
+ goto error;
+ }
+ rev->ref = read_yin_subnode(module->ctx, child, "text");
+ if (!rev->ref) {
+ goto error;
+ }
+ } else {
+ LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child->name);
+ goto error;
+ }
+ }
+
+ return EXIT_SUCCESS;
+
+error:
+ return EXIT_FAILURE;
+}
+
+static int
fill_yin_unique(struct lys_module *module, struct lys_node *parent, struct lyxml_elem *yin, struct lys_unique *unique,
struct unres_schema *unres)
{
@@ -6322,7 +6383,7 @@
struct unres_schema *unres)
{
struct ly_ctx *ctx = module->ctx;
- struct lyxml_elem *next, *next2, *child, *child2, root, grps, augs, revs, exts;
+ struct lyxml_elem *next, *child, root, grps, augs, revs, exts;
struct lys_node *node = NULL;
struct lys_module *trg;
const char *value;
@@ -6804,61 +6865,19 @@
/* middle part 1 - process revision and then check whether this (sub)module was not already parsed, add it there */
LY_TREE_FOR_SAFE(revs.child, next, child) {
- GETVAL(value, child, "date");
- if (lyp_check_date(value)) {
+ r = fill_yin_revision(trg, child, &trg->rev[trg->rev_size], unres);
+ trg->rev_size++;
+ if (r) {
goto error;
}
- memcpy(trg->rev[trg->rev_size].date, value, LY_REV_SIZE - 1);
- /* check uniqueness of the revision date - not required by RFC */
- for (i = 0; i < trg->rev_size; i++) {
- if (!strcmp(value, trg->rev[i].date)) {
- LOGVAL(LYE_INARG, LY_VLOG_NONE, NULL, value, child->name);
- LOGVAL(LYE_SPEC, LY_VLOG_NONE, NULL, "Revision is not unique.");
- }
- }
- LY_TREE_FOR_SAFE(child->child, next2, child2) {
- if (!child2->ns) {
- /* garbage */
- continue;
- } else if (strcmp(child2->ns->value, LY_NSYIN)) {
- /* possible extension instance */
- if (lyp_yin_parse_subnode_ext(trg, &trg->rev[trg->rev_size], LYEXT_PAR_REVISION,
- child2, LYEXT_SUBSTMT_SELF, 0, unres)) {
- goto error;
- }
- } else if (!strcmp(child2->name, "description")) {
- if (trg->rev[trg->rev_size].dsc) {
- LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child2->name, child->name);
- goto error;
- }
- if (lyp_yin_parse_subnode_ext(trg, &trg->rev[trg->rev_size], LYEXT_PAR_REVISION,
- child2, LYEXT_SUBSTMT_DESCRIPTION, 0, unres)) {
- goto error;
- }
- trg->rev[trg->rev_size].dsc = read_yin_subnode(ctx, child2, "text");
- if (!trg->rev[trg->rev_size].dsc) {
- goto error;
- }
- } else if (!strcmp(child2->name, "reference")) {
- if (trg->rev[trg->rev_size].ref) {
- LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, child2->name, child->name);
- goto error;
- }
- if (lyp_yin_parse_subnode_ext(trg, &trg->rev[trg->rev_size], LYEXT_PAR_REVISION,
- child2, LYEXT_SUBSTMT_REFERENCE, 0, unres)) {
- goto error;
- }
- trg->rev[trg->rev_size].ref = read_yin_subnode(ctx, child2, "text");
- if (!trg->rev[trg->rev_size].ref) {
- goto error;
- }
- } else {
- LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, child2->name);
- goto error;
+ /* check uniqueness of the revision date - not required by RFC */
+ for (i = 0; i < (trg->rev_size - 1); i++) {
+ if (!strcmp(trg->rev[i].date, trg->rev[trg->rev_size - 1].date)) {
+ LOGWRN("Module's revisions are not unique (%s).", trg->rev[trg->rev_size - 1].date);
+ break;
}
}
- trg->rev_size++;
lyxml_free(ctx, child);
}
@@ -7537,7 +7556,7 @@
long int v;
long long int ll;
unsigned long u;
- int i;
+ int i, j;
#define YIN_EXTCOMPLEX_GETPLACE(STMT, TYPE) \
p = lys_ext_complex_get_substmt(STMT, ext, &info); \
@@ -7894,6 +7913,24 @@
}
YIN_EXTCOMPLEX_ENLARGE(struct lys_when*);
+ } else if (!strcmp(node->name, "revision")) {
+ YIN_EXTCOMPLEX_GETPLACE(LY_STMT_REVISION, struct lys_revision*);
+
+ *(struct lys_revision**)p = calloc(1, sizeof(struct lys_revision));
+ if (fill_yin_revision(mod, node, *(struct lys_revision**)p, unres)) {
+ goto error;
+ }
+
+ /* check uniqueness of the revision dates - not required by RFC */
+ if (pp) {
+ for (j = 0; j < i; j++) {
+ if (!strcmp((*(struct lys_revision***)pp)[j]->date, (*(struct lys_revision**)p)->date)) {
+ LOGWRN("Module's revisions are not unique (%s).", (*(struct lys_revision**)p)->date);
+ }
+ }
+ }
+
+ YIN_EXTCOMPLEX_ENLARGE(struct lys_revision*);
} else if (!strcmp(node->name, "unique")) {
YIN_EXTCOMPLEX_GETPLACE(LY_STMT_UNIQUE, struct lys_unique*);
diff --git a/src/printer_yang.c b/src/printer_yang.c
index 996eeec..adee41a 100755
--- a/src/printer_yang.c
+++ b/src/printer_yang.c
@@ -1601,6 +1601,20 @@
}
}
+static void
+yang_print_revision(struct lyout *out, int level, const struct lys_module *module, const struct lys_revision *rev)
+{
+ if (rev->dsc || rev->ref || rev->ext_size) {
+ ly_print(out, "%*srevision \"%s\" {\n", LEVEL, INDENT, rev->date);
+ yang_print_extension_instances(out, level + 1, module, LYEXT_SUBSTMT_SELF, 0, rev->ext, rev->ext_size);
+ yang_print_substmt(out, level + 1, LYEXT_SUBSTMT_DESCRIPTION, 0, rev->dsc, module, rev->ext, rev->ext_size);
+ yang_print_substmt(out, level + 1, LYEXT_SUBSTMT_REFERENCE, 0, rev->ref, module, rev->ext, rev->ext_size);
+ ly_print(out, "%*s}\n", LEVEL, INDENT);
+ } else {
+ ly_print(out, "%*srevision %s;\n", LEVEL, INDENT, rev->date);
+ }
+}
+
static int
yang_print_model_(struct lyout *out, int level, const struct lys_module *module)
{
@@ -1700,18 +1714,7 @@
ly_print(out, "\n");
}
for (i = 0; i < module->rev_size; i++) {
- if (module->rev[i].dsc || module->rev[i].ref || module->rev[i].ext_size) {
- ly_print(out, "%*srevision \"%s\" {\n", LEVEL, INDENT, module->rev[i].date);
- yang_print_extension_instances(out, level + 1, module, LYEXT_SUBSTMT_SELF, 0,
- module->rev[i].ext, module->rev[i].ext_size);
- yang_print_substmt(out, level + 1, LYEXT_SUBSTMT_DESCRIPTION, 0, module->rev[i].dsc,
- module, module->rev[i].ext, module->rev[i].ext_size);
- yang_print_substmt(out, level + 1, LYEXT_SUBSTMT_REFERENCE, 0, module->rev[i].ref,
- module, module->rev[i].ext, module->rev[i].ext_size);
- ly_print(out, "%*s}\n", LEVEL, INDENT);
- } else {
- ly_print(out, "%*srevision %s;\n", LEVEL, INDENT, module->rev[i].date);
- }
+ yang_print_revision(out, level, module, &module->rev[i]);
}
/* body-stmts */
@@ -2190,6 +2193,9 @@
case LY_STMT_WHEN:
YANG_PRINT_EXTCOMPLEX_STRUCT_M(LY_STMT_WHEN, struct lys_when, yang_print_when);
break;
+ case LY_STMT_REVISION:
+ YANG_PRINT_EXTCOMPLEX_STRUCT_M(LY_STMT_REVISION, struct lys_revision, yang_print_revision);
+ break;
default:
/* TODO */
break;
diff --git a/src/printer_yin.c b/src/printer_yin.c
index debb72f..a8075ef 100644
--- a/src/printer_yin.c
+++ b/src/printer_yin.c
@@ -1579,6 +1579,22 @@
}
static void
+yin_print_revision(struct lyout *out, int level, const struct lys_module *module, const struct lys_revision *rev)
+{
+ if (rev->dsc || rev->ref || rev->ext_size) {
+ yin_print_open(out, level, NULL, "revision", "date", rev->date, 1);
+ level++;
+ yin_print_extension_instances(out, level, module, LYEXT_SUBSTMT_SELF, 0, rev->ext, rev->ext_size);
+ yin_print_substmt(out, level, LYEXT_SUBSTMT_DESCRIPTION, 0, rev->dsc, module, rev->ext, rev->ext_size);
+ yin_print_substmt(out, level, LYEXT_SUBSTMT_REFERENCE, 0, rev->ref, module, rev->ext, rev->ext_size);
+ level--;
+ yin_print_close(out, level, NULL, "revision", 1);
+ } else {
+ yin_print_open(out, level, NULL, "revision", "date", rev->date, -1);
+ }
+}
+
+static void
yin_print_xmlns(struct lyout *out, const struct lys_module *module)
{
unsigned int i, lvl;
@@ -1702,20 +1718,7 @@
/* revision-stmts */
for (i = 0; i < module->rev_size; i++) {
- if (module->rev[i].dsc || module->rev[i].ref || module->ext_size) {
- yin_print_open(out, level, NULL, "revision", "date", module->rev[i].date, 1);
- level++;
- yin_print_extension_instances(out, level, module, LYEXT_SUBSTMT_SELF, 0,
- module->rev[i].ext, module->rev[i].ext_size);
- yin_print_substmt(out, level, LYEXT_SUBSTMT_DESCRIPTION, 0, module->rev[i].dsc,
- module, module->rev[i].ext, module->rev[i].ext_size);
- yin_print_substmt(out, level, LYEXT_SUBSTMT_REFERENCE, 0, module->rev[i].ref,
- module, module->rev[i].ext, module->rev[i].ext_size);
- level--;
- yin_print_close(out, level, NULL, "revision", 1);
- } else {
- yin_print_open(out, level, NULL, "revision", "date", module->rev[i].date, -1);
- }
+ yin_print_revision(out, level, module, &module->rev[i]);
}
/* body-stmts */
@@ -2202,6 +2205,9 @@
case LY_STMT_WHEN:
YIN_PRINT_EXTCOMPLEX_STRUCT_M(LY_STMT_WHEN, struct lys_when, yin_print_when);
break;
+ case LY_STMT_REVISION:
+ YIN_PRINT_EXTCOMPLEX_STRUCT_M(LY_STMT_REVISION, struct lys_revision, yin_print_revision);
+ break;
default:
/* TODO */
break;
diff --git a/src/tree_schema.c b/src/tree_schema.c
index 9e67819..122f9e9 100644
--- a/src/tree_schema.c
+++ b/src/tree_schema.c
@@ -4531,6 +4531,28 @@
case LY_STMT_WHEN:
EXTCOMPLEX_FREE_STRUCT(LY_STMT_WHEN, struct lys_when, lys_when_free, 0);
break;
+ case LY_STMT_REVISION:
+ pp = lys_ext_complex_get_substmt(LY_STMT_REVISION, (struct lys_ext_instance_complex *)e[i], NULL);
+ if (!pp || !(*pp)) {
+ break;
+ }
+ if (substmt[j].cardinality >= LY_STMT_CARD_SOME) { /* process array */
+ for (start = pp = *pp; *pp; pp++) {
+ lydict_remove(ctx, (*(struct lys_revision**)pp)->dsc);
+ lydict_remove(ctx, (*(struct lys_revision**)pp)->ref);
+ lys_extension_instances_free(ctx, (*(struct lys_revision**)pp)->ext,
+ (*(struct lys_revision**)pp)->ext_size);
+ free(*pp);
+ }
+ free(start);
+ } else { /* single item */
+ lydict_remove(ctx, (*(struct lys_revision**)pp)->dsc);
+ lydict_remove(ctx, (*(struct lys_revision**)pp)->ref);
+ lys_extension_instances_free(ctx, (*(struct lys_revision**)pp)->ext,
+ (*(struct lys_revision**)pp)->ext_size);
+ free(*pp);
+ }
+ break;
default:
/* nothing to free */
break;