Commit b2a04a0a authored by Martin Blix Grydeland's avatar Martin Blix Grydeland

Add support for caseless string comparison and regular expression

evaluation.
parent 0de1ebe0
......@@ -33,6 +33,7 @@
VUT_OPT_a
VSL_OPT_b
VSL_OPT_c
VSL_OPT_C
VUT_OPT_d
VUT_OPT_D
VUT_OPT_g
......
......@@ -29,12 +29,6 @@ The following options are available:
.. include:: ../../../bin/varnishlog/varnishlog_options.rst
-C
Ignore case when matching regular expressions.
XXX: Not yet implemented
-k num
Only show the first num log transactions (or log records
......
......@@ -45,6 +45,11 @@
" client communication." \
)
#define VSL_OPT_C \
VOPT("C", "[-C]", "Caseless regular expressions", \
"Do all regular expression and string matching caseless." \
)
#define VSL_OPT_i \
VOPT("i:", "[-i taglist]", "Include tags", \
"Include log records of these tags in output. Taglist is" \
......
......@@ -87,6 +87,7 @@ struct VSL_data {
int b_opt;
int c_opt;
int C_opt;
int L_opt;
double T_opt;
int v_opt;
......
......@@ -286,7 +286,7 @@ vsl_IX_arg(struct VSL_data *vsl, int opt, const char *arg)
b = e + 1;
}
vre = VRE_compile(b, 0, &err, &off);
vre = VRE_compile(b, vsl->C_opt ? VRE_CASELESS : 0, &err, &off);
if (vre == NULL) {
if (tags)
vbit_destroy(tags);
......@@ -326,6 +326,10 @@ VSL_Arg(struct VSL_data *vsl, int opt, const char *arg)
switch (opt) {
case 'b': vsl->b_opt = 1; return (1);
case 'c': vsl->c_opt = 1; return (1);
case 'C':
/* Caseless regular expressions */
vsl->C_opt = 1;
return (1);
case 'i': case 'x': return (vsl_ix_arg(vsl, opt, arg));
case 'I': case 'X': return (vsl_IX_arg(vsl, opt, arg));
case 'L':
......
......@@ -168,15 +168,27 @@ vslq_test_rec(const struct vex *vex, const struct VSLC_ptr *rec)
VSLQ_TEST_NUMOP(rhs->type, lhs, >=, rhs->val);
case T_SEQ: /* eq */
assert(rhs->type == VEX_STRING);
if (e - b == rhs->val_stringlen &&
!strncmp(b, rhs->val_string, e - b))
return (1);
return (0);
if (e - b != rhs->val_stringlen)
return (0);
if (vex->options & VEX_OPT_CASELESS) {
if (strncasecmp(b, rhs->val_string, e - b))
return (0);
} else {
if (strncmp(b, rhs->val_string, e - b))
return (0);
}
return (1);
case T_SNEQ: /* ne */
assert(rhs->type == VEX_STRING);
if (e - b != rhs->val_stringlen ||
strncmp(b, rhs->val_string, e - b))
if (e - b != rhs->val_stringlen)
return (1);
if (vex->options & VEX_OPT_CASELESS) {
if (strncasecmp(b, rhs->val_string, e - b))
return (1);
} else {
if (strncmp(b, rhs->val_string, e - b))
return (1);
}
return (0);
case '~': /* ~ */
assert(rhs->type == VEX_REGEX && rhs->val_regex != NULL);
......@@ -294,7 +306,7 @@ vslq_newquery(struct VSL_data *vsl, enum VSL_grouping_e grouping,
vsb = VSB_new_auto();
AN(vsb);
vex = vex_New(querystring, vsb);
vex = vex_New(querystring, vsb, vsl->C_opt ? VEX_OPT_CASELESS : 0);
AZ(VSB_finish(vsb));
if (vex == NULL)
vsl_diag(vsl, "%s", VSB_data(vsb));
......
......@@ -195,7 +195,7 @@ vxp_Delete(struct vxp **pvxp)
}
struct vex *
vex_New(const char *query, struct vsb *sb)
vex_New(const char *query, struct vsb *sb, unsigned options)
{
struct vxp *vxp;
struct vex *vex;
......@@ -205,6 +205,9 @@ vex_New(const char *query, struct vsb *sb)
vxp = vxp_New(sb);
vxp->b = query;
vxp->e = query + strlen(query);
vxp->vex_options = options;
if (options & VEX_OPT_CASELESS)
vxp->vre_options |= VRE_CASELESS;
vxp_Lexer(vxp);
......
......@@ -70,6 +70,9 @@ struct vxp {
VTAILQ_HEAD(, membit) membits;
struct token *t;
unsigned vex_options;
int vre_options;
struct vsb *sb;
int err;
};
......@@ -115,6 +118,7 @@ struct vex {
unsigned magic;
#define VEX_MAGIC 0xC7DB792D
unsigned tok;
unsigned options;
struct vex *a, *b;
struct vex_lhs *lhs;
struct vex_rhs *rhs;
......@@ -137,8 +141,8 @@ void vxp_Lexer(struct vxp *vxp);
struct vex * vxp_Parse(struct vxp *vxp);
/* API internal interface */
struct vex * vex_New(const char *query, struct vsb *sb);
#define VEX_OPT_CASELESS (1 << 0)
struct vex * vex_New(const char *query, struct vsb *sb, unsigned options);
void vex_Free(struct vex **pvex);
/* Debug routines */
......
......@@ -49,6 +49,17 @@
static void vxp_expr_or(struct vxp *vxp, struct vex **pvex);
static struct vex *
vex_alloc(struct vxp *vxp)
{
struct vex *vex;
ALLOC_OBJ(vex, VEX_MAGIC);
AN(vex);
vex->options = vxp->vex_options;
return (vex);
}
static void
vxp_expr_lhs(struct vxp *vxp, struct vex_lhs **plhs)
{
......@@ -244,7 +255,8 @@ vxp_expr_regex(struct vxp *vxp, struct vex_rhs **prhs)
AN(*prhs);
(*prhs)->type = VEX_REGEX;
(*prhs)->val_string = strdup(vxp->t->dec);
(*prhs)->val_regex = VRE_compile(vxp->t->dec, 0, &errptr, &erroff);
(*prhs)->val_regex = VRE_compile(vxp->t->dec, vxp->vre_options,
&errptr, &erroff);
if ((*prhs)->val_regex == NULL) {
AN(errptr);
VSB_printf(vxp->sb, "Regular expression error: %s ", errptr);
......@@ -267,7 +279,7 @@ vxp_expr_cmp(struct vxp *vxp, struct vex **pvex)
AN(pvex);
AZ(*pvex);
ALLOC_OBJ(*pvex, VEX_MAGIC);
*pvex = vex_alloc(vxp);
AN(*pvex);
vxp_expr_lhs(vxp, &(*pvex)->lhs);
ERRCHK(vxp);
......@@ -373,7 +385,7 @@ vxp_expr_not(struct vxp *vxp, struct vex **pvex)
AZ(*pvex);
if (vxp->t->tok == T_NOT) {
ALLOC_OBJ(*pvex, VEX_MAGIC);
*pvex = vex_alloc(vxp);
AN(*pvex);
(*pvex)->tok = vxp->t->tok;
vxp_NextToken(vxp);
......@@ -402,7 +414,7 @@ vxp_expr_and(struct vxp *vxp, struct vex **pvex)
ERRCHK(vxp);
while (vxp->t->tok == T_AND) {
a = *pvex;
ALLOC_OBJ(*pvex, VEX_MAGIC);
*pvex = vex_alloc(vxp);
AN(*pvex);
(*pvex)->tok = vxp->t->tok;
(*pvex)->a = a;
......@@ -430,7 +442,7 @@ vxp_expr_or(struct vxp *vxp, struct vex **pvex)
ERRCHK(vxp);
while (vxp->t->tok == T_OR) {
a = *pvex;
ALLOC_OBJ(*pvex, VEX_MAGIC);
*pvex = vex_alloc(vxp);
AN(*pvex);
(*pvex)->tok = vxp->t->tok;
(*pvex)->a = a;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment