This commit is contained in:
Olof Hagsand 2019-05-22 18:28:07 +00:00
commit 69f2eb30f1
7 changed files with 723 additions and 31 deletions

View file

@ -140,8 +140,11 @@
### Minor changes ### Minor changes
* Regexp improvements * Regexp improvements
* Added check for libxml in configure'; * Better compliance with XSD regexps (when transforming to Posix regexps)
* Added `\p{L}` and `\p{N}`
* Added escaping of `$`
* Added clixon_util_regexp utility function * Added clixon_util_regexp utility function
* Added regexp [test/test_pattern.sh]
* Yang state get improvements * Yang state get improvements
* Integrated state and config into same tree on retrieval, not separate trees * Integrated state and config into same tree on retrieval, not separate trees
* Added cli functions `cli_show_config_state()` and `cli_show_auto_state()` for showing combined config and state info. * Added cli functions `cli_show_config_state()` and `cli_show_auto_state()` for showing combined config and state info.

View file

@ -709,6 +709,11 @@ clixon_trim(char *str)
* "other" characters: #x0000-#x10FFFF]-[\p{P}\p{Z}\p{C}] * "other" characters: #x0000-#x10FFFF]-[\p{P}\p{Z}\p{C}]
* \i letters + underscore and colon * \i letters + underscore and colon
* \c XML Namechar, see: https://www.w3.org/TR/2008/REC-xml-20081126/#NT-NameChar * \c XML Namechar, see: https://www.w3.org/TR/2008/REC-xml-20081126/#NT-NameChar
*
* Not implemented:
* \p{X} category escape. the ones identified in openconfig and yang-models are:
* \p{L} Letters [ultmo]?
* \p{N} Numbers [dlo]?
*/ */
int int
regexp_xsd2posix(char *xsd, regexp_xsd2posix(char *xsd,
@ -718,6 +723,7 @@ regexp_xsd2posix(char *xsd,
cbuf *cb = NULL; cbuf *cb = NULL;
char x; char x;
int i; int i;
int j; /* lookahead */
int esc; int esc;
int minus = 0; int minus = 0;
@ -743,12 +749,24 @@ regexp_xsd2posix(char *xsd,
case 'i': /* initial */ case 'i': /* initial */
cprintf(cb, "[a-zA-Z_:]"); cprintf(cb, "[a-zA-Z_:]");
break; break;
case 'w': /* word */ case 'p': /* category escape: \p{IsCategory} */
//cprintf(cb, "[0-9a-zA-Z_\\\\-]") j = i+1;
cprintf(cb, "[^[:punct:][:space:][:cntrl:]]"); if (j+2 < strlen(xsd) &&
break; xsd[j] == '{' &&
case 'W': /* inverse of \w */ xsd[j+2] == '}'){
cprintf(cb, "[[:punct:][:space:][:cntrl:]]"); switch (xsd[j+1]){
case 'L': /* Letters */
cprintf(cb, "a-zA-Z"); /* assume in [] */
break;
case 'N': /* Numbers */
cprintf(cb, "0-9");
break;
default:
break;
}
i = j+2;
}
/* if syntax error, just leave it */
break; break;
case 's': case 's':
cprintf(cb, "[ \t\r\n]"); cprintf(cb, "[ \t\r\n]");
@ -756,6 +774,13 @@ regexp_xsd2posix(char *xsd,
case 'S': case 'S':
cprintf(cb, "[^ \t\r\n]"); cprintf(cb, "[^ \t\r\n]");
break; break;
case 'w': /* word */
//cprintf(cb, "[0-9a-zA-Z_\\\\-]")
cprintf(cb, "[^[:punct:][:space:][:cntrl:]]");
break;
case 'W': /* inverse of \w */
cprintf(cb, "[[:punct:][:space:][:cntrl:]]");
break;
default: default:
cprintf(cb, "\\%c", x); cprintf(cb, "\\%c", x);
break; break;
@ -763,6 +788,8 @@ regexp_xsd2posix(char *xsd,
} }
else if (x == '\\') else if (x == '\\')
esc++; esc++;
else if (x == '$')
cprintf(cb, "\\%c", x);
else if (x == ']' && minus){ else if (x == ']' && minus){
cprintf(cb, "-]"); cprintf(cb, "-]");
minus = 0; minus = 0;

View file

@ -96,7 +96,7 @@ identifier [A-Za-z_][A-Za-z0-9_\-\.]*
%s STRING %s STRING
%s STRINGDQ %s STRINGDQ
%s STRINGSQ %s STRINGSQ
%s ESCAPE %s DQESC
%s COMMENT1 %s COMMENT1
%s COMMENT2 %s COMMENT2
%s UNKNOWN %s UNKNOWN
@ -228,7 +228,7 @@ identifier [A-Za-z_][A-Za-z0-9_\-\.]*
<STRING>. { clixon_yang_parselval.string = strdup(yytext); <STRING>. { clixon_yang_parselval.string = strdup(yytext);
return CHARS;} return CHARS;}
<STRINGDQ>\\ { _YY->yy_lex_state = STRINGDQ; BEGIN(ESCAPE); } <STRINGDQ>\\ { _YY->yy_lex_state = STRINGDQ; BEGIN(DQESC); }
<STRINGDQ>\" { BEGIN(_YY->yy_lex_string_state); return *yytext; } <STRINGDQ>\" { BEGIN(_YY->yy_lex_string_state); return *yytext; }
<STRINGDQ>\n { _YY->yy_linenum++; <STRINGDQ>\n { _YY->yy_linenum++;
clixon_yang_parselval.string = strdup(yytext); clixon_yang_parselval.string = strdup(yytext);
@ -243,7 +243,7 @@ identifier [A-Za-z_][A-Za-z0-9_\-\.]*
<STRINGSQ>[^'\n]+ { clixon_yang_parselval.string = strdup(yytext); <STRINGSQ>[^'\n]+ { clixon_yang_parselval.string = strdup(yytext);
return CHARS;} return CHARS;}
<ESCAPE>. { BEGIN(_YY->yy_lex_state); <DQESC>[nt"\\] { BEGIN(_YY->yy_lex_state);
clixon_yang_parselval.string = strdup(yytext); clixon_yang_parselval.string = strdup(yytext);
return CHARS; } return CHARS; }
<COMMENT1>[^*\n]* /* eat anything that's not a '*' */ <COMMENT1>[^*\n]* /* eat anything that's not a '*' */

View file

@ -31,6 +31,7 @@ if [ -f ./site.sh ]; then
# test skiplist. # test skiplist.
for f in $SKIPLIST; do for f in $SKIPLIST; do
if [ "$testfile" = "$f" ]; then if [ "$testfile" = "$f" ]; then
echo ...skipped
return -1 # skip return -1 # skip
fi fi
done done

650
test/test_pattern.sh Executable file

File diff suppressed because one or more lines are too long

View file

@ -153,7 +153,7 @@ if [ $BE -ne 0 ]; then
start_backend -s init -f $cfg -y $fyang start_backend -s init -f $cfg -y $fyang
new "waiting" new "waiting"
sleep $RCWAIT wait_backend
fi fi
new "cli defined extension" new "cli defined extension"

View file

@ -33,6 +33,7 @@
* Utility for compiling regexp and checking validity * Utility for compiling regexp and checking validity
* gcc -I /usr/include/libxml2 regex.c -o regex -lxml2 * gcc -I /usr/include/libxml2 regex.c -o regex -lxml2
* @see http://www.w3.org/TR/2004/REC-xmlschema-2-20041028
*/ */
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
#include "clixon_config.h" /* generated by config & autoconf */ #include "clixon_config.h" /* generated by config & autoconf */
@ -45,8 +46,6 @@
#include <stdlib.h> #include <stdlib.h>
#include <limits.h> #include <limits.h>
#undef HAVE_LIBXML2
#ifdef HAVE_LIBXML2 /* Actually it should check for a header file */ #ifdef HAVE_LIBXML2 /* Actually it should check for a header file */
#include <libxml/xmlregexp.h> #include <libxml/xmlregexp.h>
#endif #endif
@ -66,7 +65,9 @@
static int static int
regex_libxml2(char *regexp0, regex_libxml2(char *regexp0,
char *content0, char *content0,
int nr) int nr,
int debug)
{ {
int retval = -1; int retval = -1;
#ifdef HAVE_LIBXML2 #ifdef HAVE_LIBXML2
@ -92,7 +93,8 @@ regex_libxml2(char *regexp0,
static int static int
regex_posix(char *regexp, regex_posix(char *regexp,
char *content, char *content,
int nr) int nr,
int debug)
{ {
int retval = -1; int retval = -1;
char *posix = NULL; char *posix = NULL;
@ -105,6 +107,7 @@ regex_posix(char *regexp,
if (regexp_xsd2posix(regexp, &posix) < 0) if (regexp_xsd2posix(regexp, &posix) < 0)
goto done; goto done;
clicon_debug(1, "posix: %s", posix);
len0 = strlen(posix); len0 = strlen(posix);
if (len0 > sizeof(pattern)-5){ if (len0 > sizeof(pattern)-5){
fprintf(stderr, "pattern too long\n"); fprintf(stderr, "pattern too long\n");
@ -134,15 +137,15 @@ regex_posix(char *regexp,
static int static int
usage(char *argv0) usage(char *argv0)
{ {
fprintf(stderr, "usage:%s [options] (either one of -p or -x)\n" fprintf(stderr, "usage:%s [options]\n"
"where options are\n" "where options are\n"
"\t-h \t\tHelp\n" "\t-h \t\tHelp\n"
"\t-D <level>\tDebug\n" "\t-D <level>\tDebug\n"
"\t-p \txsd->posix translation regexp\n" "\t-p \txsd->posix translation regexp (default)\n"
"\t-x \tlibxml2 regexp\n" "\t-x \tlibxml2 regexp (alternative to -p)\n"
"\t-n <nr> \tIterate content match (0 means only compile)\n" "\t-n <nr> \tIterate content match (default: 1, 0: no match only compile)\n"
"\t-r <regexp> \tregexp (mandatory)\n" "\t-r <regexp> \tregexp (mandatory)\n"
"\t-c <string> \tValue content string(mandatory)\n", "\t-c <string> \tValue content string(mandatory if -n > 0)\n",
argv0 argv0
); );
exit(0); exit(0);
@ -157,10 +160,9 @@ main(int argc,
int c; int c;
char *regexp = NULL; char *regexp = NULL;
char *content = NULL; char *content = NULL;
int posix = 0;
int libxml2 = 0;
int ret; int ret;
int nr = 1; int nr = 1;
int mode = 0; /* 0 is posix, 1 is libxml */
optind = 1; optind = 1;
opterr = 0; opterr = 0;
@ -174,14 +176,14 @@ main(int argc,
usage(argv0); usage(argv0);
break; break;
case 'p': /* xsd->posix */ case 'p': /* xsd->posix */
posix++; mode = 0;
break; break;
case 'n': /* Number of iterations */ case 'n': /* Number of iterations */
if ((nr = atoi(optarg)) < 0) if ((nr = atoi(optarg)) < 0)
usage(argv0); usage(argv0);
break; break;
case 'x': /* libxml2 */ case 'x': /* libxml2 */
libxml2++; mode = 1;
break; break;
case 'r': /* regexp */ case 'r': /* regexp */
regexp = optarg; regexp = optarg;
@ -194,22 +196,31 @@ main(int argc,
break; break;
} }
clicon_log_init(__FILE__, debug?LOG_DEBUG:LOG_INFO, CLICON_LOG_STDERR); clicon_log_init(__FILE__, debug?LOG_DEBUG:LOG_INFO, CLICON_LOG_STDERR);
if (regexp == NULL || content == NULL) if (regexp == NULL){
fprintf(stderr, "-r mandatory\n");
usage(argv0); usage(argv0);
if (posix == libxml2) }
if (nr > 0 && content == NULL){
fprintf(stderr, "-c mandatory (if -n > 0)\n");
usage(argv0); usage(argv0);
}
if (mode != 0 && mode != 1){
fprintf(stderr, "Neither posix or libxml2 set\n");
usage(argv0);
}
clicon_debug(1, "regexp:%s", regexp); clicon_debug(1, "regexp:%s", regexp);
clicon_debug(1, "content:%s", content); clicon_debug(1, "content:%s", content);
if (libxml2){ if (mode == 0){
if ((ret = regex_libxml2(regexp, content, nr)) < 0) if ((ret = regex_posix(regexp, content, nr, debug)) < 0)
goto done; goto done;
} }
else if (posix){ else if (mode == 1){
if ((ret = regex_posix(regexp, content, nr)) < 0) if ((ret = regex_libxml2(regexp, content, nr, debug)) < 0)
goto done; goto done;
} }
else else
goto done; usage(argv0);
fprintf(stdout, "%d\n", ret); fprintf(stdout, "%d\n", ret);
exit(ret); exit(ret);
retval = 0; retval = 0;