Commit 20c820e8 authored by Dridi Boukelmoune's avatar Dridi Boukelmoune

vcc: New REGEX type with expressions

By introducing a proper REGEX type in VCL we can centralize the regular
expressions literals parsing. The type itself is currently not very
potent since VMODs aren't aware of it, but as a first step it allows
error messages to be improved at compile time.
parent 2065315a
varnishtest "Regression test for ticket 409"
varnish v1 -errvcl {Expected CSTR got '!'} {
backend b { .host = "${localhost}"; }
varnish v1 -errvcl {Unknown token '!' when looking for REGEX} {
backend be none;
sub vcl_recv {
if ( req.url ~ ! "\.(png|jpg|gif|js|css)$" ) {
return (pass);
}
}
}
varnish v1 -errvcl {Expression has type STRING, expected REGEX} {
backend be none;
sub vcl_recv {
set req.http.regex = "\.(png|jpg|gif|js|css)$";
if (req.url ~ req.http.regex) {
return (pass);
}
}
}
varnish v1 -errvcl {Expression has type STRING, expected REGEX} {
backend be none;
sub vcl_recv {
set req.http.regex = "\?.*";
set req.url = regsub(req.url, req.http.regex, "");
}
}
......@@ -273,6 +273,7 @@ typedef int64_t VCL_INT;
typedef const struct suckaddr * VCL_IP;
typedef const struct vrt_backend_probe * VCL_PROBE;
typedef double VCL_REAL;
typedef const struct vre * VCL_REGEX;
typedef const struct stevedore * VCL_STEVEDORE;
typedef const struct strands * VCL_STRANDS;
typedef const char * VCL_STRING;
......
......@@ -771,6 +771,10 @@ vcc_expr5(struct vcc *tl, struct expr **e, vcc_type_t fmt)
ERRCHK(tl);
e1 = vcc_mk_expr(IP, "%s", ip);
ERRCHK(tl);
} else if (fmt == REGEX) {
e1 = vcc_new_expr(REGEX);
vcc_regexp(tl, e1->vsb);
AZ(VSB_finish(e1->vsb));
} else {
e1 = vcc_new_expr(STRINGS);
EncToken(e1->vsb, tl->t);
......@@ -1075,20 +1079,15 @@ cmp_simple(struct vcc *tl, struct expr **e, const struct cmps *cp)
static void v_matchproto_(cmp_f)
cmp_regexp(struct vcc *tl, struct expr **e, const struct cmps *cp)
{
struct expr *e2;
char buf[128];
struct vsb vsb;
*e = vcc_expr_edit(tl, STRING, "\vS", *e, NULL);
vcc_NextToken(tl);
ExpectErr(tl, CSTR);
AN(VSB_init(&vsb, buf, sizeof buf));
VSB_printf(&vsb, "%sVRT_re_match(ctx, \v1, ", cp->emit);
vcc_regexp(tl, &vsb);
vcc_expr0(tl, &e2, REGEX);
ERRCHK(tl);
VSB_cat(&vsb, ")");
AZ(VSB_finish(&vsb));
*e = vcc_expr_edit(tl, BOOL, VSB_data(&vsb), *e, NULL);
VSB_fini(&vsb);
bprintf(buf, "%sVRT_re_match(ctx, \v1, \v2)", cp->emit);
*e = vcc_expr_edit(tl, BOOL, buf, *e, e2);
}
static void v_matchproto_(cmp_f)
......@@ -1342,6 +1341,8 @@ vcc_expr0(struct vcc *tl, struct expr **e, vcc_type_t fmt)
t1 = tl->t;
if (fmt->stringform)
vcc_expr_cor(tl, e, STRINGS);
else if (fmt == REGEX)
vcc_expr4(tl, e, REGEX);
else
vcc_expr_cor(tl, e, fmt);
ERRCHK(tl);
......@@ -1457,10 +1458,9 @@ static void v_matchproto_(sym_expr_t)
vcc_Eval_Regsub(struct vcc *tl, struct expr **e, struct token *t,
struct symbol *sym, vcc_type_t fmt)
{
struct expr *e2;
struct expr *e2, *e3;
int all = sym->eval_priv == NULL ? 0 : 1;
char buf[128];
struct vsb vsb;
(void)t;
(void)fmt;
......@@ -1468,15 +1468,11 @@ vcc_Eval_Regsub(struct vcc *tl, struct expr **e, struct token *t,
vcc_expr0(tl, &e2, STRING);
ERRCHK(tl);
SkipToken(tl, ',');
ExpectErr(tl, CSTR);
AN(VSB_init(&vsb, buf, sizeof buf));
VSB_printf(&vsb, "VRT_regsub(ctx, %d,\v+\n\v1,\n", all);
vcc_regexp(tl, &vsb);
vcc_expr0(tl, &e3, REGEX);
ERRCHK(tl);
AZ(VSB_finish(&vsb));
*e = vcc_expr_edit(tl, STRING, VSB_data(&vsb), e2, NULL);
VSB_fini(&vsb);
bprintf(buf, "VRT_regsub(ctx, %d,\v+\n\v1,\n\v2", all);
*e = vcc_expr_edit(tl, STRING, buf, e2, e3);
SkipToken(tl, ',');
vcc_expr0(tl, &e2, STRING);
ERRCHK(tl);
......
......@@ -151,6 +151,11 @@ const struct type REAL[1] = {{
.multype = REAL,
}};
const struct type REGEX[1] = {{
.magic = TYPE_MAGIC,
.name = "REGEX",
}};
static const struct vcc_method stevedore_methods[] = {
#define VRTSTVVAR(nm, vtype, ctype, dval) \
{ VCC_METHOD_MAGIC, vtype, #nm, "VRT_stevedore_" #nm "(\v1)", 0},
......
......@@ -57,9 +57,8 @@ vcc_regexp(struct vcc *tl, struct vsb *vgc_name)
int erroroffset;
struct inifin *ifp;
Expect(tl, CSTR);
if (tl->err)
return;
assert(tl->t->tok == CSTR);
t = VRE_compile(tl->t->dec, 0, &error, &erroroffset);
if (t == NULL) {
VSB_printf(tl->sb,
......@@ -78,7 +77,6 @@ vcc_regexp(struct vcc *tl, struct vsb *vgc_name)
EncToken(ifp->ini, tl->t);
VSB_cat(ifp->ini, ");");
VSB_printf(ifp->fin, "\t\tVRT_re_fini(%s);", buf);
vcc_NextToken(tl);
}
/*
......
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