Fixed again: [Nested YANG choice does not work #342](https://github.com/clicon/clixon/issues/342)

Previous fix only for some sub-cases. New fix should work for all reecursive cases
This commit is contained in:
Olof hagsand 2022-07-14 22:24:44 +02:00
parent 657ddf9e87
commit 9537596a67
3 changed files with 128 additions and 82 deletions

View file

@ -274,58 +274,66 @@ check_when_condition(cxobj *x0p,
goto done;
}
/*! Given choice/case, remove all other cases.
/*! Get cloxest yang case and choice, if any
*/
static int
choice_delete_existing_children(cxobj *x0,
yang_stmt *y1c,
yang_stmt *y1case,
yang_stmt *y1choice)
choice_case_get(yang_stmt *yc,
yang_stmt **ycase,
yang_stmt **ychoice)
{
int retval = -1;
cxobj *x0c;
yang_stmt *y0c;
yang_stmt *y0case;
yang_stmt *y0choice;
cxobj *x0prev;
yang_stmt *y0p;
/* Now traverse existing tree and compare with choice yang structure of added tree */
x0prev = NULL;
x0c = NULL;
while ((x0c = xml_child_each(x0, x0c, CX_ELMNT)) != NULL) {
if ((y0c = xml_spec(x0c)) == NULL ||
yang_parent_get(y0c) == NULL){
x0prev = x0c;
continue;
}
y0p = yang_parent_get(y0c);
if (yang_keyword_get(y0p) == Y_CASE){
y0case = y0p;
y0choice = yang_parent_get(y0case);
}
else if (yang_keyword_get(y0p) == Y_CHOICE){
y0case = NULL;
y0choice = y0p;
}
else{
x0prev = x0c;
continue;
}
if (y0choice == y1choice){
if ((y0case == NULL && y0c != y1c) ||
y0case != y1case){
if (xml_purge(x0c) < 0)
goto done;
x0c = x0prev;
continue;
}
}
x0prev = x0c;
yang_stmt *yp;
if ((yp = yang_parent_get(yc)) == NULL)
return 0;
if (yang_keyword_get(yp) == Y_CASE){
*ycase = yp;
*ychoice = yang_parent_get(yp);
return 1;
}
retval = 0;
done:
return retval;
else if (yang_keyword_get(yp) == Y_CHOICE){
*ycase = NULL;
*ychoice = yp;
return 1;
}
return 0;
}
/*! Check if x0/y0 is part of other choice/case than y1 recursively , if so purge
* @retval 0 No, y0 it is not in other case than y1
* @retval 1 yes, y0 is in other case than y1
*/
static int
choice_is_other(yang_stmt *y0c,
yang_stmt *y0case,
yang_stmt *y0choice,
yang_stmt *y1c,
yang_stmt *y1case,
yang_stmt *y1choice)
{
yang_stmt *ycase;
yang_stmt *ychoice;
if (y0choice == y1choice){
if ((y0case == NULL && y0c != y1c) ||
y0case != y1case){
return 1;
}
}
else {
/* First recurse y0 */
if (choice_case_get(y0choice, &ycase, &ychoice)){
if (choice_is_other(y0choice, ycase, ychoice,
y1c, y1case, y1choice) == 1)
return 1;
}
/* Second recurse y1 */
if (choice_case_get(y1choice, &ycase, &ychoice)){
if (choice_is_other(y0choice, y0case, y0choice,
y1choice, ycase, ychoice) == 1)
return 1;
}
}
return 0;
}
/*! Check if choice nodes and implicitly remove all other cases.
@ -346,31 +354,41 @@ choice_delete_existing_children(cxobj *x0,
* other cases inside the choice.
*/
static int
check_delete_existing_case(cxobj *x0,
yang_stmt *y1c)
choice_delete_other(cxobj *x0,
yang_stmt *y1c)
{
int retval = -1;
yang_stmt *yp;
yang_stmt *y1case;
yang_stmt *y1choice;
if ((yp = yang_parent_get(y1c)) == NULL)
cxobj *x0c;
cxobj *x0prev;
yang_stmt *y0c;
yang_stmt *y0case;
yang_stmt *y0choice;
yang_stmt *y1case = NULL;
yang_stmt *y1choice = NULL;
if (choice_case_get(y1c, &y1case, &y1choice) == 0)
goto ok;
if (yang_keyword_get(yp) == Y_CASE){
y1case = yp;
y1choice = yang_parent_get(y1case);
x0prev = NULL;
x0c = NULL;
while ((x0c = xml_child_each(x0, x0c, CX_ELMNT)) != NULL) {
if ((y0c = xml_spec(x0c)) == NULL ||
yang_parent_get(y0c) == NULL){
x0prev = x0c;
continue;
}
if (choice_case_get(y0c, &y0case, &y0choice) == 0){
x0prev = x0c;
continue;
}
/* Check if x0/y0 is part of other choice/case than y1 recursively , if so purge */
if (choice_is_other(y0c, y0case, y0choice, y1c, y1case, y1choice) == 1){
if (xml_purge(x0c) < 0)
goto done;
x0c = x0prev;
continue;
}
x0prev = x0c;
}
else if (yang_keyword_get(yp) == Y_CHOICE){
y1case = NULL;
y1choice = yp;
}
else
goto ok;
if (choice_delete_existing_children(x0, y1c, y1case, y1choice) < 0)
goto done;
/* Recursive call */
if (check_delete_existing_case(x0, y1choice) < 0)
goto done;
ok:
retval = 0;
done:
@ -827,8 +845,8 @@ text_modify(clicon_handle h,
x1cname, yang_find_mynamespace(y0));
goto done;
}
/* Check if existing case should be deleted */
if (check_delete_existing_case(x0, yc) < 0)
/* Check if existing choice/case should be deleted */
if (choice_delete_other(x0, yc) < 0)
goto done;
/* See if there is a corresponding node in the base tree */
x0c = NULL;