Skip to content

Commit

Permalink
* Partially corrected: [yang type range statement does not support mu…
Browse files Browse the repository at this point in the history
…ltiple values](#59).

  * Should work for netconf and restconf, but not for CLI.
* Fixed again: [Range parsing is not RFC 7950 compliant](#71)
  • Loading branch information
olofhagsand committed Feb 5, 2019
1 parent f718c71 commit 19343c2
Show file tree
Hide file tree
Showing 6 changed files with 327 additions and 200 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,9 @@
* <!DOCTYPE (ie DTD) is not supported.
### Corrected Bugs
* Partially corrected: [yang type range statement does not support multiple values](https://github.com/clicon/clixon/issues/59).
* Should work for netconf and restconf, but not for CLI.
* Fixed again: [Range parsing is not RFC 7950 compliant](https://github.com/clicon/clixon/issues/71)
* xml_cmp() compares numeric nodes based on string value [https://github.com/clicon/clixon/issues/64]
* xml_cmp() respects 'ordered-by user' for state nodes, which violates RFC 7950 [https://github.com/clicon/clixon/issues/63]. (Thanks JDL)
* XML<>JSON conversion problems [https://github.com/clicon/clixon/issues/66]
Expand Down
150 changes: 98 additions & 52 deletions apps/cli/cli_generate.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
#include <errno.h>
#include <assert.h>
#include <fcntl.h>
#include <syslog.h>
#include <sys/param.h>
#include <math.h> /* For pow() kludge in cvtype_max2str_dup2 */

Expand Down Expand Up @@ -162,6 +163,98 @@ cli_callback_generate(clicon_handle h,
return retval;
}


/*! Generate identityref statements for CLI variables
* @param[in] ys Yang statement
* @param[in] ytype Yang union type being resolved
* @param[in] helptext CLI help text
* @param[out] cb Buffer where cligen code is written
* @see yang2cli_var_sub Its sub-function
*/
static int
yang2cli_var_identityref(yang_stmt *ys,
yang_stmt *ytype,
char *cvtypestr,
char *helptext,
cbuf *cb)
{
int retval = -1;
yang_stmt *ybaseref;
yang_stmt *ybaseid;
cg_var *cv = NULL;
char *name;
char *id;
int i;

/* Add a wildchar string first -let validate take it for default prefix */
cprintf(cb, ">");
if (helptext)
cprintf(cb, "(\"%s\")", helptext);
if ((ybaseref = yang_find((yang_node*)ytype, Y_BASE, NULL)) != NULL &&
(ybaseid = yang_find_identity(ys, ybaseref->ys_argument)) != NULL){
if (cvec_len(ybaseid->ys_cvec) > 0){
cprintf(cb, "|<%s:%s choice:", ys->ys_argument, cvtypestr);
i = 0;
while ((cv = cvec_each(ybaseid->ys_cvec, cv)) != NULL){
if (i++)
cprintf(cb, "|");
name = strdup(cv_name_get(cv));
if ((id=strchr(name, ':')) != NULL)
*id = '\0';
cprintf(cb, "%s:%s", name, id+1);
if (name)
free(name);
}
}
}
retval = 0;
// done:
return retval;
}

/*! Generate range check statements for CLI variables
* @param[out] cb Buffer where cligen code is written
* @see yang2cli_var_sub Its sub-function
*/
static int
yang2cli_var_range(yang_stmt *ys,
cvec *cvv,
int options,
cbuf *cb)
{
int retval = -1;
int i;
cg_var *cv;

/* Loop through range_min and range_min..range_max */
i = 0;
while (i<cvec_len(cvv)){
if (i){
// clicon_log(LOG_NOTICE, "%s: Warning %s has more ranges, ignoring", __FUNCTION__, ys->ys_argument);
break;
}
cv = cvec_i(cvv, i++);
if (strcmp(cv_name_get(cv),"range_min") == 0){
cprintf(cb, " %s[", (options&YANG_OPTIONS_RANGE)?"range":"length");
cv2cbuf(cv, cb);
cprintf(cb,":");
/* probe next */
if (i<cvec_len(cvv) &&
(cv = cvec_i(cvv, i)) != NULL &&
strcmp(cv_name_get(cv),"range_max") == 0){
i++;
cv2cbuf(cv, cb);
}
else /* If not, it is a single number range [x:x]*/
cv2cbuf(cv, cb);
cprintf(cb,"]");
}
}
retval = 0;
// done:
return retval;
}

/* Forward */
static int yang2cli_stmt(clicon_handle h, yang_stmt *ys, cbuf *cb,
enum genmodel_type gt, int level);
Expand All @@ -175,7 +268,7 @@ static int yang2cli_var_union(clicon_handle h, yang_stmt *ys, char *origtype,
* @param[in] h Clixon handle
* @param[in] ys Yang statement
* @param[in] ytype Yang union type being resolved
* @param[in] cb Buffer where cligen code is written
* @param[out] cb Buffer where cligen code is written
* @param[in] helptext CLI help text
*/
static int
Expand All @@ -196,7 +289,6 @@ yang2cli_var_sub(clicon_handle h,
yang_stmt *yi = NULL;
int i = 0;
char *cvtypestr;
cg_var *cv;

if (cvtype == CGV_VOID){
retval = 0;
Expand All @@ -223,61 +315,16 @@ yang2cli_var_sub(clicon_handle h,
}
}
else if (strcmp(type, "identityref") == 0){
yang_stmt *ybaseref;
yang_stmt *ybaseid;
cg_var *cv = NULL;
char *name;
char *id;
/* Add a wildchar string first -let validate take it for default prefix */
cprintf(cb, ">");
if (helptext)
cprintf(cb, "(\"%s\")", helptext);
if ((ybaseref = yang_find((yang_node*)ytype, Y_BASE, NULL)) != NULL &&
(ybaseid = yang_find_identity(ys, ybaseref->ys_argument)) != NULL){
if (cvec_len(ybaseid->ys_cvec) > 0){
cprintf(cb, "|<%s:%s choice:", ys->ys_argument, cvtypestr);
i = 0;
while ((cv = cvec_each(ybaseid->ys_cvec, cv)) != NULL){
if (i++)
cprintf(cb, "|");
name = strdup(cv_name_get(cv));
if ((id=strchr(name, ':')) != NULL)
*id = '\0';
cprintf(cb, "%s:%s", name, id+1);
if (name)
free(name);
}
}
}
if (yang2cli_var_identityref(ys, ytype, cvtypestr, helptext, cb) < 0)
goto done;
}
}

if (options & YANG_OPTIONS_FRACTION_DIGITS)
cprintf(cb, " fraction-digits:%u", fraction_digits);

if (options & (YANG_OPTIONS_RANGE|YANG_OPTIONS_LENGTH)){
/* Loop through range_min and range_min..rang_max */
i = 0;
while (i<cvec_len(cvv)){
// if (i)
// clicon_log(LOG_NOTICE, "%s: Warning %s has more ranges, ignoring", __FUNCTION__, ys->ys_argument);
cv = cvec_i(cvv, i++);
if (strcmp(cv_name_get(cv),"range_min") == 0){
cprintf(cb, " %s[", (options&YANG_OPTIONS_RANGE)?"range":"length");
cv2cbuf(cv, cb);
cprintf(cb,":");
/* probe next */
if (i<cvec_len(cvv) &&
(cv = cvec_i(cvv, i)) != NULL &&
strcmp(cv_name_get(cv),"range_max") == 0){
i++;
cv2cbuf(cv, cb);
}
else /* If not, it is a single number range [x:x]*/
cv2cbuf(cv, cb);
cprintf(cb,"]");
}
}
if (yang2cli_var_range(ys, cvv, options, cb) < 0)
goto done;
}
if (options & YANG_OPTIONS_PATTERN){
char *posix = NULL;
Expand All @@ -292,7 +339,6 @@ yang2cli_var_sub(clicon_handle h,
cprintf(cb, "(\"%s\")", helptext);
if (type && strcmp(type, "identityref") == 0)
cprintf(cb, ")");

retval = 0;
done:
return retval;
Expand Down
9 changes: 5 additions & 4 deletions lib/src/clixon_string.c
Original file line number Diff line number Diff line change
Expand Up @@ -624,13 +624,14 @@ clixon_trim(char *str)
char *s = str;
int i;

while (strlen(s) && isblank(s[0]))
while (strlen(s) && isblank(s[0])) /* trim from front */
s++;
for (i=0; i<strlen(s); i++)
if (isblank(s[i])){
for (i=strlen(s)-1; i>=0; i--){ /* trim from rear */
if (isblank(s[i]))
s[i] = '\0';
else
break;
}
}
return s;
}

Expand Down
92 changes: 41 additions & 51 deletions lib/src/clixon_yang.c
Original file line number Diff line number Diff line change
Expand Up @@ -1152,9 +1152,7 @@ bound_add(yang_stmt *ys,
enum cv_type cvtype,
char *name,
char *val,
int options,
uint8_t fraction_digits
)
uint8_t fraction_digits)
{
int retval = -1;
cg_var *cv;
Expand All @@ -1169,7 +1167,7 @@ bound_add(yang_stmt *ys,
clicon_err(OE_YANG, errno, "cv_name_set(%s)", name);
goto done;
}
if (options & YANG_OPTIONS_FRACTION_DIGITS && cvtype == CGV_DEC64)
if (cvtype == CGV_DEC64)
cv_dec64_n_set(cv, fraction_digits);
if (strcmp(val, "min") == 0)
cv_min_set(cv);
Expand All @@ -1189,6 +1187,43 @@ bound_add(yang_stmt *ys,
return retval;
}

/*! Common range length parsing of "x .. y | z..w " statements
*/
static int
range_parse(yang_stmt *ys,
enum cv_type cvtype,
uint8_t fraction_digits)
{
int retval = -1;
char **vec = NULL;
int nvec;
int i;
char *v;
char *v2;

if ((vec = clicon_strsep(ys->ys_argument, "|", &nvec)) == NULL)
goto done;
for (i=0; i<nvec; i++){
v = vec[i];
if ((v2 = strstr(v, "..")) != NULL){
*v2 = '\0';
v2 += 2;
v2 = clixon_trim(v2); /* trim blanks */
}
v = clixon_trim(v); /* trim blanks */
if (bound_add(ys, cvtype, "range_min", v, fraction_digits) < 0)
goto done;
if (v2)
if (bound_add(ys, cvtype, "range_max", v2, fraction_digits) < 0)
goto done;
}
retval = 0;
done:
if (vec)
free(vec);
return retval;
}

/*! Populate string built-in range statement
*
* Create cvec variables "range_min" and "range_max". Assume parent is type.
Expand All @@ -1213,11 +1248,6 @@ ys_populate_range(yang_stmt *ys,
int options = 0x0;
uint8_t fraction_digits;
enum cv_type cvtype = CGV_ERR;
char **vec = NULL;
char *v;
char *v2;
int nvec;
int i;

yparent = ys->ys_parent; /* Find parent: type */
if (yparent->yn_keyword != Y_TYPE){
Expand All @@ -1232,28 +1262,10 @@ ys_populate_range(yang_stmt *ys,
/* This handles non-resolved also */
if (clicon_type2cv(origtype, restype, ys, &cvtype) < 0)
goto done;
if ((vec = clicon_strsep(ys->ys_argument, "|", &nvec)) == NULL)
if (range_parse(ys, cvtype, fraction_digits) < 0)
goto done;
for (i=0; i<nvec; i++){
v = vec[i++];
v = clixon_trim(v); /* trim blanks */
if ((v2 = strstr(v, "..")) != NULL){
*v2 = '\0';
v2 += 2;
v2 = clixon_trim(v2); /* trim blanks */
}
if (bound_add(ys, cvtype, "range_min", v,
options, fraction_digits) < 0)
goto done;
if (v2)
if (bound_add(ys, cvtype, "range_max",v2,
options, fraction_digits) < 0)
goto done;
}
retval = 0;
done:
if (vec)
free(vec);
return retval;
}

Expand All @@ -1276,39 +1288,17 @@ ys_populate_length(yang_stmt *ys,
int retval = -1;
yang_node *yparent; /* type */
enum cv_type cvtype = CGV_ERR;
char **vec = NULL;
char *v;
int nvec;
int i;
char *v2;

yparent = ys->ys_parent; /* Find parent: type */
if (yparent->yn_keyword != Y_TYPE){
clicon_err(OE_YANG, 0, "parent should be type");
goto done;
}
cvtype = CGV_UINT64;
if ((vec = clicon_strsep(ys->ys_argument, "|", &nvec)) == NULL)
if (range_parse(ys, cvtype, 0) < 0)
goto done;
for (i=0; i<nvec; i++){

v = vec[i++];
v = clixon_trim(v); /* trim blanks */
if ((v2 = strstr(v, "..")) != NULL){
*v2 = '\0';
v2 += 2;
v2 = clixon_trim(v2); /* trim blanks */
}
if (bound_add(ys, cvtype, "range_min", v, 0, 0) < 0)
goto done;
if (v2)
if (bound_add(ys, cvtype, "range_max",v2, 0, 0) < 0)
goto done;
}
retval = 0;
done:
if (vec)
free(vec);
return retval;
}

Expand Down
Loading

0 comments on commit 19343c2

Please sign in to comment.