parser yang CHANGE grouping statement and its substatemnets
optimalize
diff --git a/src/parser_yang.c b/src/parser_yang.c
index 03b33ff..6e145ac 100644
--- a/src/parser_yang.c
+++ b/src/parser_yang.c
@@ -22,7 +22,8 @@
static void yang_free_import(struct ly_ctx *ctx, struct lys_import *imp, uint8_t start, uint8_t size);
static void yang_free_include(struct ly_ctx *ctx, struct lys_include *inc, uint8_t start, uint8_t size);
static int yang_check_sub_module(struct lys_module *module, struct unres_schema *unres, struct lys_node *node);
-static void free_yang_common(struct lys_module *module);
+static void free_yang_common(struct lys_module *module, struct lys_node *node);
+void lys_iffeature_free(struct lys_iffeature *iffeature, uint8_t iffeature_size);
static int
yang_check_string(struct lys_module *module, const char **target, char *what, char *where, char *value)
@@ -504,9 +505,10 @@
}
void *
-yang_read_node(struct lys_module *module, struct lys_node *parent, char *value, int nodetype, int sizeof_struct)
+yang_read_node(struct lys_module *module, struct lys_node *parent, struct lys_node **root,
+ char *value, int nodetype, int sizeof_struct)
{
- struct lys_node *node;
+ struct lys_node *node, **child;
node = calloc(1, sizeof_struct);
if (!node) {
@@ -519,21 +521,21 @@
}
node->module = module;
node->nodetype = nodetype;
- node->prev = node;
/* insert the node into the schema tree */
- if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, node)) {
- if (value) {
- lydict_remove(module->ctx, node->name);
- }
- free(node);
- return NULL;
+ child = (parent) ? &parent->child : root;
+ if (*child) {
+ (*child)->prev->next = node;
+ (*child)->prev = node;
+ } else {
+ *child = node;
+ node->prev = node;
}
return node;
}
void *
-yang_read_action(struct lys_module *module, struct lys_node *parent, char *value)
+yang_read_action(struct lys_module *module, struct lys_node *parent, struct lys_node **root, char *value)
{
struct lys_node *node;
@@ -549,7 +551,7 @@
return NULL;
}
}
- return yang_read_node(module, parent, value, LYS_ACTION, sizeof(struct lys_node_rpc_action));
+ return yang_read_node(module, parent, root, value, LYS_ACTION, sizeof(struct lys_node_rpc_action));
}
int
@@ -2552,7 +2554,7 @@
module->implemented = (implement ? 1 : 0);
if (yang_parse_mem(module, NULL, unres, data, size, &node)) {
- free_yang_common(module);
+ free_yang_common(module, node);
goto error;
}
@@ -2630,7 +2632,7 @@
submodule->belongsto = module;
if (yang_parse_mem(module, submodule, unres, data, size, &node)) {
- free_yang_common((struct lys_module *)submodule);
+ free_yang_common((struct lys_module *)submodule, node);
goto error;
}
@@ -2833,13 +2835,56 @@
}
}
+static void
+yang_free_grouping(struct ly_ctx *ctx, struct lys_node_grp * grp)
+{
+ yang_tpdf_free(ctx, grp->tpdf, 0, grp->tpdf_size);
+ free(grp->tpdf);
+}
+
+static void
+yang_free_nodes(struct ly_ctx *ctx, struct lys_node *node)
+{
+ struct lys_node *tmp, *child, *sibling;
+
+ if (!node) {
+ return;
+ }
+ tmp = node;
+ child = tmp->child;
+
+ while (tmp) {
+ sibling = tmp->next;
+ /* common part */
+ lydict_remove(ctx, tmp->name);
+ if (!(tmp->nodetype & (LYS_INPUT | LYS_OUTPUT))) {
+ lys_iffeature_free(node->iffeature, node->iffeature_size);
+ lydict_remove(ctx, node->dsc);
+ lydict_remove(ctx, node->ref);
+ }
+
+ switch (tmp->nodetype) {
+ case LYS_GROUPING:
+ yang_free_grouping(ctx, (struct lys_node_grp *)tmp);
+ break;
+ default:
+ break;
+ }
+
+ yang_free_nodes(ctx, child);
+ free(tmp);
+ tmp = sibling;
+ }
+}
+
/* free common item from module and submodule */
static void
-free_yang_common(struct lys_module *module)
+free_yang_common(struct lys_module *module, struct lys_node *node)
{
yang_tpdf_free(module->ctx, module->tpdf, 0, module->tpdf_size);
module->tpdf_size = 0;
yang_free_ident_base(module->ident, 0, module->ident_size);
+ yang_free_nodes(module->ctx, node);
}
/* check function*/
@@ -2965,6 +3010,16 @@
if (!parent) {
tpdf = module->tpdf;
ptr_tpdf_size = &module->tpdf_size;
+ } else {
+ switch (parent->nodetype) {
+ case LYS_GROUPING:
+ tpdf = ((struct lys_node_grp *)parent)->tpdf;
+ ptr_tpdf_size = &((struct lys_node_grp *)parent)->tpdf_size;
+ break;
+ default:
+ LOGINT;
+ return EXIT_FAILURE;
+ }
}
tpdf_size = *ptr_tpdf_size;
@@ -3028,9 +3083,76 @@
}
static int
+yang_check_grouping(struct lys_module *module, struct lys_node_grp *node, struct unres_schema *unres)
+{
+ uint8_t i, size;
+
+ if (yang_check_typedef(module, (struct lys_node *)node, unres)) {
+ goto error;
+ }
+
+ size = node->iffeature_size;
+ node->iffeature_size = 0;
+ for (i = 0; i < size; ++i) {
+ if (yang_read_if_feature(module, node, NULL, (char *)node->iffeature[i].features, unres, GROUPING_KEYWORD)) {
+ node->iffeature_size = size;
+ goto error;
+ }
+ }
+
+ return EXIT_SUCCESS;
+
+error:
+ return EXIT_FAILURE;
+}
+
+static int
+yang_check_nodes(struct lys_module *module, struct lys_node *nodes, struct unres_schema *unres)
+{
+ struct lys_node *node = nodes, *sibling, *child;
+
+ while (node) {
+ sibling = node->next;
+ child = node->child;
+ node->next = NULL;
+ node->child = NULL;
+ node->prev = node;
+
+ if (lys_node_addchild(node->parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, node)) {
+ sibling = node;
+ child = NULL;
+ goto error;
+ }
+ switch (node->nodetype) {
+ case LYS_GROUPING:
+ if (yang_check_grouping(module, (struct lys_node_grp *)node, unres)) {
+ goto error;
+ }
+ break;
+ default:
+ LOGINT;
+ sibling = node;
+ child = NULL;
+ goto error;
+ }
+ if (yang_check_nodes(module, child, unres)) {
+ child = NULL;
+ goto error;
+ }
+ node = sibling;
+ }
+
+ return EXIT_SUCCESS;
+error:
+ yang_free_nodes(module->ctx, sibling);
+ yang_free_nodes(module->ctx, child);
+ return EXIT_FAILURE;
+}
+
+static int
yang_check_sub_module(struct lys_module *module, struct unres_schema *unres, struct lys_node *node)
{
- uint8_t i, j, size, erase_identities = 1;
+ uint8_t i, j, size, erase_identities = 1, erase_nodes = 1;
struct lys_feature *feature; /* shortcut */
char *s;
@@ -3057,11 +3179,18 @@
if (yang_check_identities(module, unres)) {
goto error;
}
+ erase_nodes = 0;
+ if (yang_check_nodes(module, node, unres)) {
+ goto error;
+ }
return EXIT_SUCCESS;
error:
if (erase_identities) {
yang_free_ident_base(module->ident, 0, module->ident_size);
}
+ if (erase_nodes) {
+ yang_free_nodes(module->ctx, node);
+ }
return EXIT_FAILURE;
}