parser yang CHANGE augment statement and its substatements

optimalize
diff --git a/src/parser_yang.c b/src/parser_yang.c
index d85a223..2eb0cac 100644
--- a/src/parser_yang.c
+++ b/src/parser_yang.c
@@ -23,6 +23,8 @@
 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, struct lys_node *node);
+static int yang_check_nodes(struct lys_module *module, struct lys_node *parent, struct lys_node *nodes,
+                            int config_opt, struct unres_schema *unres);
 void lys_iffeature_free(struct lys_iffeature *iffeature, uint8_t iffeature_size);
 
 static int
@@ -427,7 +429,6 @@
     }
     node->module = module;
     node->nodetype = nodetype;
-    node->parent = parent;
 
     /* insert the node into the schema tree */
     child = (parent) ? &parent->child : root;
@@ -1387,30 +1388,18 @@
     return EXIT_FAILURE;
 }
 
-void *
-yang_read_augment(struct lys_module *module, struct lys_node *parent, char *value)
+int
+yang_read_augment(struct lys_module *module, struct lys_node *parent, struct lys_node_augment *aug, char *value)
 {
-    struct lys_node_augment *aug;
-
-    if (parent) {
-        aug = &((struct lys_node_uses *)parent)->augment[((struct lys_node_uses *)parent)->augment_size];
-    } else {
-        aug = &module->augment[module->augment_size];
-    }
     aug->nodetype = LYS_AUGMENT;
     aug->target_name = transform_schema2json(module, value);
     free(value);
     if (!aug->target_name) {
-        return NULL;
+        return EXIT_FAILURE;
     }
     aug->parent = parent;
     aug->module = module;
-    if (parent) {
-        ((struct lys_node_uses *)parent)->augment_size++;
-    } else {
-        module->augment_size++;
-    }
-    return aug;
+    return EXIT_SUCCESS;
 }
 
 void *
@@ -2892,7 +2881,6 @@
     lys_when_free(ctx, uses->when);
 }
 
-
 static void
 yang_free_nodes(struct ly_ctx *ctx, struct lys_node *node)
 {
@@ -2962,6 +2950,18 @@
     }
 }
 
+static void
+yang_free_augment(struct ly_ctx *ctx, struct lys_node_augment *aug)
+{
+    lydict_remove(ctx, aug->target_name);
+    lydict_remove(ctx, aug->dsc);
+    lydict_remove(ctx, aug->ref);
+
+    lys_iffeature_free(aug->iffeature, aug->iffeature_size);
+    lys_when_free(ctx, aug->when);
+    yang_free_nodes(ctx, aug->child);
+}
+
 /* free common item from module and submodule */
 static void
 free_yang_common(struct lys_module *module, struct lys_node *node)
@@ -3523,11 +3523,40 @@
 }
 
 static int
-yang_check_uses(struct lys_module *module, struct lys_node_uses *uses, struct unres_schema *unres)
+yang_check_augment(struct lys_module *module, struct lys_node_augment *augment, int config_opt, struct unres_schema *unres)
 {
-    uint8_t i;
+    struct lys_node *child;
 
-     if (yang_check_iffeatures(module, NULL, uses, USES_KEYWORD, unres)) {
+    child = augment->child;
+    augment->child = NULL;
+
+    if (yang_check_nodes(module, (struct lys_node *)augment, child, config_opt, unres)) {
+        goto error;
+    }
+
+    if (yang_check_iffeatures(module, NULL, augment, AUGMENT_KEYWORD, unres)) {
+        goto error;
+    }
+
+    /* check XPath dependencies */
+    if (augment->when && (unres_schema_add_node(module, unres, augment, UNRES_XPATH, NULL) == -1)) {
+        goto error;
+    }
+
+    return EXIT_SUCCESS;
+error:
+    return EXIT_FAILURE;
+}
+
+static int
+yang_check_uses(struct lys_module *module, struct lys_node_uses *uses, int config_opt, struct unres_schema *unres)
+{
+    uint i, size;
+
+    size = uses->augment_size;
+    uses->augment_size = 0;
+
+    if (yang_check_iffeatures(module, NULL, uses, USES_KEYWORD, unres)) {
         goto error;
     }
 
@@ -3537,6 +3566,13 @@
         }
     }
 
