* YANG Leafref feature update

* Closer adherence to RFC 7950. Some of this is changed behavior, some is new feature.
  * Essentially instead of looking at the referring leaf, context is referred(target) node
  * Validation uses referred node
    * Validation changed to use type of referred node, instead of just "string"
  * Auto-cli
    * Changed to use type of referred node for typecheck
    * Completion uses referred node
  * Required instance / less strict validation
    * New: Leafrefs must refer to existing data leaf ONLY IF YANG `required-instance` is true
    * Previous: All leafrefs must refer to existing data leaf node
* Fixed: [Autocli does not offer completions for leafref to identityref #254](https://github.com/clicon/clixon/issues/254)
This commit is contained in:
Olof hagsand 2021-08-16 13:57:51 +02:00
parent 8db716ca07
commit 980718178a
18 changed files with 1151 additions and 115 deletions

View file

@ -480,15 +480,15 @@ xp_eval_predicate(xp_ctx *xc,
cxobj *x;
xp_ctx *xcc;
if (xs->xs_c0 == NULL){ /* empty */
if ((xr0 = ctx_dup(xc)) == NULL)
goto done;
}
else{ /* eval previous predicates */
if (xs->xs_c0 != NULL){ /* eval previous predicates */
if (xp_eval(xc, xs->xs_c0, nsc, localonly, &xr0) < 0)
goto done;
}
if (xs->xs_c1){
else{ /* empty */
if ((xr0 = ctx_dup(xc)) == NULL)
goto done;
}
if (xs->xs_c1){ /* Second child */
/* Loop over each node in the nodeset */
assert (xr0->xc_type == XT_NODESET);
if ((xr1 = malloc(sizeof(*xr1))) == NULL){
@ -537,16 +537,18 @@ xp_eval_predicate(xp_ctx *xc,
ctx_free(xrc);
}
}
assert(xr0||xr1);
if (xr0 == NULL && xr1 == NULL){
clicon_err(OE_XML, EFAULT, "Internal error: no result produced");
goto done;
}
if (xr1){
*xrp = xr1;
xr1 = NULL;
}
else
if (xr0){
*xrp = xr0;
xr0 = NULL;
}
else if (xr0){
*xrp = xr0;
xr0 = NULL;
}
retval = 0;
done:
if (xr0)
@ -1005,12 +1007,11 @@ xp_eval(xp_ctx *xc,
/* // is short for /descendant-or-self::node()/ */
if (xs->xs_int == A_DESCENDANT_OR_SELF)
xc->xc_descendant = 1; /* XXX need to set to 0 in sub */
break;
case XP_STEP: /* XP_NODE is first argument -not called explicitly */
if (xp_eval_step(xc, xs, nsc, localonly, xrp) < 0)
goto done;
goto ok;
goto ok; /* Skip generic child traverse */
break;
case XP_PRED:
if (xp_eval_predicate(xc, xs, nsc, localonly, xrp) < 0)
@ -1167,12 +1168,11 @@ xp_eval(xp_ctx *xc,
/* Eval second child c1
* Note, some operators like locationpath, need transitive context (use_xr0)
*/
if (xs->xs_c1)
if (xs->xs_c1){
if (xp_eval(use_xr0?xr0:xc, xs->xs_c1, nsc, localonly, &xr1) < 0)
goto done;
/* Actions after second child
*/
if (xs->xs_c1)
/* Actions after second child
*/
switch (xs->xs_type){
case XP_AND: /* combine and and or ops */
if (xp_logop(xr0, xr1, xs->xs_int, &xr2) < 0)
@ -1192,15 +1192,12 @@ xp_eval(xp_ctx *xc,
default:
break;
}
}
xc->xc_descendant = 0;
#if 0
assert(xr0||xr1||xr2); /* for debugging */
#else
if (xr0 == NULL && xr1 == NULL && xr2 == NULL){
clicon_err(OE_XML, EFAULT, "Internal error: no result produced");
goto done;
}
#endif
if (xr2){
*xrp = xr2;
xr2 = NULL;