yang - add deviate delete statement
diff --git a/src/parser_yang.c b/src/parser_yang.c
index 29dea1e..8816f07 100644
--- a/src/parser_yang.c
+++ b/src/parser_yang.c
@@ -588,6 +588,9 @@
retval = &(*((struct type_deviation *)node)->trg_must)[(*((struct type_deviation *)node)->trg_must_size)++];
memset(retval, 0, sizeof *retval);
break;
+ case DELETE_KEYWORD:
+ retval = &((struct type_deviation *)node)->deviate->must[((struct type_deviation *)node)->deviate->must_size++];
+ break;
}
retval->expr = transform_schema2json(module, value, line);
if (!retval->expr || lyxp_syntax_check(retval->expr, line)) {
@@ -1748,6 +1751,23 @@
}
}
+ if (dev->deviate->mod == LY_DEVIATE_DEL) {
+ /* check values */
+ if (*stritem != dev->deviate->units) {
+ LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, dev->deviate->units, "units");
+ LOGVAL(LYE_SPEC, 0, 0, NULL, "Value differs from the target being deleted.");
+ goto error;
+ }
+ /* remove current units value of the target */
+ lydict_remove(ctx, *stritem);
+ } else { /* add (already checked) and replace */
+ /* remove current units value of the target ... */
+ lydict_remove(ctx, *stritem);
+
+ /* ... and replace it with the value specified in deviation */
+ *stritem = lydict_insert(ctx, dev->deviate->units, 0);
+ }
+
return EXIT_SUCCESS;
error:
@@ -1797,11 +1817,13 @@
*dev->trg_must = dev->deviate->must;
dev->deviate->must = &((*dev->trg_must)[*dev->trg_must_size]);
dev->deviate->must_size = c_must;
- }
-
- if (!dev->deviate->must) {
- LOGMEM;
- goto error;
+ } else {
+ /* LY_DEVIATE_DEL */
+ dev->deviate->must = calloc(c_must, sizeof *dev->deviate->must);
+ if (!dev->deviate->must) {
+ LOGMEM;
+ goto error;
+ }
}
return EXIT_SUCCESS;
@@ -1835,6 +1857,13 @@
dev->deviate->unique = &list->unique[list->unique_size];
dev->deviate->unique_size = c_uniq;
memset(dev->deviate->unique, 0, c_uniq * sizeof *dev->deviate->unique);
+ } else {
+ /* LY_DEVIATE_DEL */
+ dev->deviate->unique = calloc(c_uniq, sizeof *dev->deviate->unique);
+ if (!dev->deviate->unique) {
+ LOGMEM;
+ goto error;
+ }
}
return EXIT_SUCCESS;
@@ -1876,12 +1905,20 @@
LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, dev->deviate->dflt, "default");
goto error;
}
- /* add (already checked) and replace */
- choice->dflt = node;
- if (!choice->dflt) {
- /* default branch not found */
- LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, dev->deviate->dflt, "default");
- goto error;
+ if (dev->deviate->mod == LY_DEVIATE_DEL) {
+ if (!choice->dflt || (choice->dflt != node)) {
+ LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, dev->deviate->dflt, "default");
+ LOGVAL(LYE_SPEC, 0, 0, NULL, "Value differs from the target being deleted.");
+ goto error;
+ }
+ choice->dflt = NULL;
+ } else { /* add (already checked) and replace */
+ choice->dflt = node;
+ if (!choice->dflt) {
+ /* default branch not found */
+ LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, dev->deviate->dflt, "default");
+ goto error;
+ }
}
} else if (dev->target->nodetype == LYS_LEAF) {
leaf = (struct lys_node_leaf *)dev->target;
@@ -1894,13 +1931,22 @@
goto error;
}
}
+ if (dev->deviate->mod == LY_DEVIATE_DEL) {
+ if (!leaf->dflt || (leaf->dflt != dev->deviate->dflt)) {
+ LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, dev->deviate->dflt, "default");
+ LOGVAL(LYE_SPEC, 0, 0, NULL, "Value differs from the target being deleted.");
+ goto error;
+ }
+ /* remove value */
+ lydict_remove(ctx, leaf->dflt);
+ leaf->dflt = NULL;
+ } else { /* add (already checked) and replace */
+ /* remove value */
+ lydict_remove(ctx, leaf->dflt);
- /* add (already checked) and replace */
- /* remove value */
- lydict_remove(ctx, leaf->dflt);
-
- /* set new value */
- leaf->dflt = lydict_insert(ctx, dev->deviate->dflt, 0);
+ /* set new value */
+ leaf->dflt = lydict_insert(ctx, dev->deviate->dflt, 0);
+ }
} else {
/* invalid target for default value */
LOGVAL(LYE_INSTMT, line, LY_VLOG_NONE, NULL, "default");
@@ -2029,3 +2075,113 @@
error:
return EXIT_FAILURE;
}
+
+int
+yang_check_deviate_must(struct ly_ctx *ctx, struct type_deviation *dev, int line)
+{
+ int i;
+
+ /* find must to delete, we are ok with just matching conditions */
+ for (i = 0; i < *dev->trg_must_size; i++) {
+ if (ly_strequal(dev->deviate->must[dev->deviate->must_size - 1].expr, (*dev->trg_must)[i].expr, 1)) {
+ /* we have a match, free the must structure ... */
+ lys_restr_free(ctx, &((*dev->trg_must)[i]));
+ /* ... and maintain the array */
+ (*dev->trg_must_size)--;
+ if (i != *dev->trg_must_size) {
+ (*dev->trg_must)[i].expr = (*dev->trg_must)[*dev->trg_must_size].expr;
+ (*dev->trg_must)[i].dsc = (*dev->trg_must)[*dev->trg_must_size].dsc;
+ (*dev->trg_must)[i].ref = (*dev->trg_must)[*dev->trg_must_size].ref;
+ (*dev->trg_must)[i].eapptag = (*dev->trg_must)[*dev->trg_must_size].eapptag;
+ (*dev->trg_must)[i].emsg = (*dev->trg_must)[*dev->trg_must_size].emsg;
+ }
+ if (!(*dev->trg_must_size)) {
+ free(*dev->trg_must);
+ *dev->trg_must = NULL;
+ } else {
+ (*dev->trg_must)[*dev->trg_must_size].expr = NULL;
+ (*dev->trg_must)[*dev->trg_must_size].dsc = NULL;
+ (*dev->trg_must)[*dev->trg_must_size].ref = NULL;
+ (*dev->trg_must)[*dev->trg_must_size].eapptag = NULL;
+ (*dev->trg_must)[*dev->trg_must_size].emsg = NULL;
+ }
+
+ i = -1; /* set match flag */
+ break;
+ }
+ }
+ if (i != -1) {
+ /* no match found */
+ LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, dev->deviate->must[dev->deviate->must_size - 1].expr, "must");
+ LOGVAL(LYE_SPEC, 0, 0, NULL, "Value does not match any must from the target.");
+ return EXIT_FAILURE;
+ }
+
+ return EXIT_SUCCESS;
+}
+
+int
+yang_check_deviate_unique(struct lys_module *module, struct type_deviation *dev, char *value, int line)
+{
+ struct lys_node_list *list;
+ int i, j;
+
+ list = (struct lys_node_list *)dev->target;
+ if (yang_fill_unique(module, list, &dev->deviate->unique[dev->deviate->unique_size], value, NULL, line)) {
+ dev->deviate->unique_size++;
+ goto error;
+ }
+
+ /* find unique structures to delete */
+ for (i = 0; i < list->unique_size; i++) {
+ if (list->unique[i].expr_size != dev->deviate->unique[dev->deviate->unique_size].expr_size) {
+ continue;
+ }
+
+ for (j = 0; j < dev->deviate->unique[dev->deviate->unique_size].expr_size; j++) {
+ if (!ly_strequal(list->unique[i].expr[j], dev->deviate->unique[dev->deviate->unique_size].expr[j], 1)) {
+ break;
+ }
+ }
+
+ if (j == dev->deviate->unique[dev->deviate->unique_size].expr_size) {
+ /* we have a match, free the unique structure ... */
+ for (j = 0; j < list->unique[i].expr_size; j++) {
+ lydict_remove(module->ctx, list->unique[i].expr[j]);
+ }
+ free(list->unique[i].expr);
+ /* ... and maintain the array */
+ list->unique_size--;
+ if (i != list->unique_size) {
+ list->unique[i].expr_size = list->unique[list->unique_size].expr_size;
+ list->unique[i].expr = list->unique[list->unique_size].expr;
+ }
+
+ if (!list->unique_size) {
+ free(list->unique);
+ list->unique = NULL;
+ } else {
+ list->unique[list->unique_size].expr_size = 0;
+ list->unique[list->unique_size].expr = NULL;
+ }
+
+ i = -1; /* set match flag */
+ break;
+ }
+ }
+ dev->deviate->unique_size++;
+
+ if (i != -1) {
+ /* no match found */
+ LOGVAL(LYE_INARG, line, LY_VLOG_NONE, NULL, value, "unique");
+ LOGVAL(LYE_SPEC, 0, 0, NULL, "Value differs from the target being deleted.");
+ goto error;
+ }
+
+ free(value);
+ return EXIT_SUCCESS;
+
+error:
+ free(value);
+ return EXIT_FAILURE;
+}
diff --git a/src/parser_yang.h b/src/parser_yang.h
index a45ea43..54d3af2 100644
--- a/src/parser_yang.h
+++ b/src/parser_yang.h
@@ -263,4 +263,9 @@
*/
int yang_read_deviate_minmax(struct type_deviation *dev, uint32_t value, int type, int line);
+int yang_check_deviate_must(struct ly_ctx *ctx, struct type_deviation *dev, int line);
+
+int yang_check_deviate_unique(struct lys_module *module, struct type_deviation *dev, char *value, int line);
+
+
#endif /* LY_PARSER_YANG_H_ */
diff --git a/src/yang.y b/src/yang.y
index ce34bb3..aafb11e 100644
--- a/src/yang.y
+++ b/src/yang.y
@@ -197,6 +197,7 @@
%type <nodes> notification_opt_stmt
%type <nodes> deviation_opt_stmt
%type <nodes> deviate_add_opt_stmt
+%type <nodes> deviate_delete_opt_stmt
%destructor { free($$); } tmp_identifier_arg_str
%destructor { if (read_all && $$.choice.s) { free($$.choice.s); } } choice_opt_stmt
@@ -2511,19 +2512,76 @@
}
}
-deviate_delete_stmt: DELETE_KEYWORD optsep deviate_delete_end;
+deviate_delete_stmt: DELETE_KEYWORD optsep { if (read_all && yang_read_deviate(actual, LY_DEVIATE_DEL, yylineno)) {
+ YYERROR;
+ }
+ }
+ deviate_delete_end
deviate_delete_end: ';'
- | '{' start_check
- deviate_delete_opt_stmt {free_check();}
+ | '{' stmtsep
+ deviate_delete_opt_stmt
'}' ;
-deviate_delete_opt_stmt: %empty
- | deviate_delete_opt_stmt yychecked_1 units_stmt
- | deviate_delete_opt_stmt must_stmt
- | deviate_delete_opt_stmt unique_stmt
- | deviate_delete_opt_stmt yychecked_2 default_stmt
- ;
+deviate_delete_opt_stmt: %empty { if (read_all) {
+ $$.deviation = actual;
+ actual_type = DELETE_KEYWORD;
+ if (size_arrays->node[size_arrays->next].must) {
+ if (yang_read_deviate_must(module->ctx, actual, size_arrays->node[size_arrays->next].must, yylineno)) {
+ YYERROR;
+ }
+ }
+ if (size_arrays->node[size_arrays->next].unique) {
+ if (yang_read_deviate_unique(module->ctx, actual, size_arrays->node[size_arrays->next].unique, yylineno)) {
+ YYERROR;
+ }
+ }
+ size_arrays->next++;
+ } else {
+ $$.index = size_arrays->size;
+ if (yang_add_elem(&size_arrays->node, &size_arrays->size)) {
+ LOGMEM;
+ YYERROR;
+ }
+ }
+ }
+ | deviate_delete_opt_stmt units_stmt { if (read_all) {
+ if (yang_read_deviate_units(module->ctx, $1.deviation, s, yylineno)) {
+ YYERROR;
+ }
+ s = NULL;
+ $$ = $1;
+ }
+ }
+ | deviate_delete_opt_stmt must_stmt { if (read_all) {
+ if (yang_check_deviate_must(module->ctx, $1.deviation, yylineno)) {
+ YYERROR;
+ }
+ actual = $1.deviation;
+ actual_type = DELETE_KEYWORD;
+ $$ = $1;
+ } else {
+ size_arrays->node[$1.index].must++;
+ }
+ }
+ | deviate_delete_opt_stmt unique_stmt { if (read_all) {
+ if (yang_check_deviate_unique(module, $1.deviation, s, yylineno)) {
+ YYERROR;
+ }
+ s = NULL;
+ $$ = $1;
+ } else {
+ size_arrays->node[$1.index].unique++;
+ }
+ }
+ | deviate_delete_opt_stmt default_stmt { if (read_all) {
+ if (yang_read_deviate_default(module->ctx, $1.deviation, s, yylineno)) {
+ YYERROR;
+ }
+ s = NULL;
+ $$ = $1;
+ }
+ }
deviate_replace_stmt: REPLACE_KEYWORD optsep deviate_replace_end;