diff --git a/apps/backend/backend_main.c b/apps/backend/backend_main.c index 85ef14c3..dae76e94 100644 --- a/apps/backend/backend_main.c +++ b/apps/backend/backend_main.c @@ -498,7 +498,7 @@ main(int argc, usage(h, argv[0]); #ifndef HAVE_LIBXML2 - if (strcmp(clicon_yang_regexp(h), "libxml2")==0){ + if (clicon_yang_regexp(h) == REGEXP_LIBXML2){ clicon_err(OE_FATAL, 0, "CLICON_YANG_REGEXP set to libxml2, but HAVE_LIBXML2 not set (Either change CLICON_YANG_REGEXP to posix, or run: configure --with-libxml2))"); goto done; } diff --git a/apps/cli/cli_generate.c b/apps/cli/cli_generate.c index 69b360ae..c5d26013 100644 --- a/apps/cli/cli_generate.c +++ b/apps/cli/cli_generate.c @@ -284,7 +284,7 @@ yang2cli_var_pattern(clicon_handle h, cbuf *cb) { int retval = -1; - char *mode; + enum regexp_mode mode; cg_var *cvp; char *pattern; int invert; @@ -295,7 +295,7 @@ yang2cli_var_pattern(clicon_handle h, while ((cvp = cvec_each(patterns, cvp)) != NULL){ pattern = cv_string_get(cvp); invert = cv_flag(cvp, V_INVERT); - if (strcmp(mode, "posix") == 0){ + if (mode == REGEXP_POSIX){ posix = NULL; if (regexp_xsd2posix(pattern, &posix) < 0) goto done; diff --git a/apps/cli/cli_main.c b/apps/cli/cli_main.c index 36b0d255..57e7da65 100644 --- a/apps/cli/cli_main.c +++ b/apps/cli/cli_main.c @@ -446,7 +446,7 @@ main(int argc, char **argv) if (help) usage(h, argv[0]); - if (strcmp(clicon_yang_regexp(h), "libxml2")==0){ + if (clicon_yang_regexp(h) == REGEXP_LIBXML2){ #ifdef HAVE_LIBXML2 /* Enable XSD libxml2 regex engine */ cligen_regex_xsd_set(cli_cligen(h), 1); diff --git a/lib/clixon/clixon_options.h b/lib/clixon/clixon_options.h index 8e4d5922..c25e1f21 100644 --- a/lib/clixon/clixon_options.h +++ b/lib/clixon/clixon_options.h @@ -82,6 +82,14 @@ enum datastore_cache{ DATASTORE_CACHE_ZEROCOPY }; +/*! yang clixon regexp engine + * @see regexp_mode in clixon-config.yang + */ +enum regexp_mode{ + REGEXP_POSIX, + REGEXP_LIBXML2 +}; + /* * Prototypes */ @@ -129,9 +137,6 @@ static inline char *clicon_yang_module_main(clicon_handle h){ static inline char *clicon_yang_module_revision(clicon_handle h){ return clicon_option_str(h, "CLICON_YANG_MODULE_REVISION"); } -static inline char *clicon_yang_regexp(clicon_handle h){ - return clicon_option_str(h, "CLICON_YANG_REGEXP"); -} static inline char *clicon_backend_dir(clicon_handle h){ return clicon_option_str(h, "CLICON_BACKEND_DIR"); } @@ -176,7 +181,7 @@ int clicon_sock_port(clicon_handle h); int clicon_autocommit(clicon_handle h); int clicon_startup_mode(clicon_handle h); enum datastore_cache clicon_datastore_cache(clicon_handle h); - +enum regexp_mode clicon_yang_regexp(clicon_handle h); /*-- Specific option access functions for non-yang options --*/ int clicon_quiet_mode(clicon_handle h); int clicon_quiet_mode_set(clicon_handle h, int val); diff --git a/lib/clixon/clixon_regex.h b/lib/clixon/clixon_regex.h index ccd1d555..1266a504 100644 --- a/lib/clixon/clixon_regex.h +++ b/lib/clixon/clixon_regex.h @@ -42,5 +42,6 @@ int regexp_xsd2posix(char *xsd, char **posix); int regex_compile(clicon_handle h, char *regexp, void **recomp); int regex_exec(clicon_handle h, void *recomp, char *string); +int regex_free(clicon_handle h, void *recomp); #endif /* _CLIXON_REGEX_H_ */ diff --git a/lib/clixon/clixon_yang_type.h b/lib/clixon/clixon_yang_type.h index 8aa6a4fa..dc6438eb 100644 --- a/lib/clixon/clixon_yang_type.h +++ b/lib/clixon/clixon_yang_type.h @@ -56,10 +56,12 @@ typedef struct yang_type_cache yang_type_cache; */ int yang_type_cache_set(yang_type_cache **ycache, yang_stmt *resolved, int options, - cvec *cvv, cvec *patterns, cvec *regexps, + cvec *cvv, cvec *patterns, + int rxmode, cvec *regexps, uint8_t fraction); int yang_type_cache_get(yang_type_cache *ycache, yang_stmt **resolved, int *options, cvec **cvv, cvec *patterns, + int *rxmode, cvec *regexps, 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); diff --git a/lib/src/clixon_options.c b/lib/src/clixon_options.c index 2aea61c5..d91dc9ee 100644 --- a/lib/src/clixon_options.c +++ b/lib/src/clixon_options.c @@ -640,8 +640,8 @@ static const map_str2int datastore_cache_map[] = { {NULL, -1} }; -/*! How to generate and show CLI syntax: VARS|ALL - * @see clixon-config@.yang CLICON_CLI_GENMODEL_TYPE +/*! Which datastore cache method to use + * @see clixon-config@.yang CLICON_DATASTORE_CACHE */ enum datastore_cache clicon_datastore_cache(clicon_handle h) @@ -654,6 +654,25 @@ clicon_datastore_cache(clicon_handle h) return clicon_str2int(datastore_cache_map, str); } +static const map_str2int yang_regexp_map[] = { + {"posix", REGEXP_POSIX}, + {"libxml2", REGEXP_LIBXML2}, + {NULL, -1} +}; + +/*! Which Yang regexp/pattern engine to use + * @see clixon-config@.yang CLICON_YANG_REGEXP + */ +enum regexp_mode +clicon_yang_regexp(clicon_handle h) +{ + char *str; + + if ((str = clicon_option_str(h, "CLICON_YANG_REGEXP")) == NULL) + return REGEXP_POSIX; + else + return clicon_str2int(yang_regexp_map, str); +} /*--------------------------------------------------------------------- * Specific option access functions for non-yang options diff --git a/lib/src/clixon_regex.c b/lib/src/clixon_regex.c index 6e1b195b..663c6f03 100644 --- a/lib/src/clixon_regex.c +++ b/lib/src/clixon_regex.c @@ -218,21 +218,21 @@ regex_compile(clicon_handle h, char *regexp, void **recomp) { - int retval = -1; - char *mode; - char *posix = NULL; /* Transform to posix regex */ + int retval = -1; + char *posix = NULL; /* Transform to posix regex */ - mode = clicon_yang_regexp(h); - if (strcmp(mode, "posix") == 0){ + switch (clicon_yang_regexp(h)){ + case REGEXP_POSIX: if (regexp_xsd2posix(regexp, &posix) < 0) goto done; retval = cligen_regex_posix_compile(posix, recomp); - } - else if (strcmp(mode, "libxml2") == 0) + break; + case REGEXP_LIBXML2: retval = cligen_regex_libxml2_compile(regexp, recomp); - else{ - clicon_err(OE_CFG, 0, "clicon_yang_regexp invalid value: %s", mode); - goto done; + break; + default: + clicon_err(OE_CFG, 0, "clicon_yang_regexp invalid value: %d", clicon_yang_regexp(h)); + break; } /* retval from fns above */ done: @@ -242,7 +242,9 @@ regex_compile(clicon_handle h, } /*! Execution of (pre-compiled) regular expression / pattern - * @param[in] h Clicon handle + * @param[in] h Clicon handle + * @param[in] recomp Compiled regular expression + * @param[in] string Content string to match */ int regex_exec(clicon_handle h, @@ -250,15 +252,43 @@ regex_exec(clicon_handle h, char *string) { int retval = -1; - char *mode; - mode = clicon_yang_regexp(h); - if (strcmp(mode, "posix") == 0) + switch (clicon_yang_regexp(h)){ + case REGEXP_POSIX: retval = cligen_regex_posix_exec(recomp, string); - else if (strcmp(mode, "libxml2") == 0) + break; + case REGEXP_LIBXML2: retval = cligen_regex_libxml2_exec(recomp, string); - else{ - clicon_err(OE_CFG, 0, "clicon_yang_regexp invalid value: %s", mode); + break; + default: + clicon_err(OE_CFG, 0, "clicon_yang_regexp invalid value: %d", + clicon_yang_regexp(h)); + goto done; + } + /* retval from fns above */ + done: + return retval; +} + +/*! Free of (pre-compiled) regular expression / pattern + * @param[in] h Clicon handle + * @param[in] recomp Compiled regular expression + */ +int +regex_free(clicon_handle h, + void *recomp) +{ + int retval = -1; + + switch (clicon_yang_regexp(h)){ + case REGEXP_POSIX: + retval = cligen_regex_posix_free(recomp); + break; + case REGEXP_LIBXML2: + retval = cligen_regex_libxml2_free(recomp); + break; + default: + clicon_err(OE_CFG, 0, "clicon_yang_regexp invalid value: %d", clicon_yang_regexp(h)); goto done; } /* retval from fns above */ diff --git a/lib/src/clixon_yang_internal.h b/lib/src/clixon_yang_internal.h index acf7d416..98aefbab 100644 --- a/lib/src/clixon_yang_internal.h +++ b/lib/src/clixon_yang_internal.h @@ -61,6 +61,7 @@ struct yang_type_cache{ LENGTH|RANGE. Can be a vector if multiple ranges*/ cvec *yc_patterns; /* list of regexp, if cvec_len() > 0 */ + int yc_rxmode; /* need to store mode for freeing since handle may not be available */ cvec *yc_regexps; /* list of _compiled_ regexp, if cvec_len() > 0 */ uint8_t yc_fraction; /* Fraction digits for decimal64 (if YANG_OPTIONS_FRACTION_DIGITS */ diff --git a/lib/src/clixon_yang_type.c b/lib/src/clixon_yang_type.c index 702093d0..f03132dd 100644 --- a/lib/src/clixon_yang_type.c +++ b/lib/src/clixon_yang_type.c @@ -155,6 +155,7 @@ yang_builtin(char *type) } /*! Set type cache for yang type + * @param[in] rxmode Kludge to know which regexp engine is used */ int yang_type_cache_set(yang_type_cache **ycache0, @@ -162,6 +163,7 @@ yang_type_cache_set(yang_type_cache **ycache0, int options, cvec *cvv, cvec *patterns, + int rxmode, cvec *regexps, uint8_t fraction) { @@ -187,6 +189,7 @@ yang_type_cache_set(yang_type_cache **ycache0, clicon_err(OE_UNIX, errno, "cvec_dup"); goto done; } + ycache->yc_rxmode = rxmode; if (regexps && (ycache->yc_regexps = cvec_dup(regexps)) == NULL){ clicon_err(OE_UNIX, errno, "cvec_dup"); goto done; @@ -206,6 +209,7 @@ yang_type_cache_get(yang_type_cache *ycache, int *options, cvec **cvv, cvec *patterns, + int *rxmode, cvec *regexps, uint8_t *fraction) { @@ -228,6 +232,8 @@ yang_type_cache_get(yang_type_cache *ycache, while ((cv = cvec_each(ycache->yc_regexps, cv)) != NULL) cvec_append_var(regexps, cv); } + if (rxmode) + *rxmode = ycache->yc_rxmode; if (fraction) *fraction = ycache->yc_fraction; retval = 0; @@ -243,6 +249,7 @@ yang_type_cache_cp(yang_type_cache **ycnew, int options; cvec *cvv; cvec *patterns = NULL; + int rxmode; cvec *regexps = NULL; uint8_t fraction; yang_stmt *resolved; @@ -255,8 +262,8 @@ yang_type_cache_cp(yang_type_cache **ycnew, clicon_err(OE_UNIX, errno, "cvec_new"); goto done; } - yang_type_cache_get(ycold, &resolved, &options, &cvv, patterns, regexps, &fraction); - if (yang_type_cache_set(ycnew, resolved, options, cvv, patterns, regexps, fraction) < 0) + yang_type_cache_get(ycold, &resolved, &options, &cvv, patterns, &rxmode, regexps, &fraction); + if (yang_type_cache_set(ycnew, resolved, options, cvv, patterns, rxmode, regexps, fraction) < 0) goto done; retval = 0; done: @@ -270,12 +277,29 @@ yang_type_cache_cp(yang_type_cache **ycnew, int yang_type_cache_free(yang_type_cache *ycache) { + cg_var *cv; + if (ycache->yc_cvv) cvec_free(ycache->yc_cvv); if (ycache->yc_patterns) cvec_free(ycache->yc_patterns); - if (ycache->yc_regexps) + if (ycache->yc_regexps){ + cv = NULL; + while ((cv = cvec_each(ycache->yc_regexps, cv)) != NULL){ + /* need to store mode since clicon_handle is not available */ + switch (ycache->yc_rxmode){ + case REGEXP_POSIX: + cligen_regex_posix_free(cv_void_get(cv)); + break; + case REGEXP_LIBXML2: + cligen_regex_libxml2_free(cv_void_get(cv)); + break; + default: + break; + } + } cvec_free(ycache->yc_regexps); + } free(ycache); return 0; } @@ -304,8 +328,6 @@ compile_pattern2regexp(clicon_handle h, pcv = NULL; while ((pcv = cvec_each(patterns, pcv)) != NULL){ - if (cv_type_get(pcv) == CGV_VOID) - continue; /* already compiled */ pattern = cv_string_get(pcv); /* Compile yang pattern. handle necessary to select regex engine */ if ((ret = regex_compile(h, pattern, &re)) < 0) @@ -380,7 +402,7 @@ ys_resolve_type(yang_stmt *ys, */ if (yang_type_cache_set(&ys->ys_typecache, resolved, options, cvv, - patterns, regexps, + patterns, clicon_yang_regexp(h), regexps, fraction) < 0) goto done; retval = 0; @@ -1169,7 +1191,7 @@ yang_type_resolve(yang_stmt *yorig, /* Cache does not work for eg string length 32? */ if (/*!yang_builtin(type) &&*/ ytype->ys_typecache != NULL){ if (yang_type_cache_get(ytype->ys_typecache, yrestype, - options, cvv, patterns, regexps, fraction) < 0) + options, cvv, patterns, NULL, regexps, fraction) < 0) goto done; goto ok; }