]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libsmartcols: (filter) add regular expression operators
authorKarel Zak <kzak@redhat.com>
Thu, 14 Sep 2023 09:55:03 +0000 (11:55 +0200)
committerKarel Zak <kzak@redhat.com>
Mon, 20 Nov 2023 21:25:46 +0000 (22:25 +0100)
Signed-off-by: Karel Zak <kzak@redhat.com>
libsmartcols/src/filter-expr.c
libsmartcols/src/filter-param.c
libsmartcols/src/filter-parser.y
libsmartcols/src/smartcolsP.h

index b92023d346bbfaacf9c7ccbf6de5dd7e5661c5bb..ddd64370386926d3ef212203da914f96ae72596f 100644 (file)
@@ -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);
index aeb286f4fb781a2210b86af1e900879a0b012b47..295695e0a6b32b81865ed552120b78270cc45de3 100644 (file)
@@ -2,6 +2,7 @@
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
+#include <regex.h>
 
 #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,
index cf03b4f2d913a2a6821971402d84a6583a66c50f..c62aa151597ef143a41249098e983389c47e6597 100644 (file)
@@ -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;
index 4ad86a858b3f0fcc91187aced8a1eb9ff41bf52c..f892855c7c9addad25e4364f995962227e525c45 100644 (file)
@@ -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,