From: Karel Zak Date: Thu, 14 Sep 2023 09:55:03 +0000 (+0200) Subject: libsmartcols: (filter) add regular expression operators X-Git-Tag: v2.40-rc1~151^2~62 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=408ae150a6a170708e2f678c594f415dd83eb65e;p=thirdparty%2Futil-linux.git libsmartcols: (filter) add regular expression operators Signed-off-by: Karel Zak --- diff --git a/libsmartcols/src/filter-expr.c b/libsmartcols/src/filter-expr.c index b92023d346..ddd6437038 100644 --- a/libsmartcols/src/filter-expr.c +++ b/libsmartcols/src/filter-expr.c @@ -40,7 +40,6 @@ struct filter_node *filter_new_expr( case F_EXPR_NEG: n->right = right; break; - } return (struct filter_node *) n; } @@ -202,7 +201,7 @@ int filter_eval_expr(struct libscols_filter *fltr, struct libscols_line *ln, if (!rc) rc = cast_node(fltr, ln, type, n->right, &r); if (!rc) - rc = filter_compare_params(fltr, ln, oper, l, r, status); + rc = filter_compare_params(fltr, oper, l, r, status); filter_unref_node((struct filter_node *) l); filter_unref_node((struct filter_node *) r); diff --git a/libsmartcols/src/filter-param.c b/libsmartcols/src/filter-param.c index aeb286f4fb..295695e0a6 100644 --- a/libsmartcols/src/filter-param.c +++ b/libsmartcols/src/filter-param.c @@ -2,6 +2,7 @@ #include #include #include +#include #include "smartcolsP.h" @@ -20,6 +21,7 @@ struct filter_param { struct list_head pr_params; struct libscols_column *col; char *holder_name; + regex_t *re; unsigned int has_value :1; }; @@ -107,6 +109,32 @@ struct filter_node *filter_new_param( return (struct filter_node *) n; } +int filter_compile_param(struct libscols_filter *fltr, struct filter_param *n) +{ + int rc; + + if (n->re) + return 0; + if (!n->val.str) + return -EINVAL; + + n->re = calloc(1, sizeof(regex_t)); + if (!n->re) + return -ENOMEM; + + rc = regcomp(n->re, n->val.str, REG_NOSUB | REG_EXTENDED); + if (rc) { + size_t size = regerror(rc, n->re, NULL, 0); + + fltr->errmsg = malloc(size + 1); + if (!fltr->errmsg) + return -ENOMEM; + regerror(rc, n->re, fltr->errmsg, size); + return -EINVAL; + } + return 0; +} + static struct filter_param *copy_param(struct filter_param *n) { return (struct filter_param *) filter_new_param(NULL, @@ -120,8 +148,12 @@ static void param_reset_data(struct filter_param *n) memset(&n->val, 0, sizeof(n->val)); n->has_value = 0; -} + if (n->re) { + regfree(n->re); + free(n->re); + } +} void filter_free_param(struct filter_param *n) { @@ -312,6 +344,16 @@ static int string_opers(enum filter_etype oper, struct filter_param *l, case F_EXPR_GT: *status = xstrcmp(l->val.str, r->val.str) > 0; break; + case F_EXPR_REG: + if (!r->re) + return -EINVAL; + *status = regexec(r->re, l->val.str ? : "", 0, NULL, 0) == 0; + break; + case F_EXPR_NREG: + if (!r->re) + return -EINVAL; + *status = regexec(r->re, l->val.str ? : "", 0, NULL, 0) != 0; + break; default: return -EINVAL; } @@ -405,7 +447,6 @@ static int bool_opers(enum filter_etype oper, struct filter_param *l, /* call filter_cast_param() to be sure that param data are ready (fetched from * holder, etc.) */ int filter_compare_params(struct libscols_filter *fltr __attribute__((__unused__)), - struct libscols_line *ln __attribute__((__unused__)), enum filter_etype oper, struct filter_param *l, struct filter_param *r, diff --git a/libsmartcols/src/filter-parser.y b/libsmartcols/src/filter-parser.y index cf03b4f2d9..c62aa15159 100644 --- a/libsmartcols/src/filter-parser.y +++ b/libsmartcols/src/filter-parser.y @@ -70,8 +70,18 @@ expr: | expr T_LT expr { $$ = filter_new_expr(fltr, F_EXPR_LT, $1, $3); } | expr T_GE expr { $$ = filter_new_expr(fltr, F_EXPR_GE, $1, $3); } | expr T_GT expr { $$ = filter_new_expr(fltr, F_EXPR_GT, $1, $3); } - | expr T_REG expr { $$ = filter_new_expr(fltr, F_EXPR_REG, $1, $3); } - | expr T_NREG expr { $$ = filter_new_expr(fltr, F_EXPR_NREG, $1, $3); } + + | expr T_REG expr { + if (filter_compile_param(fltr, (struct filter_param *) $3) != 0) + YYERROR; + $$ = filter_new_expr(fltr, F_EXPR_REG, $1, $3); + } + + | expr T_NREG expr { + if (filter_compile_param(fltr, (struct filter_param *) $3) != 0) + YYERROR; + $$ = filter_new_expr(fltr, F_EXPR_NREG, $1, $3); + } ; param: @@ -97,7 +107,9 @@ void yyerror (yyscan_t *locp __attribute__((__unused__)), struct libscols_filter *fltr, char const *msg) { - if (msg) { + if (msg && fltr) { + if (fltr->errmsg) + free(fltr->errmsg); fltr->errmsg = strdup(msg); if (!fltr->errmsg) return; diff --git a/libsmartcols/src/smartcolsP.h b/libsmartcols/src/smartcolsP.h index 4ad86a858b..f892855c7c 100644 --- a/libsmartcols/src/smartcolsP.h +++ b/libsmartcols/src/smartcolsP.h @@ -548,6 +548,7 @@ int filter_eval_node(struct libscols_filter *fltr, struct libscols_line *ln, struct filter_node *n, int *status); /* param */ +int filter_compile_param(struct libscols_filter *fltr, struct filter_param *n); void filter_dump_param(struct ul_jsonwrt *json, struct filter_param *n); int filter_eval_param(struct libscols_filter *fltr, struct libscols_line *ln, struct filter_param *n, int *status); @@ -559,7 +560,6 @@ int filter_next_param(struct libscols_filter *fltr, struct libscols_iter *itr, struct filter_param **prm); int filter_compare_params(struct libscols_filter *fltr, - struct libscols_line *ln, enum filter_etype oper, struct filter_param *l, struct filter_param *r,