+    for (i = 0; i < size; ++i) {
+        uses->augment_size++;
+        if (yang_check_augment(module, &uses->augment[i], config_opt, unres)) {
+            goto error;
+        }
+    }
+
     if (unres_schema_add_node(module, unres, uses, UNRES_USES, NULL) == -1) {
         goto error;
     }
@@ -3548,21 +3584,23 @@
 
     return EXIT_SUCCESS;
 error:
+    for (i = uses->augment_size; i < size; ++i) {
+        yang_free_augment(module->ctx, &uses->augment[i]);
+    }
     return EXIT_FAILURE;
 }
 
 static int
-yang_check_nodes(struct lys_module *module, struct lys_node *nodes, int config_opt, struct unres_schema *unres)
+yang_check_nodes(struct lys_module *module, struct lys_node *parent, struct lys_node *nodes,
+                 int config_opt, struct unres_schema *unres)
 {
-    struct lys_node *node = nodes, *sibling, *child, *parent;
+    struct lys_node *node = nodes, *sibling, *child;
 
     while (node) {
         sibling = node->next;
         child = node->child;
-        parent = node->parent;
         node->next = NULL;
         node->child = NULL;
-        node->parent = NULL;
         node->prev = node;
 
         if (lys_node_addchild(parent, module->type ? ((struct lys_submodule *)module)->belongsto: module, node)) {
@@ -3573,7 +3611,7 @@
         }
         config_opt = store_config_flag(node, config_opt);
 
-        if (yang_check_nodes(module, child, config_opt, unres)) {
+        if (yang_check_nodes(module, node, child, config_opt, unres)) {
             child = NULL;
             goto error;
         }
@@ -3651,7 +3689,7 @@
             }
             break;
         case LYS_USES:
-            if (yang_check_uses(module, (struct lys_node_uses *)node, unres)) {
+            if (yang_check_uses(module, (struct lys_node_uses *)node, config_opt, unres)) {
                 goto error;
             }
             break;
@@ -3674,7 +3712,10 @@
 static int
 yang_check_sub_module(struct lys_module *module, struct unres_schema *unres, struct lys_node *node)
 {
-    uint i, erase_identities = 1, erase_nodes = 1;
+    uint i, erase_identities = 1, erase_nodes = 1, aug_size;
+
+    aug_size = module->augment_size;
+    module->augment_size = 0;
 
     if (yang_check_typedef(module, NULL, unres)) {
         goto error;
@@ -3695,10 +3736,21 @@
         goto error;
     }
     erase_nodes = 0;
-    if (yang_check_nodes(module, node, CONFIG_INHERIT_ENABLE, unres)) {
+    if (yang_check_nodes(module, NULL, node, CONFIG_INHERIT_ENABLE, unres)) {
         goto error;
     }
 
+    /* check augments */
+    for (i = 0; i < aug_size; ++i) {
+        module->augment_size++;
+        if (yang_check_augment(module, &module->augment[i], CONFIG_INHERIT_ENABLE, unres)) {
+            goto error;
+        }
+        if (unres_schema_add_node(module, unres, &module->augment[i], UNRES_AUGMENT, NULL) == -1) {
+            goto error;
+        }
+    }
+
     return EXIT_SUCCESS;
 error:
     if (erase_identities) {
@@ -3707,5 +3759,9 @@
     if (erase_nodes) {
         yang_free_nodes(module->ctx, node);
     }
+    for (i = module->augment_size; i < aug_size; ++i) {
+        yang_free_augment(module->ctx, &module->augment[i]);
+    }
+
     return EXIT_FAILURE;
 }
diff --git a/src/parser_yang.h b/src/parser_yang.h
index 78f482e..511cf88 100644
--- a/src/parser_yang.h
+++ b/src/parser_yang.h
@@ -87,7 +87,6 @@
         struct lys_node_leaf *ptr_leaf;
         struct lys_tpdf *ptr_tpdf;
         struct lys_node_anydata *ptr_anydata;
-        struct lys_node_augment *ptr_augment;
         struct lys_node_rpc_action *ptr_rpc;
         struct lys_node_choice *ptr_choice;
     };
@@ -137,8 +136,6 @@
 
 void yang_read_revision(struct lys_module *module, char *value, struct lys_revision *retval);
 
-int yang_read_if_feature(struct lys_module *module, void *ptr, void *parent, char *value, struct unres_schema *unres, enum yytokentype type);
-
 int yang_read_message(struct lys_module *module,struct lys_restr *save,char *value, char *what, int message);
 
 int yang_read_presence(struct lys_module *module, struct lys_node_container *cont, char *value);
@@ -199,7 +196,7 @@
 
 void *yang_read_typedef(struct lys_module *module, struct lys_node *parent, char *value);
 
-void *yang_read_augment(struct lys_module *module, struct lys_node *parent, char *value);
+int yang_read_augment(struct lys_module *module, struct lys_node *parent, struct lys_node_augment *aug, char *value);
 
 void *yang_read_deviation(struct lys_module *module, char *value);
 
diff --git a/src/yang.y.in b/src/yang.y.in
index b26e872..a541f07 100644
--- a/src/yang.y.in
+++ b/src/yang.y.in
@@ -84,6 +84,7 @@
     struct type_deviation *deviation;

     struct lys_node_uses *uses;

     struct lys_node_inout *inout;

+    struct lys_node_augment *augment;

   } nodes;

 }

 

@@ -677,6 +678,15 @@
                                }

                                trg->ident = tmp;

                              }

