* A yang type regex cache added, this helps the performance by avoiding re-running the regcomp command on every iteration.
* An XML namespace cache added (see `xml2ns()`) * Better performance of XML whitespace parsing/scanning.
This commit is contained in:
parent
728c97ab6d
commit
8c36083e16
8 changed files with 214 additions and 19 deletions
|
|
@ -146,7 +146,7 @@ generic_validate(yang_stmt *yspec,
|
||||||
* and call application callback validations.
|
* and call application callback validations.
|
||||||
* @param[in] h Clicon handle
|
* @param[in] h Clicon handle
|
||||||
* @param[in] db The startup database. The wanted backend state
|
* @param[in] db The startup database. The wanted backend state
|
||||||
* @param[out] xtr Transformed XML
|
* @param[in] td Transaction
|
||||||
* @param[out] cbret CLIgen buffer w error stmt if retval = 0
|
* @param[out] cbret CLIgen buffer w error stmt if retval = 0
|
||||||
* @retval -1 Error - or validation failed (but cbret not set)
|
* @retval -1 Error - or validation failed (but cbret not set)
|
||||||
* @retval 0 Validation failed (with cbret set)
|
* @retval 0 Validation failed (with cbret set)
|
||||||
|
|
@ -183,6 +183,10 @@ startup_common(clicon_handle h,
|
||||||
clicon_debug(1, "Reading startup config from %s", db);
|
clicon_debug(1, "Reading startup config from %s", db);
|
||||||
if (xmldb_get(h, db, "/", &xt, msd) < 0)
|
if (xmldb_get(h, db, "/", &xt, msd) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
if (xml_child_nr(xt) == 0){ /* If empty skip */
|
||||||
|
td->td_target = xt;
|
||||||
|
goto ok;
|
||||||
|
}
|
||||||
if (msd){
|
if (msd){
|
||||||
if ((ret = clixon_module_upgrade(h, xt, msd, cbret)) < 0)
|
if ((ret = clixon_module_upgrade(h, xt, msd, cbret)) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -225,6 +229,7 @@ startup_common(clicon_handle h,
|
||||||
/* 7. Call plugin transaction complete callbacks */
|
/* 7. Call plugin transaction complete callbacks */
|
||||||
if (plugin_transaction_complete(h, td) < 0)
|
if (plugin_transaction_complete(h, td) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
ok:
|
||||||
retval = 1;
|
retval = 1;
|
||||||
done:
|
done:
|
||||||
if (msd)
|
if (msd)
|
||||||
|
|
|
||||||
|
|
@ -114,6 +114,7 @@ db_merge(clicon_handle h,
|
||||||
|
|
||||||
/*! Clixon startup startup mode: Commit startup configuration into running state
|
/*! Clixon startup startup mode: Commit startup configuration into running state
|
||||||
* @param[in] h Clixon handle
|
* @param[in] h Clixon handle
|
||||||
|
* @param[in] db tmp or startup
|
||||||
* @param[out] cbret If status is invalid contains error message
|
* @param[out] cbret If status is invalid contains error message
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
* @retval 0 Validation failed
|
* @retval 0 Validation failed
|
||||||
|
|
@ -150,6 +151,10 @@ startup_mode_startup(clicon_handle h,
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
if (strcmp(db, "running")==0){
|
||||||
|
clicon_err(OE_FATAL, 0, "Invalid startup db: %s", db);
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
/* Load plugins and call plugin_init() */
|
/* Load plugins and call plugin_init() */
|
||||||
if (backend_plugin_initiate(h) != 0)
|
if (backend_plugin_initiate(h) != 0)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
@ -255,6 +260,8 @@ startup_extraxml(clicon_handle h,
|
||||||
goto done;
|
goto done;
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
if (xt==NULL /* || xml_child_nr(xt)==0 */ ) /* This gives SEGV in test_feature */
|
||||||
|
goto ok;
|
||||||
/* Write (potentially modified) xml tree xt back to tmp
|
/* Write (potentially modified) xml tree xt back to tmp
|
||||||
*/
|
*/
|
||||||
if ((ret = xmldb_put(h, "tmp", OP_REPLACE, xt,
|
if ((ret = xmldb_put(h, "tmp", OP_REPLACE, xt,
|
||||||
|
|
@ -265,6 +272,7 @@ startup_extraxml(clicon_handle h,
|
||||||
goto fail;
|
goto fail;
|
||||||
if (ret == 0)
|
if (ret == 0)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
ok:
|
||||||
retval = 1;
|
retval = 1;
|
||||||
done:
|
done:
|
||||||
if (xt)
|
if (xt)
|
||||||
|
|
|
||||||
|
|
@ -218,7 +218,9 @@ struct yang_stmt{
|
||||||
Y_TYPE & identity: store all derived types
|
Y_TYPE & identity: store all derived types
|
||||||
*/
|
*/
|
||||||
yang_type_cache *ys_typecache; /* If ys_keyword==Y_TYPE, cache all typedef data except unions */
|
yang_type_cache *ys_typecache; /* If ys_keyword==Y_TYPE, cache all typedef data except unions */
|
||||||
|
void *ys_regex_cache; /* regex cache */
|
||||||
int _ys_vector_i; /* internal use: yn_each */
|
int _ys_vector_i; /* internal use: yn_each */
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef int (yang_applyfn_t)(yang_stmt *ys, void *arg);
|
typedef int (yang_applyfn_t)(yang_stmt *ys, void *arg);
|
||||||
|
|
@ -232,6 +234,8 @@ enum rfc_6020 yang_keyword_get(yang_stmt *ys);
|
||||||
char *yang_argument_get(yang_stmt *ys);
|
char *yang_argument_get(yang_stmt *ys);
|
||||||
cg_var *yang_cv_get(yang_stmt *ys);
|
cg_var *yang_cv_get(yang_stmt *ys);
|
||||||
cvec *yang_cvec_get(yang_stmt *ys);
|
cvec *yang_cvec_get(yang_stmt *ys);
|
||||||
|
void *yang_regex_cache_get(yang_stmt *ys);
|
||||||
|
int yang_regex_cache_set(yang_stmt *ys, void *regex);
|
||||||
|
|
||||||
/* Other functions */
|
/* Other functions */
|
||||||
yang_stmt *yspec_new(void);
|
yang_stmt *yspec_new(void);
|
||||||
|
|
|
||||||
|
|
@ -127,6 +127,7 @@ struct xml{
|
||||||
reference, dont free */
|
reference, dont free */
|
||||||
cg_var *x_cv; /* Cached value as cligen variable
|
cg_var *x_cv; /* Cached value as cligen variable
|
||||||
(eg xml_cmp) */
|
(eg xml_cmp) */
|
||||||
|
char *x_ns_cache; /* Cached namespace */
|
||||||
int _x_vector_i; /* internal use: xml_child_each */
|
int _x_vector_i; /* internal use: xml_child_each */
|
||||||
int _x_i; /* internal use for sorting:
|
int _x_i; /* internal use for sorting:
|
||||||
see xml_enumerate and xml_cmp */
|
see xml_enumerate and xml_cmp */
|
||||||
|
|
@ -234,6 +235,7 @@ xml_prefix_set(cxobj *xn,
|
||||||
* @retval 0 OK
|
* @retval 0 OK
|
||||||
* @retval -1 Error
|
* @retval -1 Error
|
||||||
* @see xmlns_check XXX can these be merged?
|
* @see xmlns_check XXX can these be merged?
|
||||||
|
* @note, this function uses a cache. Any case where cache should be cleared?
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
xml2ns(cxobj *x,
|
xml2ns(cxobj *x,
|
||||||
|
|
@ -241,9 +243,11 @@ xml2ns(cxobj *x,
|
||||||
char **namespace)
|
char **namespace)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
char *ns;
|
char *ns = NULL;
|
||||||
cxobj *xp;
|
cxobj *xp;
|
||||||
|
|
||||||
|
if ((ns = x->x_ns_cache) != NULL)
|
||||||
|
goto ok;
|
||||||
if (prefix != NULL) /* xmlns:<prefix>="<uri>" */
|
if (prefix != NULL) /* xmlns:<prefix>="<uri>" */
|
||||||
ns = xml_find_type_value(x, "xmlns", prefix, CX_ATTR);
|
ns = xml_find_type_value(x, "xmlns", prefix, CX_ATTR);
|
||||||
else /* xmlns="<uri>" */
|
else /* xmlns="<uri>" */
|
||||||
|
|
@ -261,6 +265,11 @@ xml2ns(cxobj *x,
|
||||||
ns = DEFAULT_XML_RPC_NAMESPACE;
|
ns = DEFAULT_XML_RPC_NAMESPACE;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
if (ns && (x->x_ns_cache = strdup(ns)) == NULL){
|
||||||
|
clicon_err(OE_XML, errno, "strdup");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
ok:
|
||||||
if (namespace)
|
if (namespace)
|
||||||
*namespace = ns;
|
*namespace = ns;
|
||||||
retval = 0;
|
retval = 0;
|
||||||
|
|
@ -1359,6 +1368,8 @@ xml_free(cxobj *x)
|
||||||
free(x->x_childvec);
|
free(x->x_childvec);
|
||||||
if (x->x_cv)
|
if (x->x_cv)
|
||||||
cv_free(x->x_cv);
|
cv_free(x->x_cv);
|
||||||
|
if (x->x_ns_cache)
|
||||||
|
free(x->x_ns_cache);
|
||||||
free(x);
|
free(x);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -132,10 +132,10 @@ ncname {namestart}{namechar}*
|
||||||
<STATEA>"<?" { BEGIN(PIDECL); return BQMARK; }
|
<STATEA>"<?" { BEGIN(PIDECL); return BQMARK; }
|
||||||
<STATEA>\< { BEGIN(START); return *clixon_xml_parsetext; }
|
<STATEA>\< { BEGIN(START); return *clixon_xml_parsetext; }
|
||||||
<STATEA>& { _YA->ya_lex_state =STATEA;BEGIN(AMPERSAND);}
|
<STATEA>& { _YA->ya_lex_state =STATEA;BEGIN(AMPERSAND);}
|
||||||
<STATEA>[ \t] { clixon_xml_parselval.string = yytext;return WHITESPACE; }
|
<STATEA>[ \t]+ { clixon_xml_parselval.string = yytext;return WHITESPACE; }
|
||||||
<STATEA>\r\n { clixon_xml_parselval.string = "\n";return WHITESPACE; }
|
<STATEA>\r\n { clixon_xml_parselval.string = "\n"; _YA->ya_linenum++; return WHITESPACE; }
|
||||||
<STATEA>\r { clixon_xml_parselval.string = "\n";return WHITESPACE; }
|
<STATEA>\r { clixon_xml_parselval.string = "\n";return WHITESPACE; }
|
||||||
<STATEA>\n { clixon_xml_parselval.string = yytext; _YA->ya_linenum++;return WHITESPACE; }
|
<STATEA>\n { clixon_xml_parselval.string = "\n"; _YA->ya_linenum++;return WHITESPACE; }
|
||||||
<STATEA>. { clixon_xml_parselval.string = yytext; return CHARDATA; }
|
<STATEA>. { clixon_xml_parselval.string = yytext; return CHARDATA; }
|
||||||
|
|
||||||
/* @see xml_chardata_encode */
|
/* @see xml_chardata_encode */
|
||||||
|
|
|
||||||
|
|
@ -112,6 +112,44 @@ xml_parse_content(struct xml_parse_yacc_arg *ya,
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*! Add whitespace
|
||||||
|
* If text, ie only body, keep as is.
|
||||||
|
* But if there is an element, then skip all whitespace.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
xml_parse_whitespace(struct xml_parse_yacc_arg *ya,
|
||||||
|
char *str)
|
||||||
|
{
|
||||||
|
cxobj *xn = ya->ya_xelement;
|
||||||
|
cxobj *xp = ya->ya_xparent;
|
||||||
|
int retval = -1;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
ya->ya_xelement = NULL; /* init */
|
||||||
|
/* If there is an element already, only add one whitespace child
|
||||||
|
* otherwise, keep all whitespace.
|
||||||
|
*/
|
||||||
|
#if 1
|
||||||
|
for (i=0; i<xml_child_nr(xp); i++){
|
||||||
|
if (xml_type(xml_child_i(xp, i)) == CX_ELMNT)
|
||||||
|
goto ok; /* Skip if already element */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (xn == NULL){
|
||||||
|
if ((xn = xml_new("body", xp, NULL)) == NULL)
|
||||||
|
goto done;
|
||||||
|
xml_type_set(xn, CX_BODY);
|
||||||
|
}
|
||||||
|
if (xml_value_append(xn, str)==NULL)
|
||||||
|
goto done;
|
||||||
|
ya->ya_xelement = xn;
|
||||||
|
ok:
|
||||||
|
retval = 0;
|
||||||
|
done:
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int
|
static int
|
||||||
xml_parse_version(struct xml_parse_yacc_arg *ya,
|
xml_parse_version(struct xml_parse_yacc_arg *ya,
|
||||||
char *ver)
|
char *ver)
|
||||||
|
|
@ -243,10 +281,16 @@ xml_parse_bslash1(struct xml_parse_yacc_arg *ya,
|
||||||
while ((xc = xml_child_each(x, xc, CX_ELMNT)) != NULL)
|
while ((xc = xml_child_each(x, xc, CX_ELMNT)) != NULL)
|
||||||
break;
|
break;
|
||||||
if (xc != NULL){ /* at least one element */
|
if (xc != NULL){ /* at least one element */
|
||||||
xc = NULL;
|
int i;
|
||||||
while ((xc = xml_child_each(x, xc, CX_BODY)) != NULL) {
|
for (i=0; i<xml_child_nr(x);){
|
||||||
xml_purge(xc);
|
xc = xml_child_i(x, i);
|
||||||
xc = NULL; /* reset iterator */
|
if (xml_type(xc) != CX_BODY){
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (xml_child_rm(x, i) < 0)
|
||||||
|
goto done;
|
||||||
|
xml_free(xc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -425,7 +469,7 @@ content : element { clicon_debug(2, "content -> element"); }
|
||||||
| pi { clicon_debug(2, "content -> pi"); }
|
| pi { clicon_debug(2, "content -> pi"); }
|
||||||
| CHARDATA { if (xml_parse_content(_YA, $1) < 0) YYABORT;
|
| CHARDATA { if (xml_parse_content(_YA, $1) < 0) YYABORT;
|
||||||
clicon_debug(2, "content -> CHARDATA %s", $1); }
|
clicon_debug(2, "content -> CHARDATA %s", $1); }
|
||||||
| WHITESPACE { if (xml_parse_content(_YA, $1) < 0) YYABORT;
|
| WHITESPACE { if (xml_parse_whitespace(_YA, $1) < 0) YYABORT;
|
||||||
clicon_debug(2, "content -> WHITESPACE %s", $1); }
|
clicon_debug(2, "content -> WHITESPACE %s", $1); }
|
||||||
| { clicon_debug(2, "content -> "); }
|
| { clicon_debug(2, "content -> "); }
|
||||||
;
|
;
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,7 @@
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
|
#include <regex.h>
|
||||||
|
|
||||||
/* cligen */
|
/* cligen */
|
||||||
#include <cligen/cligen.h>
|
#include <cligen/cligen.h>
|
||||||
|
|
@ -222,6 +223,20 @@ yang_cvec_get(yang_stmt *ys)
|
||||||
return ys->ys_cvec;
|
return ys->ys_cvec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void*
|
||||||
|
yang_regex_cache_get(yang_stmt *ys)
|
||||||
|
{
|
||||||
|
return ys->ys_regex_cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
yang_regex_cache_set(yang_stmt *ys,
|
||||||
|
void *regex)
|
||||||
|
{
|
||||||
|
ys->ys_regex_cache = regex;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* End access functions */
|
/* End access functions */
|
||||||
|
|
||||||
/*! Create new yang specification
|
/*! Create new yang specification
|
||||||
|
|
@ -266,6 +281,17 @@ ys_new(enum rfc_6020 keyw)
|
||||||
return ys;
|
return ys;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
yang_regex_cache_free(yang_stmt *ys)
|
||||||
|
{
|
||||||
|
if (ys->ys_regex_cache){
|
||||||
|
regfree(ys->ys_regex_cache);
|
||||||
|
free(ys->ys_regex_cache);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/*! Free a single yang statement */
|
/*! Free a single yang statement */
|
||||||
static int
|
static int
|
||||||
ys_free1(yang_stmt *ys)
|
ys_free1(yang_stmt *ys)
|
||||||
|
|
@ -280,6 +306,7 @@ ys_free1(yang_stmt *ys)
|
||||||
cvec_free(ys->ys_cvec);
|
cvec_free(ys->ys_cvec);
|
||||||
if (ys->ys_typecache)
|
if (ys->ys_typecache)
|
||||||
yang_type_cache_free(ys->ys_typecache);
|
yang_type_cache_free(ys->ys_typecache);
|
||||||
|
yang_regex_cache_free(ys);
|
||||||
free(ys);
|
free(ys);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -49,6 +49,7 @@
|
||||||
#include <regex.h>
|
#include <regex.h>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <regex.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
|
|
||||||
/* cligen */
|
/* cligen */
|
||||||
|
|
@ -99,6 +100,74 @@ static const map_str2int ytmap[] = {
|
||||||
{NULL, -1}
|
{NULL, -1}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*! Regular expression compiling
|
||||||
|
* @retval -1 Error
|
||||||
|
* @retval 0 regex problem (no match?)
|
||||||
|
* @retval 1 OK Match
|
||||||
|
* @see match_regexp the CLIgen original composite function
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
regex_compile(char *pattern0,
|
||||||
|
regex_t *re)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
char pattern[1024];
|
||||||
|
// char errbuf[1024];
|
||||||
|
int len0;
|
||||||
|
int status;
|
||||||
|
|
||||||
|
len0 = strlen(pattern0);
|
||||||
|
if (len0 > sizeof(pattern)-5){
|
||||||
|
clicon_err(OE_XML, EINVAL, "pattern too long");
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
strncpy(pattern, "^(", 2);
|
||||||
|
strncpy(pattern+2, pattern0, sizeof(pattern)-2);
|
||||||
|
strncat(pattern, ")$", sizeof(pattern)-len0-1);
|
||||||
|
if ((status = regcomp(re, pattern, REG_NOSUB|REG_EXTENDED)) != 0) {
|
||||||
|
#if 0 /* ignore error msg for now */
|
||||||
|
regerror(status, re, errbuf, sizeof(errbuf));
|
||||||
|
#endif
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
retval = 1;
|
||||||
|
done:
|
||||||
|
return retval;
|
||||||
|
fail:
|
||||||
|
retval = 0;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*! Regular expression execution
|
||||||
|
* @retval -1 Error
|
||||||
|
* @retval 0 regex problem (no match?)
|
||||||
|
* @retval 1 OK Match
|
||||||
|
* @see match_regexp the CLIgen original composite function
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
regex_exec(regex_t *re,
|
||||||
|
char *string)
|
||||||
|
{
|
||||||
|
int retval = -1;
|
||||||
|
int status;
|
||||||
|
// char errbuf[1024];
|
||||||
|
|
||||||
|
status = regexec(re, string, (size_t) 0, NULL, 0);
|
||||||
|
if (status != 0) {
|
||||||
|
#if 0 /* ignore error msg for now */
|
||||||
|
regerror(status, re, errbuf, sizeof(errbuf));
|
||||||
|
#endif
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
retval = 1;
|
||||||
|
done:
|
||||||
|
return retval;
|
||||||
|
fail:
|
||||||
|
retval = 0;
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* return 1 if built-in, 0 if not */
|
/* return 1 if built-in, 0 if not */
|
||||||
static int
|
static int
|
||||||
yang_builtin(char *type)
|
yang_builtin(char *type)
|
||||||
|
|
@ -525,14 +594,41 @@ cv_validate1(cg_var *cv,
|
||||||
}
|
}
|
||||||
if ((options & YANG_OPTIONS_PATTERN) != 0){
|
if ((options & YANG_OPTIONS_PATTERN) != 0){
|
||||||
char *posix = NULL;
|
char *posix = NULL;
|
||||||
|
regex_t *re = NULL;
|
||||||
|
|
||||||
|
if ((re = yang_regex_cache_get(yrestype)) == NULL){
|
||||||
|
/* Transform to posix regex */
|
||||||
if (regexp_xsd2posix(pattern, &posix) < 0)
|
if (regexp_xsd2posix(pattern, &posix) < 0)
|
||||||
goto done;
|
goto done;
|
||||||
if ((retval2 = match_regexp(str?str:"", posix)) < 0){
|
/* Create regex cache */
|
||||||
clicon_err(OE_DB, 0, "match_regexp: %s", pattern);
|
if ((re = malloc(sizeof(*re))) == NULL){
|
||||||
return -1;
|
clicon_err(OE_UNIX, errno, "malloc");
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
|
memset(re, 0, sizeof(*re));
|
||||||
|
/* Compute regex pattern for use in patterns */
|
||||||
|
if ((retval2 = regex_compile(posix, re)) < 0)
|
||||||
|
goto done;
|
||||||
|
if (retval2 == 0){
|
||||||
|
if (reason)
|
||||||
|
*reason = cligen_reason("regexp match fail: \"%s\" does not match %s",
|
||||||
|
str, pattern);
|
||||||
|
goto fail;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
yang_regex_cache_set(yrestype, re);
|
||||||
if (posix)
|
if (posix)
|
||||||
free(posix);
|
free(posix);
|
||||||
|
}
|
||||||
|
if ((retval2 = regex_exec(re, str?str:"")) < 0)
|
||||||
|
goto done;
|
||||||
|
if (retval2 == 0){
|
||||||
|
if (reason)
|
||||||
|
*reason = cligen_reason("regexp match fail: \"%s\" does not match %s",
|
||||||
|
str, pattern);
|
||||||
|
goto fail;
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (retval2 == 0){
|
if (retval2 == 0){
|
||||||
if (reason)
|
if (reason)
|
||||||
*reason = cligen_reason("regexp match fail: \"%s\" does not match %s",
|
*reason = cligen_reason("regexp match fail: \"%s\" does not match %s",
|
||||||
|
|
@ -667,7 +763,7 @@ ys_cv_validate_union(yang_stmt *ys,
|
||||||
/*! Validate cligen variable cv using yang statement as spec
|
/*! Validate cligen variable cv using yang statement as spec
|
||||||
*
|
*
|
||||||
* @param[in] cv A cligen variable to validate. This is a correctly parsed cv.
|
* @param[in] cv A cligen variable to validate. This is a correctly parsed cv.
|
||||||
* @param[in] ys A yang statement, must be leaf of leaf-list.
|
* @param[in] ys A yang statement, must be leaf or leaf-list.
|
||||||
* @param[out] reason If given, and if return value is 0, contains a malloced string
|
* @param[out] reason If given, and if return value is 0, contains a malloced string
|
||||||
* describing the reason why the validation failed. Must be freed.
|
* describing the reason why the validation failed. Must be freed.
|
||||||
* @retval -1 Error (fatal), with errno set to indicate error
|
* @retval -1 Error (fatal), with errno set to indicate error
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue