Skip to content

Commit

Permalink
Keyword "min" (not only "max") can be used in built-in types "range"…
Browse files Browse the repository at this point in the history
… and "length" statements.
  • Loading branch information
olofhagsand committed Jan 6, 2019
1 parent bd67a2a commit c7e847c
Show file tree
Hide file tree
Showing 14 changed files with 458 additions and 394 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,5 @@ build-root/*.tar.xz
build-root/*.rpm
build-root/rpmbuild

test/public
test/site.sh
doc/html
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@
* <!DOCTYPE (ie DTD) is not supported.
### Corrected Bugs
* Keyword "min" (not only "max") can be used in built-in types "range" and "length" statements.
* Support for empty yang string added, eg `default "";`
* Removed CLI generation for yang notifications (and other non-data yang nodes)
* Some restconf error messages contained "rpc-reply" or "rpc-error" which have now been removed.
Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,8 @@ However, the following YANG syntax modules are not implemented:
- belongs-to

Restrictions on Yang types are as follows:
- The range statement does not support multiple values (RFC7950 9.2.4)
- The range statement for built-in integers does not support multiple values (RFC7950 9.2.4)
- The length statement for built-in strings does not support multiple values (RFC7950 9.4.4)
- Submodules cannot re-use a prefix in an import statement that is already used for another imported module in the module that the submodule belongs to. (see https://github.com/clicon/clixon/issues/60)
- default values on leaf-lists (RFC7950 7.7.2)

Expand Down
95 changes: 28 additions & 67 deletions apps/cli/cli_generate.c
Original file line number Diff line number Diff line change
Expand Up @@ -169,28 +169,6 @@ static int yang2cli_stmt(clicon_handle h, yang_stmt *ys, cbuf *cb,
static int yang2cli_var_union(clicon_handle h, yang_stmt *ys, char *origtype,
yang_stmt *ytype, cbuf *cb, char *helptext);

/*! Patched maxstring to account for DEC64 types
* @note kludge to fix overflow error -> Fix the original error in cvtype_max2str
* by adding a fraction_digits argument.
*/
static char *
cvtype_max2str_dup2(enum cv_type type,
int fraction_digits)
{
int len;
char *str;

if (type!=CGV_DEC64 || fraction_digits==0)
return cvtype_max2str_dup(type);
if ((len = cvtype_max2str(type, NULL, 0)) < 0)
return NULL;
if ((str = (char *)malloc(len+1)) == NULL)
return NULL;
memset(str, '\0', len+1);
len = snprintf(str, len+1, "%" PRId64 ".0", (INT64_MAX/((int)pow(10,fraction_digits))));
return str;
}