+

+                             if (trg->augment_size) {

+                               tmp = realloc(trg->augment, trg->augment_size * sizeof *trg->augment);

+                               if (!tmp) {

+                                 LOGMEM;

+                                 YYABORT;

+                               }

+                               trg->augment = tmp;

+                             }

                            }

 

 body_stmts: @EMPTYDIR@ { actual = NULL; }

@@ -2748,151 +2758,95 @@
                                             s = NULL;

                                           }

 

-uses_augment_stmt: AUGMENT_KEYWORD sep uses_augment_arg_str { if (read_all) {

-                                                                if (!(actual = yang_read_augment(trg, actual, s))) {

-                                                                  YYABORT;

-                                                                }

-                                                                data_node = actual;

-                                                                s = NULL;

-                                                              }

-                                                            }

-                   '{' stmtsep

-                       augment_opt_stmt { if (read_all) {

-                                            if (!($7.node.flag & LYS_DATADEF)) {

-                                              LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "data-def or case", "uses/augment");

-                                              YYABORT;

-                                            }

-                                            config_inherit = $7.node.flag & CONFIG_MASK;

-                                            /* check XPath dependencies */

-                                            if ($7.node.ptr_augment->when &&

-                                                (unres_schema_add_node(trg, unres, $7.node.ptr_augment, UNRES_XPATH, NULL) == -1)) {

-                                              YYABORT;

-                                            }

-                                          }

-                                        }

-                   '}' ;

-

 uses_augment_arg_str: descendant_schema_nodeid optsep

   |  string_1

   ;

 

-augment_stmt: AUGMENT_KEYWORD sep augment_arg_str { if (read_all) {

-                                                      if (!(actual = yang_read_augment(trg, NULL, s))) {

-                                                        YYABORT;

-                                                      }

-                                                      data_node = actual;

-                                                      s = NULL;

-                                                    }

-                                                  }

-              '{' stmtsep