/*! Generate CLI code for Yang leaf statement to CLIgen variable of specific type
* Check for completion (of already existent values), ranges (eg range[min:max]) and
* patterns, (eg regexp:"[0.9]*").
Expand All @@ -208,18 +186,17 @@ yang2cli_var_sub(clicon_handle h,
char *helptext,
enum cv_type cvtype,
int options,
cg_var *mincv,
cg_var *maxcv,
cvec *cvv,
char *pattern,
uint8_t fraction_digits
)
{
int retval = -1;
char *type;
char *r;
yang_stmt *yi = NULL;
int i = 0;
char *cvtypestr;
cg_var *cv;

if (cvtype == CGV_VOID){
retval = 0;
Expand Down Expand Up @@ -276,44 +253,30 @@ yang2cli_var_sub(clicon_handle h,

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

if (options & (YANG_OPTIONS_RANGE|YANG_OPTIONS_LENGTH)){
assert(mincv || maxcv);
cprintf(cb, " %s[", (options&YANG_OPTIONS_RANGE)?"range":"length");
if (mincv){
if ((r = cv2str_dup(mincv)) == NULL){
clicon_err(OE_UNIX, errno, "cv2str_dup");
goto done;
}
cprintf(cb, "%s:", r);
free(r);
r = NULL;
}
if (maxcv != NULL){
if ((r = cv2str_dup(maxcv)) == NULL){
clicon_err(OE_UNIX, errno, "cv2str_dup");
goto done;
}
}
else{ /* Cligen does not have 'max' keyword in range so need to find actual
max value of type if yang range expression is 0..max
*/
if (cvtype==CGV_STRING){
if ((r = malloc(512)) == NULL){
clicon_err(OE_UNIX, errno, "malloc");
goto done;
}
snprintf(r, 512, "%d", MAXPATHLEN);
}
else {
if ((r = cvtype_max2str_dup2(cvtype, fraction_digits)) == NULL){
clicon_err(OE_UNIX, errno, "cvtype_max2str");
goto done;
/* 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,"]");
}
}
cprintf(cb, "%s]", r); /* range */
free(r);
r = NULL;
}
if (options & YANG_OPTIONS_PATTERN)
cprintf(cb, " regexp:\"%s\"", pattern);
Expand Down Expand Up @@ -347,8 +310,7 @@ yang2cli_var_union_one(clicon_handle h,
{
int retval = -1;
int options = 0;
cg_var *mincv = NULL;
cg_var *maxcv = NULL;
cvec *cvv = NULL;
char *pattern = NULL;
uint8_t fraction_digits = 0;
enum cv_type cvtype;
Expand All @@ -358,7 +320,7 @@ yang2cli_var_union_one(clicon_handle h,
/* Resolve the sub-union type to a resolved type */
if (yang_type_resolve(ys, ytsub, /* in */
&ytype, &options, /* resolved type */
&mincv, &maxcv, &pattern, &fraction_digits) < 0)
&cvv, &pattern, &fraction_digits) < 0)
goto done;
restype = ytype?ytype->ys_argument:NULL;

Expand All @@ -370,7 +332,7 @@ yang2cli_var_union_one(clicon_handle h,
if (clicon_type2cv(origtype, restype, &cvtype) < 0)
goto done;
if ((retval = yang2cli_var_sub(h, ys, ytype, cb, helptext, cvtype,
options, mincv, maxcv, pattern, fraction_digits)) < 0)
options, cvv, pattern, fraction_digits)) < 0)
goto done;
}
retval = 0;
Expand Down Expand Up @@ -438,8 +400,7 @@ yang2cli_var(clicon_handle h,
char *origtype;
yang_stmt *yrestype; /* resolved type */
char *restype; /* resolved type */
cg_var *mincv = NULL;
cg_var *maxcv = NULL;
cvec *cvv = NULL;
char *pattern = NULL;
uint8_t fraction_digits = 0;
enum cv_type cvtype;
Expand All @@ -448,7 +409,7 @@ yang2cli_var(clicon_handle h,
char *type;

if (yang_type_get(ys, &origtype, &yrestype,
&options, &mincv, &maxcv, &pattern, &fraction_digits) < 0)
&options, &cvv, &pattern, &fraction_digits) < 0)
goto done;
restype = yrestype?yrestype->ys_argument:NULL;

Expand Down Expand Up @@ -485,7 +446,7 @@ yang2cli_var(clicon_handle h,
if (completionp)
cprintf(cb, "(");
if ((retval = yang2cli_var_sub(h, ys, yrestype, cb, helptext, cvtype,
options, mincv, maxcv, pattern, fraction_digits)) < 0)
options, cvv, pattern, fraction_digits)) < 0)
goto done;
if (completionp){
if (cli_expand_var_generate(h, ys, cvtype, cb,
Expand Down
1 change: 1 addition & 0 deletions lib/clixon/clixon_string.h
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ int uri_percent_decode(char *enc, char **str);
const char *clicon_int2str(const map_str2int *mstab, int i);
int clicon_str2int(const map_str2int *mstab, char *str);
int nodeid_split(char *nodeid, char **prefix, char **id);
char *clixon_trim(char *str);
#ifndef HAVE_STRNDUP
char *clicon_strndup (const char *, size_t);
#endif /* ! HAVE_STRNDUP */
Expand Down
3 changes: 1 addition & 2 deletions lib/clixon/clixon_yang.h
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,7 @@ typedef struct yang_stmt yang_stmt; /* forward */
*/
struct yang_type_cache{
int yc_options;
cg_var *yc_mincv;
cg_var *yc_maxcv;
cvec *yc_cvv; /* range and length restriction */
char *yc_pattern;
uint8_t yc_fraction;
yang_stmt *yc_resolved; /* Resolved type object, can be NULL - note direct ptr */
Expand Down
19 changes: 9 additions & 10 deletions lib/clixon/clixon_yang_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,11 @@
* Prototypes
*/
int yang_type_cache_set(yang_type_cache **ycache,
yang_stmt *resolved, int options, cg_var *mincv,
cg_var *maxcv, char *pattern, uint8_t fraction);
int yang_type_cache_get(yang_type_cache *ycache,
yang_stmt **resolved, int *options, cg_var **mincv,
cg_var **maxcv, char **pattern, uint8_t *fraction);
yang_stmt *resolved, int options,
cvec *cvv, char *pattern, uint8_t fraction);
int yang_type_cache_get(yang_type_cache *ycache, yang_stmt **resolved,
int *options, cvec **cvv, char **pattern,
uint8_t *fraction);
int yang_type_cache_cp(yang_type_cache **ycnew, yang_type_cache *ycold);
int yang_type_cache_free(yang_type_cache *ycache);
int ys_resolve_type(yang_stmt *ys, void *arg);
Expand All @@ -69,12 +69,11 @@ yang_stmt *yang_find_identity(yang_stmt *ys, char *identity);
int ys_cv_validate(cg_var *cv, yang_stmt *ys, char **reason);
int clicon_type2cv(char *type, char *rtype, enum cv_type *cvtype);
int yang_type_get(yang_stmt *ys, char **otype, yang_stmt **restype,
int *options, cg_var **mincv, cg_var **maxcv, char **pattern,
int *options, cvec **cvv, char **pattern,
uint8_t *fraction_digits);
int yang_type_resolve(yang_stmt *ys, yang_stmt *ytype,
yang_stmt **restype, int *options,
cg_var **mincv, cg_var **maxcv,
char **pattern, uint8_t *fraction);
int yang_type_resolve(yang_stmt *ys, yang_stmt *ytype,
yang_stmt **restype, int *options,
cvec **cvv, char **pattern, uint8_t *fraction);


#endif /* _CLIXON_YANG_TYPE_H_ */
42 changes: 33 additions & 9 deletions lib/src/clixon_string.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,14 +57,15 @@
/*! Split string into a vector based on character delimiters. Using malloc
*
* The given string is split into a vector where the delimiter can be
* any of the characters in the specified delimiter string.
* _any_ of the characters in the specified delimiter string.
*
* The vector returned is one single memory block that must be freed
* by the caller
*
* @code
* char **vec = NULL;
* int nvec;
* char **vec = NULL;
* char *v;
* int nvec;
* if ((vec = clicon_strsep("/home/user/src/clixon", "/", &nvec)) == NULL)
* err;
* for (i=0; i<nvec; i++){
Expand Down Expand Up @@ -437,15 +438,18 @@ xml_chardata_encode(char **escp,
/*! Split a string into a cligen variable vector using 1st and 2nd delimiter
* Split a string first into elements delimited by delim1, then into
* pairs delimited by delim2.
* @param[in] string String to split
* @param[in] delim1 First delimiter char that delimits between elements
* @param[in] delim2 Second delimiter char for pairs within an element
* @param[in] string String to split
* @param[in] delim1 First delimiter char that delimits between elements
* @param[in] delim2 Second delimiter char for pairs within an element
* @param[out] cvp Created cligen variable vector, deallocate w cvec_free
* @retval 0 on OK
* @retval 0 OK
* @retval -1 error
* @code
* cvec *cvv = NULL;
* if (str2cvec("a=b&c=d", ';', '=', &cvv) < 0)
* err;
* @endcode
*
* @example,
* Assuming delim1 = '&' and delim2 = '='
* a=b&c=d -> [[a,"b"][c="d"]
* kalle&c=d -> [[c="d"]] # Discard elements with no delim2
* XXX differentiate between error and null cvec.
Expand Down Expand Up @@ -610,6 +614,26 @@ nodeid_split(char *nodeid,
return retval;
}

/*! Trim blanks from front and end of a string, return new string
* @param[in] str
* @retval s Pointer into existing str after trimming blanks
*/
char *
clixon_trim(char *str)
{
char *s = str;
int i;

while (strlen(s) && isblank(s[0]))
s++;
for (i=0; i<strlen(s); i++)
if (isblank(s[i])){
s[i] = '\0';
break;
}
return s;
}

/*! strndup() for systems without it, such as xBSD
*/
#ifndef HAVE_STRNDUP
Expand Down
2 changes: 1 addition & 1 deletion lib/src/clixon_xml_map.c
Original file line number Diff line number Diff line change
Expand Up @@ -2414,7 +2414,7 @@ yang_enum_int_value(cxobj *node,
if ((ytype = yang_find((yang_node *)ys, Y_TYPE, NULL)) == NULL)
goto done;
if (yang_type_resolve(ys, ytype, &yrestype,
NULL, NULL, NULL, NULL, NULL) < 0)
NULL, NULL, NULL, NULL) < 0)
goto done;
if (yrestype==NULL || strcmp(yrestype->ys_argument, "enumeration"))
goto done;
Expand Down
Loading

0 comments on commit c7e847c

Please sign in to comment.