-                  augment_opt_stmt { if (read_all) {

-                                       if (!($7.node.flag & LYS_DATADEF)){

-                                         LOGVAL(LYE_MISSCHILDSTMT, LY_VLOG_NONE, NULL, "data-def or case", "augment");

-                                         YYABORT;

-                                       }

-                                       if (unres_schema_add_node(trg, unres, actual, UNRES_AUGMENT, NULL) == -1) {

-                                         YYABORT;

-                                       }

-                                       config_inherit = $7.node.flag & CONFIG_MASK;

-                                       /* check XPath dependencies */

-                                       if ($7.node.ptr_augment->when &&

-                                           (unres_schema_add_node(trg, unres, $7.node.ptr_augment, UNRES_XPATH, NULL) == -1)) {

-                                         YYABORT;

-                                       }

-                                     }

-                                   }

-               '}' ;

+uses_augment_arg: uses_augment_arg_str { void *parent;

 

-augment_opt_stmt: @EMPTYDIR@ { if (read_all) {

-                             $$.node.ptr_augment = actual;

-                             $$.node.flag = config_inherit;

-                             config_inherit = CONFIG_INHERIT_ENABLE;

-                             actual_type = AUGMENT_KEYWORD;

-                             if (size_arrays->node[size_arrays->next].if_features) {

-                               $$.node.ptr_augment->iffeature = calloc(size_arrays->node[size_arrays->next].if_features, sizeof *$$.node.ptr_augment->iffeature);

-                               if (!$$.node.ptr_augment->iffeature) {

-                                 LOGMEM;

+                                         parent = actual;

+                                         YANG_ADDELEM(((struct lys_node_uses *)actual)->augment,

+                                                      ((struct lys_node_uses *)actual)->augment_size);

+                                         if (yang_read_augment(trg, parent, actual, s)) {

+                                           YYABORT;

+                                         }

+                                         data_node = actual;

+                                         s = NULL;

+                                       }

+

+uses_augment_stmt: AUGMENT_KEYWORD sep uses_augment_arg

+                   '{' stmtsep

+                       augment_opt_stmt

+                   '}'

+

+augment_arg_str: absolute_schema_nodeids optsep

+  |  string_1

+

+augment_arg: augment_arg_str { YANG_ADDELEM(trg->augment, trg->augment_size);

+                               if (yang_read_augment(trg, NULL, actual, s)) {

                                  YYABORT;

                                }

+                               data_node = actual;

+                               s = NULL;

                              }

-                             size_arrays->next++;

-                           } else {

-                             $$.index = size_arrays->size;

-                             if (yang_add_elem(&size_arrays->node, &size_arrays->size)) {

-                               LOGMEM;

-                               YYABORT;

+

+augment_stmt: AUGMENT_KEYWORD sep augment_arg

+              '{' stmtsep

+                  augment_opt_stmt

+              '}'

+

+augment_opt_stmt: @EMPTYDIR@ { $$.augment = actual;

+                               actual_type = AUGMENT_KEYWORD;

                              }

-                           }

-                         }

-  |  augment_opt_stmt when_stmt { actual = $1.node.ptr_augment; actual_type = AUGMENT_KEYWORD; }

+  |  augment_opt_stmt when_stmt { actual = $1.augment;

+                                  actual_type = AUGMENT_KEYWORD;

+                                }

      stmtsep

-  |  augment_opt_stmt if_feature_stmt { if (read_all) {

-                                          if (yang_read_if_feature(trg, $1.node.ptr_augment, NULL, s, unres, AUGMENT_KEYWORD)) {YYABORT;}

-                                          s=NULL;

-                                        } else {

-                                          size_arrays->node[$1.index].if_features++;

-                                        }

+  |  augment_opt_stmt if_feature_stmt { YANG_ADDELEM($1.augment->iffeature, $1.augment->iffeature_size);

+                                        ((struct lys_iffeature *)actual)->features = (struct lys_feature**)s;

+                                        actual = $1.augment;

+                                        s = NULL;

                                       }

-  |  augment_opt_stmt status_stmt { if (read_all) {

-                                      /* hack - flags is bit field, so its address is taken as a member after

-                                       * 3 const char pointers in the lys_node_augment structure */

-                                      if (yang_check_flags((uint16_t*)((const char **)$1.node.ptr_augment + 3),

-                                                           LYS_STATUS_MASK, "status", "augment", $2, 0)) {

-                                        YYABORT;

-                                      }

+  |  augment_opt_stmt status_stmt { if ($1.augment->flags & LYS_STATUS_MASK) {

+                                      LOGVAL(LYE_TOOMANY, LY_VLOG_NONE, NULL, "status", "augment");

+                                      YYABORT;

                                     }

+                                    $1.augment->flags |= $2;

                                   }

-  |  augment_opt_stmt description_stmt { if (read_all && yang_read_description(trg, $1.node.ptr_augment, s, "augment")) {

+  |  augment_opt_stmt description_stmt { if (yang_read_description(trg, $1.augment, s, "augment")) {

                                            YYABORT;

                                          }

                                          s = NULL;

                                        }

-  |  augment_opt_stmt reference_stmt { if (read_all && yang_read_reference(trg, $1.node.ptr_augment, s, "augment")) {

+  |  augment_opt_stmt reference_stmt { if (yang_read_reference(trg, $1.augment, s, "augment")) {

                                          YYABORT;

                                        }

                                        s = NULL;

                                      }

-  |  augment_opt_stmt data_def_stmt { if (read_all) {

-                                        actual = $1.node.ptr_augment;

-                                        actual_type = AUGMENT_KEYWORD;

-                                        $1.node.flag |= LYS_DATADEF;

-                                        data_node = actual;

-                                      }

-                                    }

-     stmtsep { $$ = $1; }

-  |  augment_opt_stmt action_stmt { if (read_all) {

-                                      actual = $1.node.ptr_augment;

+  |  augment_opt_stmt data_def_stmt { actual = $1.augment;

                                       actual_type = AUGMENT_KEYWORD;

-                                      $1.node.flag |= LYS_DATADEF;

                                       data_node = actual;

                                     }

-                                  }

-     stmtsep { $$ = $1; }

-  |  augment_opt_stmt notification_stmt { if (read_all) {

-                                            actual = $1.node.ptr_augment;

-                                            actual_type = AUGMENT_KEYWORD;

-                                            $1.node.flag |= LYS_DATADEF;

-                                            data_node = actual;

-                                            if (trg->version < 2) {

-                                              LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "notification");

-                                              YYABORT;

-                                            }

-                                          }

-                                        }

-     stmtsep { $$ = $1; }

-  |  augment_opt_stmt case_stmt { if (read_all) {

-                                    actual = $1.node.ptr_augment;

+     stmtsep

+  |  augment_opt_stmt action_stmt { actual = $1.augment;

                                     actual_type = AUGMENT_KEYWORD;

-                                    $1.node.flag |= LYS_DATADEF;

                                     data_node = actual;

                                   }

+     stmtsep

+  |  augment_opt_stmt notification_stmt { actual = $1.augment;

+                                          actual_type = AUGMENT_KEYWORD;

+                                          data_node = actual;

+                                          if (trg->version < 2) {

+                                            LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "notification");

+                                            YYABORT;

+                                          }

+                                        }

+     stmtsep

+  |  augment_opt_stmt case_stmt { actual = $1.augment;

+                                  actual_type = AUGMENT_KEYWORD;

+                                  data_node = actual;

                                 }

-     stmtsep { $$ = $1; }

-  ;

-

-augment_arg_str: absolute_schema_nodeids optsep

-  |  string_1

-  ;

+     stmtsep

 

 action_arg_str: identifier_arg_str { if (module->version != 2) {

                                        LOGVAL(LYE_INSTMT, LY_VLOG_NONE, NULL, "action");