[master] b317d95 Introduce VCL_STRANDS, and use it for string compare.
Poul-Henning Kamp
phk at FreeBSD.org
Thu Dec 14 10:16:04 UTC 2017
commit b317d959cc797221ece4127896b305d30204f58f
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date: Thu Dec 14 10:12:15 2017 +0000
Introduce VCL_STRANDS, and use it for string compare.
VCL_STRANDS is an alternative to VCL_STRING_LIST which uses a
struct instead of varargs.
This means that multiple VCL_STRANDS can be passed to a function,
and string-compare really needed that to not waste workspace.
Add <, >, <=, >= string comparisons while here anyway.
The struct and a const char *[N] array are built on the stack and
they are only valid for the duration of the function call.
diff --git a/bin/varnishd/cache/cache_vrt.c b/bin/varnishd/cache/cache_vrt.c
index 3d0952f..9adc590 100644
--- a/bin/varnishd/cache/cache_vrt.c
+++ b/bin/varnishd/cache/cache_vrt.c
@@ -157,6 +157,64 @@ VRT_GetHdr(VRT_CTX, const struct gethdr_s *hs)
}
/*--------------------------------------------------------------------
+ * Build STRANDS from what is essentially a STRING_LIST
+ */
+
+VCL_STRANDS
+VRT_BundleStrands(int n, struct strands *s, char const **d, const char *f, ...)
+{
+ va_list ap;
+
+ s->n = n;
+ s->p = d;
+ *d++ = f;
+ va_start(ap, f);
+ while(--n)
+ *d++ = va_arg(ap, const char *);
+ assert(va_arg(ap, const char *) == vrt_magic_string_end);
+ va_end(ap);
+ return (s);
+}
+
+/*--------------------------------------------------------------------
+ * Compare two STRANDS
+ */
+
+int
+VRT_CompareStrands(VCL_STRANDS a, VCL_STRANDS b)
+{
+ const char *pa = NULL, *pb = NULL;
+ int na = 0, nb = 0;
+
+ while (1) {
+ if (pa != NULL && *pa == '\0')
+ pa = NULL;
+ if (pb != NULL && *pb == '\0')
+ pb = NULL;
+ if (pa == NULL && na < a->n)
+ pa = a->p[na++];
+ else if (pb == NULL && nb < b->n)
+ pb = b->p[nb++];
+ else if (pa == NULL && pb == NULL)
+ return (0);
+ else if (pa == NULL)
+ return (-1);
+ else if (pb == NULL)
+ return (1);
+ else if (*pa == '\0')
+ pa = NULL;
+ else if (*pb == '\0')
+ pb = NULL;
+ else if (*pa != *pb)
+ return (*pa - *pb);
+ else {
+ pa++;
+ pb++;
+ }
+ }
+}
+
+/*--------------------------------------------------------------------
* Collapse a STRING_LIST in the space provided, or return NULL
*/
@@ -341,7 +399,7 @@ VRT_r_now(VRT_CTX)
/*--------------------------------------------------------------------*/
-char *
+VCL_STRING v_matchproto_()
VRT_IP_string(VRT_CTX, VCL_IP ip)
{
char *p;
@@ -361,7 +419,7 @@ VRT_IP_string(VRT_CTX, VCL_IP ip)
return (p);
}
-char *
+VCL_STRING v_matchproto_()
VRT_INT_string(VRT_CTX, long num)
{
@@ -369,7 +427,7 @@ VRT_INT_string(VRT_CTX, long num)
return (WS_Printf(ctx->ws, "%ld", num));
}
-char *
+VCL_STRING v_matchproto_()
VRT_REAL_string(VRT_CTX, double num)
{
@@ -377,7 +435,7 @@ VRT_REAL_string(VRT_CTX, double num)
return (WS_Printf(ctx->ws, "%.3f", num));
}
-char *
+VCL_STRING v_matchproto_()
VRT_TIME_string(VRT_CTX, double t)
{
char *p;
@@ -389,7 +447,7 @@ VRT_TIME_string(VRT_CTX, double t)
return (p);
}
-const char * v_matchproto_()
+VCL_STRING v_matchproto_()
VRT_BACKEND_string(VCL_BACKEND d)
{
if (d == NULL)
@@ -398,7 +456,7 @@ VRT_BACKEND_string(VCL_BACKEND d)
return (d->vcl_name);
}
-const char *
+VCL_STRING v_matchproto_()
VRT_BOOL_string(unsigned val)
{
diff --git a/bin/varnishtest/tests/a00015.vtc b/bin/varnishtest/tests/a00015.vtc
index 03caf19..843637f 100644
--- a/bin/varnishtest/tests/a00015.vtc
+++ b/bin/varnishtest/tests/a00015.vtc
@@ -12,7 +12,7 @@ server s1 {
txresp -hdr "Content-Type: text/plain" -body response
} -start
-varnish v1 -vcl+backend {} -start
+varnish v1 -vcl+backend {} -start -cliok "param.set debug +syncvsl"
client c1 {
txreq -req POST -hdr "Content-Type: text/plain" -body request
diff --git a/bin/varnishtest/tests/v00002.vtc b/bin/varnishtest/tests/v00002.vtc
new file mode 100644
index 0000000..48d914e
--- /dev/null
+++ b/bin/varnishtest/tests/v00002.vtc
@@ -0,0 +1,174 @@
+varnishtest "Test VCL STRINGS/STRANDS comparisons"
+
+server s1 {
+ rxreq
+ txresp
+} -start
+
+varnish v1 -vcl+backend {
+ sub vcl_deliver {
+ set resp.http.test = req.http.test;
+
+ set resp.http.eq =
+ req.http.foo == req.http.bar;
+
+ set resp.http.neq =
+ req.http.foo != req.http.bar;
+
+ set resp.http.lt =
+ req.http.foo < req.http.bar;
+
+ set resp.http.le =
+ req.http.foo <= req.http.bar;
+
+ set resp.http.gt =
+ req.http.foo > req.http.bar;
+
+ set resp.http.ge =
+ req.http.foo >= req.http.bar;
+ }
+} -start
+
+client c1 {
+ txreq -hdr "foo: 1" -hdr "bar: 1" -hdr "test: 1"
+ rxresp
+ expect resp.http.eq == true
+ expect resp.http.neq == false
+ expect resp.http.lt == false
+ expect resp.http.le == true
+ expect resp.http.gt == false
+ expect resp.http.ge == true
+
+ txreq -hdr "foo: 1" -hdr "bar: 2" -hdr "test: 2"
+ rxresp
+ expect resp.http.eq == false
+ expect resp.http.neq == true
+ expect resp.http.lt == true
+ expect resp.http.le == true
+ expect resp.http.gt == false
+ expect resp.http.ge == false
+
+ txreq -hdr "foo: 2" -hdr "bar: 1" -hdr "test: 3"
+ rxresp
+ expect resp.http.eq == false
+ expect resp.http.neq == true
+ expect resp.http.lt == false
+ expect resp.http.le == false
+ expect resp.http.gt == true
+ expect resp.http.ge == true
+
+ txreq -hdr "foo: 1" -hdr "bar: 11" -hdr "test: 4"
+ rxresp
+ expect resp.http.eq == false
+ expect resp.http.neq == true
+ expect resp.http.lt == true
+ expect resp.http.le == true
+ expect resp.http.gt == false
+ expect resp.http.ge == false
+
+ txreq -hdr "foo: 11" -hdr "bar: 1" -hdr "test: 5"
+ rxresp
+ expect resp.http.eq == false
+ expect resp.http.neq == true
+ expect resp.http.lt == false
+ expect resp.http.le == false
+ expect resp.http.gt == true
+ expect resp.http.ge == true
+
+ txreq -hdr "foo:" -hdr "bar:" -hdr "test: 6"
+ rxresp
+ expect resp.http.eq == true
+ expect resp.http.neq == false
+ expect resp.http.lt == false
+ expect resp.http.le == true
+ expect resp.http.gt == false
+ expect resp.http.ge == true
+
+ txreq -hdr "foo:" -hdr "bar: 1" -hdr "test: 7"
+ rxresp
+ expect resp.http.eq == false
+ expect resp.http.neq == true
+ expect resp.http.lt == true
+ expect resp.http.le == true
+ expect resp.http.gt == false
+ expect resp.http.ge == false
+
+} -run
+
+varnish v1 -vsl_catchup -vcl+backend {
+ sub vcl_deliver {
+ set resp.http.test = req.http.test;
+
+ set resp.http.eq =
+ req.http.foo + " " == req.http.bar + " ";
+
+ set resp.http.neq =
+ req.http.foo + " " != req.http.bar + " ";
+
+ set resp.http.lt =
+ req.http.foo + " " < req.http.bar + " ";
+
+ set resp.http.le =
+ req.http.foo + " " <= req.http.bar + " ";
+
+ set resp.http.gt =
+ req.http.foo + " " > req.http.bar + " ";
+
+ set resp.http.ge =
+ req.http.foo + " " >= req.http.bar + " ";
+ }
+}
+
+client c1 -run
+
+varnish v1 -vsl_catchup -vcl+backend {
+ sub vcl_deliver {
+ set resp.http.test = req.http.test;
+
+ set resp.http.eq =
+ req.http.foo == req.http.bar + req.http.not;
+
+ set resp.http.neq =
+ req.http.foo != req.http.bar + req.http.not;
+
+ set resp.http.lt =
+ req.http.foo < req.http.bar + req.http.not;
+
+ set resp.http.le =
+ req.http.foo <= req.http.bar + req.http.not;
+
+ set resp.http.gt =
+ req.http.foo > req.http.bar + req.http.not;
+
+ set resp.http.ge =
+ req.http.foo >= req.http.bar + req.http.not;
+ }
+}
+
+client c1 -run
+
+varnish v1 -vsl_catchup -vcl+backend {
+ sub vcl_deliver {
+ set resp.http.test = req.http.test;
+
+ set resp.http.eq =
+ req.http.not + req.http.foo == req.http.bar + req.http.not;
+
+ set resp.http.neq =
+ req.http.not + req.http.foo != req.http.bar + req.http.not;
+
+ set resp.http.lt =
+ req.http.not + req.http.foo < req.http.bar + req.http.not;
+
+ set resp.http.le =
+ req.http.not + req.http.foo <= req.http.bar + req.http.not;
+
+ set resp.http.gt =
+ req.http.not + req.http.foo > req.http.bar + req.http.not;
+
+ set resp.http.ge =
+ req.http.not + req.http.foo >= req.http.bar + req.http.not;
+ }
+}
+
+client c1 -run
diff --git a/include/vrt.h b/include/vrt.h
index 0a78bd1..12e0375 100644
--- a/include/vrt.h
+++ b/include/vrt.h
@@ -61,6 +61,7 @@
* VRT_r_beresp_storage_hint() removed - under discussion #2509
* VRT_l_beresp_storage_hint() removed - under discussion #2509
* VRT_blob() added
+ * VCL_STRANDS added
* 6.1 (2017-09-15 aka 5.2)
* http_CollectHdrSep added
* VRT_purge modified (may fail a transaction, signature changed)
@@ -114,6 +115,11 @@ struct vsb;
struct vsl_log;
struct ws;
+struct strands {
+ int n;
+ const char **p;
+};
+
/***********************************************************************
* This is the central definition of the mapping from VCL types to
* C-types. The python scripts read these from here.
@@ -136,6 +142,7 @@ typedef const struct suckaddr * VCL_IP;
typedef const struct vrt_backend_probe * VCL_PROBE;
typedef double VCL_REAL;
typedef const struct stevedore * VCL_STEVEDORE;
+typedef const struct strands * VCL_STRANDS;
typedef const char * VCL_STRING;
typedef double VCL_TIME;
typedef struct vcl * VCL_VCL;
@@ -421,14 +428,19 @@ VCL_STEVEDORE VRT_stevedore(const char *nm);
/* Convert things to string */
-char *VRT_IP_string(VRT_CTX, VCL_IP);
-char *VRT_INT_string(VRT_CTX, VCL_INT);
-char *VRT_REAL_string(VRT_CTX, VCL_REAL);
-char *VRT_TIME_string(VRT_CTX, VCL_TIME);
-const char *VRT_BOOL_string(VCL_BOOL);
-const char *VRT_BACKEND_string(VCL_BACKEND);
-const char *VRT_STEVEDORE_string(VCL_STEVEDORE);
-const char *VRT_CollectString(VRT_CTX, const char *p, ...);
+VCL_STRANDS VRT_BundleStrands(int, struct strands *, char const **,
+ const char *f, ...);
+int VRT_CompareStrands(VCL_STRANDS a, VCL_STRANDS b);
+
+VCL_STRING VRT_BACKEND_string(VCL_BACKEND);
+VCL_STRING VRT_BOOL_string(VCL_BOOL);
+VCL_STRING VRT_CollectString(VRT_CTX, const char *p, ...);
+VCL_STRING VRT_INT_string(VRT_CTX, VCL_INT);
+VCL_STRING VRT_IP_string(VRT_CTX, VCL_IP);
+VCL_STRING VRT_REAL_string(VRT_CTX, VCL_REAL);
+VCL_STRING VRT_STEVEDORE_string(VCL_STEVEDORE);
+VCL_STRING VRT_STRANDS_string(VCL_STRANDS);
+VCL_STRING VRT_TIME_string(VRT_CTX, VCL_TIME);
#ifdef va_start // XXX: hackish
void *VRT_VSC_Alloc(const char *, size_t, size_t, const unsigned char *, size_t,
diff --git a/lib/libvcc/vcc_expr.c b/lib/libvcc/vcc_expr.c
index 7ad4bb0..742ca21 100644
--- a/lib/libvcc/vcc_expr.c
+++ b/lib/libvcc/vcc_expr.c
@@ -129,6 +129,8 @@ vcc_delete_expr(struct expr *e)
* \v1 insert subexpression 1
* \v2 insert subexpression 2
* \vS insert subexpression 1(STRINGS) as STRING
+ * \vT insert subexpression 1(STRINGS) as STRANDS
+ * \vt insert subexpression 1(STRINGS) as STRANDS
* \v+ increase indentation
* \v- decrease indentation
* anything else is literal
@@ -140,10 +142,10 @@ vcc_delete_expr(struct expr *e)
*/
static struct expr *
-vcc_expr_edit(vcc_type_t fmt, const char *p, struct expr *e1,
+vcc_expr_edit(struct vcc *tl, vcc_type_t fmt, const char *p, struct expr *e1,
struct expr *e2)
{
- struct expr *e;
+ struct expr *e, *e3;
int nl = 1;
AN(e1);
@@ -161,15 +163,33 @@ vcc_expr_edit(vcc_type_t fmt, const char *p, struct expr *e1,
case '+': VSB_cat(e->vsb, "\v+"); break;
case '-': VSB_cat(e->vsb, "\v-"); break;
case 'S':
+ case 's':
+ e3 = (*p == 'S' ? e1 : e2);
+ AN(e3);
assert(e1->fmt == STRINGS);
- if (e1->nstr > 1)
+ if (e3->nstr > 1)
VSB_cat(e->vsb,
"\nVRT_CollectString(ctx,\v+\n");
- VSB_cat(e->vsb, VSB_data(e1->vsb));
- if (e1->nstr > 1)
+ VSB_cat(e->vsb, VSB_data(e3->vsb));
+ if (e3->nstr > 1)
VSB_cat(e->vsb,
",\nvrt_magic_string_end)\v-\n");
break;
+ case 'T':
+ case 't':
+ e3 = (*p == 'T' ? e1 : e2);
+ AN(e3);
+ VSB_printf(tl->curproc->prologue,
+ " struct strands strs_%u_a;\n"
+ " const char * strs_%u_s[%d];\n",
+ tl->unique, tl->unique, e3->nstr);
+ VSB_printf(e->vsb,
+ "\v+\nVRT_BundleStrands(%d, &strs_%u_a, strs_%u_s,"
+ "\v+\n%s,\nvrt_magic_string_end)\v-\v-",
+ e3->nstr, tl->unique, tl->unique,
+ VSB_data(e3->vsb));
+ tl->unique++;
+ break;
case '1':
VSB_cat(e->vsb, VSB_data(e1->vsb));
break;
@@ -208,7 +228,7 @@ vcc_expr_fmt(struct vsb *d, int ind, const struct expr *e1)
while (*p != '\0') {
if (*p == '\n') {
VSB_putc(d, '\n');
- if (++p == '\0')
+ if (*++p == '\0')
break;
for (i = 0; i < ind; i++)
VSB_cat(d, " ");
@@ -241,7 +261,7 @@ vcc_expr_tostring(struct vcc *tl, struct expr **e, vcc_type_t fmt)
p = (*e)->fmt->tostring;
if (p != NULL) {
AN(*p);
- *e = vcc_expr_edit(fmt, p, *e, NULL);
+ *e = vcc_expr_edit(tl, fmt, p, *e, NULL);
(*e)->constant = constant;
(*e)->nstr = 1;
} else {
@@ -279,11 +299,11 @@ vcc_Eval_Regsub(struct vcc *tl, struct expr **e, const struct symbol *sym,
ExpectErr(tl, CSTR);
p = vcc_regexp(tl);
bprintf(buf, "VRT_regsub(ctx, %d,\v+\n\v1,\n%s", all, p);
- *e = vcc_expr_edit(STRING, buf, e2, NULL);
+ *e = vcc_expr_edit(tl, STRING, buf, e2, NULL);
SkipToken(tl, ',');
vcc_expr0(tl, &e2, STRING);
ERRCHK(tl);
- *e = vcc_expr_edit(STRINGS, "\v1,\n\v2)\v-", *e, e2);
+ *e = vcc_expr_edit(tl, STRINGS, "\v1,\n\v2)\v-", *e, e2);
(*e)->nstr = 1;
SkipToken(tl, ')');
}
@@ -545,7 +565,7 @@ vcc_func(struct vcc *tl, struct expr **e, const char *spec,
if (fa->result == NULL && fa->val != NULL)
fa->result = vcc_mk_expr(fa->type, "%s", fa->val);
if (fa->result != NULL)
- e1 = vcc_expr_edit(e1->fmt, "\v1,\n\v2",
+ e1 = vcc_expr_edit(tl, e1->fmt, "\v1,\n\v2",
e1, fa->result);
else {
VSB_printf(tl->sb, "Argument '%s' missing\n",
@@ -554,7 +574,7 @@ vcc_func(struct vcc *tl, struct expr **e, const char *spec,
}
free(fa);
}
- *e = vcc_expr_edit(e1->fmt, "\v1\n)\v-", e1, NULL);
+ *e = vcc_expr_edit(tl, e1->fmt, "\v1\n)\v-", e1, NULL);
SkipToken(tl, ')');
}
@@ -625,7 +645,7 @@ vcc_expr4(struct vcc *tl, struct expr **e, vcc_type_t fmt)
if (e2->fmt == STRINGS)
*e = e2;
else
- *e = vcc_expr_edit(e2->fmt, "(\v1)", e2, NULL);
+ *e = vcc_expr_edit(tl, e2->fmt, "(\v1)", e2, NULL);
return;
}
switch (tl->t->tok) {
@@ -780,9 +800,9 @@ vcc_expr_mul(struct vcc *tl, struct expr **e, vcc_type_t fmt)
return;
}
if (tk->tok == '*')
- *e = vcc_expr_edit((*e)->fmt, "(\v1*\v2)", *e, e2);
+ *e = vcc_expr_edit(tl, (*e)->fmt, "(\v1*\v2)", *e, e2);
else
- *e = vcc_expr_edit((*e)->fmt, "(\v1/\v2)", *e, e2);
+ *e = vcc_expr_edit(tl, (*e)->fmt, "(\v1/\v2)", *e, e2);
}
}
@@ -847,9 +867,9 @@ vcc_expr_add(struct vcc *tl, struct expr **e, vcc_type_t fmt)
break;
if (ap->op == '+') {
- *e = vcc_expr_edit(ap->fmt, "(\v1 + \v2)", *e, e2);
+ *e = vcc_expr_edit(tl, ap->fmt, "(\v1 + \v2)", *e, e2);
} else if (ap->op == '-') {
- *e = vcc_expr_edit(ap->fmt, "(\v1 - \v2)", *e, e2);
+ *e = vcc_expr_edit(tl, ap->fmt, "(\v1 - \v2)", *e, e2);
} else if (tk->tok == '+' &&
((*e)->fmt == STRINGS || fmt == STRINGS)) {
if ((*e)->fmt != STRINGS)
@@ -857,14 +877,14 @@ vcc_expr_add(struct vcc *tl, struct expr **e, vcc_type_t fmt)
if (e2->fmt != STRINGS)
vcc_expr_tostring(tl, &e2, STRINGS);
if (vcc_islit(*e) && vcc_isconst(e2)) {
- *e = vcc_expr_edit(STRINGS,
+ *e = vcc_expr_edit(tl, STRINGS,
"\v1\n\v2", *e, e2);
(*e)->constant = EXPR_CONST;
if (vcc_islit(e2))
(*e)->constant |= EXPR_STR_CONST;
} else {
n = (*e)->nstr + e2->nstr;
- *e = vcc_expr_edit(STRINGS,
+ *e = vcc_expr_edit(tl, STRINGS,
"\v1,\n\v2", *e, e2);
(*e)->constant = EXPR_VAR;
(*e)->nstr = n;
@@ -919,7 +939,7 @@ cmp_simple(struct vcc *tl, struct expr **e, const struct cmps *cp)
vcc_utype((*e)->fmt), PF(tk), vcc_utype(e2->fmt));
vcc_ErrWhere(tl, tk);
} else
- *e = vcc_expr_edit(BOOL, cp->emit, *e, e2);
+ *e = vcc_expr_edit(tl, BOOL, cp->emit, *e, e2);
}
static void v_matchproto_(cmp_f)
@@ -928,13 +948,13 @@ cmp_regexp(struct vcc *tl, struct expr **e, const struct cmps *cp)
char buf[128];
const char *re;
- *e = vcc_expr_edit(STRING, "\vS", *e, NULL);
+ *e = vcc_expr_edit(tl, STRING, "\vS", *e, NULL);
vcc_NextToken(tl);
ExpectErr(tl, CSTR);
re = vcc_regexp(tl);
ERRCHK(tl);
bprintf(buf, "%sVRT_re_match(ctx, \v1, %s)", cp->emit, re);
- *e = vcc_expr_edit(BOOL, buf, *e, NULL);
+ *e = vcc_expr_edit(tl, BOOL, buf, *e, NULL);
}
static void v_matchproto_(cmp_f)
@@ -949,7 +969,7 @@ cmp_acl(struct vcc *tl, struct expr **e, const struct cmps *cp)
vcc_NextToken(tl);
VCC_GlobalSymbol(sym, ACL, ACL_SYMBOL_PREFIX);
bprintf(buf, "%sVRT_acl_match(ctx, %s, \v1)", cp->emit, sym->rname);
- *e = vcc_expr_edit(BOOL, buf, *e, NULL);
+ *e = vcc_expr_edit(tl, BOOL, buf, *e, NULL);
}
static void v_matchproto_(cmp_f)
@@ -957,6 +977,7 @@ cmp_string(struct vcc *tl, struct expr **e, const struct cmps *cp)
{
struct expr *e2;
struct token *tk;
+ char buf[128];
tk = tl->t;
vcc_NextToken(tl);
@@ -967,10 +988,12 @@ cmp_string(struct vcc *tl, struct expr **e, const struct cmps *cp)
"Comparison of different types: %s '%.*s' %s\n",
vcc_utype((*e)->fmt), PF(tk), vcc_utype(e2->fmt));
vcc_ErrWhere(tl, tk);
+ } else if ((*e)->nstr == 1 && e2->nstr == 1) {
+ bprintf(buf, "(%s VRT_strcmp(\v1, \v2))", cp->emit);
+ *e = vcc_expr_edit(tl, BOOL, buf, *e, e2);
} else {
- *e = vcc_expr_edit(STRING, "\vS", *e, NULL);
- e2 = vcc_expr_edit(STRING, "\vS", e2, NULL);
- *e = vcc_expr_edit(BOOL, cp->emit, *e, e2);
+ bprintf(buf, "(%s VRT_CompareStrands(\vT, \vt))", cp->emit);
+ *e = vcc_expr_edit(tl, BOOL, buf, *e, e2);
}
}
@@ -1004,8 +1027,12 @@ static const struct cmps vcc_cmps[] = {
{IP, '~', cmp_acl, "" },
{IP, T_NOMATCH, cmp_acl, "!" },
- {STRINGS, T_EQ, cmp_string, "!VRT_strcmp(\v1, \v2)" },
- {STRINGS, T_NEQ, cmp_string, "VRT_strcmp(\v1, \v2)" },
+ {STRINGS, T_EQ, cmp_string, "0 =="},
+ {STRINGS, T_NEQ, cmp_string, "0 !="},
+ {STRINGS, '<', cmp_string, "0 > "},
+ {STRINGS, '>', cmp_string, "0 < "},
+ {STRINGS, T_LEQ, cmp_string, "0 >="},
+ {STRINGS, T_GEQ, cmp_string, "0 <="},
{STRINGS, '~', cmp_regexp, "" },
{STRINGS, T_NOMATCH, cmp_regexp, "!" },
@@ -1057,11 +1084,11 @@ vcc_expr_cmp(struct vcc *tl, struct expr **e, vcc_type_t fmt)
if (fmt != BOOL)
return;
if ((*e)->fmt == BACKEND || (*e)->fmt == INT)
- *e = vcc_expr_edit(BOOL, "(\v1 != 0)", *e, NULL);
+ *e = vcc_expr_edit(tl, BOOL, "(\v1 != 0)", *e, NULL);
else if ((*e)->fmt == DURATION)
- *e = vcc_expr_edit(BOOL, "(\v1 > 0)", *e, NULL);
+ *e = vcc_expr_edit(tl, BOOL, "(\v1 > 0)", *e, NULL);
else if ((*e)->fmt == STRINGS)
- *e = vcc_expr_edit(BOOL, "(\vS != 0)", *e, NULL);
+ *e = vcc_expr_edit(tl, BOOL, "(\vS != 0)", *e, NULL);
else
INCOMPL();
}
@@ -1093,7 +1120,7 @@ vcc_expr_not(struct vcc *tl, struct expr **e, vcc_type_t fmt)
VSB_printf(tl->sb, "%s.\n", vcc_utype(e2->fmt));
vcc_ErrWhere2(tl, tk, tl->t);
} else {
- *e = vcc_expr_edit(BOOL, "!(\v1)", e2, NULL);
+ *e = vcc_expr_edit(tl, BOOL, "!(\v1)", e2, NULL);
}
}
@@ -1114,7 +1141,7 @@ vcc_expr_cand(struct vcc *tl, struct expr **e, vcc_type_t fmt)
ERRCHK(tl);
if ((*e)->fmt != BOOL || tl->t->tok != T_CAND)
return;
- *e = vcc_expr_edit(BOOL, "(\v+\n\v1", *e, NULL);
+ *e = vcc_expr_edit(tl, BOOL, "(\v+\n\v1", *e, NULL);
while (tl->t->tok == T_CAND) {
vcc_NextToken(tl);
tk = tl->t;
@@ -1127,9 +1154,9 @@ vcc_expr_cand(struct vcc *tl, struct expr **e, vcc_type_t fmt)
vcc_ErrWhere2(tl, tk, tl->t);
return;
}
- *e = vcc_expr_edit(BOOL, "\v1\v-\n&&\v+\n\v2", *e, e2);
+ *e = vcc_expr_edit(tl, BOOL, "\v1\v-\n&&\v+\n\v2", *e, e2);
}
- *e = vcc_expr_edit(BOOL, "\v1\v-\n)", *e, NULL);
+ *e = vcc_expr_edit(tl, BOOL, "\v1\v-\n)", *e, NULL);
}
/*--------------------------------------------------------------------
@@ -1149,7 +1176,7 @@ vcc_expr_cor(struct vcc *tl, struct expr **e, vcc_type_t fmt)
ERRCHK(tl);
if ((*e)->fmt != BOOL || tl->t->tok != T_COR)
return;
- *e = vcc_expr_edit(BOOL, "(\v+\n\v1", *e, NULL);
+ *e = vcc_expr_edit(tl, BOOL, "(\v+\n\v1", *e, NULL);
while (tl->t->tok == T_COR) {
vcc_NextToken(tl);
tk = tl->t;
@@ -1162,9 +1189,9 @@ vcc_expr_cor(struct vcc *tl, struct expr **e, vcc_type_t fmt)
vcc_ErrWhere2(tl, tk, tl->t);
return;
}
- *e = vcc_expr_edit(BOOL, "\v1\v-\n||\v+\n\v2", *e, e2);
+ *e = vcc_expr_edit(tl, BOOL, "\v1\v-\n||\v+\n\v2", *e, e2);
}
- *e = vcc_expr_edit(BOOL, "\v1\v-\n)", *e, NULL);
+ *e = vcc_expr_edit(tl, BOOL, "\v1\v-\n)", *e, NULL);
}
/*--------------------------------------------------------------------
@@ -1191,12 +1218,15 @@ vcc_expr0(struct vcc *tl, struct expr **e, vcc_type_t fmt)
if ((*e)->fmt == STRINGS && fmt == STRING_LIST)
(*e)->fmt = STRING_LIST;
else if ((*e)->fmt == STRINGS && fmt == STRING)
- *e = vcc_expr_edit(STRING, "\vS", *e, NULL);
- else if ((*e)->fmt != STRINGS && (fmt == STRING || fmt == STRING_LIST))
+ *e = vcc_expr_edit(tl, STRING, "\vS", *e, NULL);
+ else if ((*e)->fmt == STRINGS && fmt == STRANDS) {
+ *e = vcc_expr_edit(tl, STRANDS, "\vT", (*e), NULL);
+ } else if ((*e)->fmt != STRINGS &&
+ (fmt == STRING || fmt == STRING_LIST))
vcc_expr_tostring(tl, e, fmt);
if ((*e)->fmt == STRING_LIST)
- *e = vcc_expr_edit(STRING_LIST,
+ *e = vcc_expr_edit(tl, STRING_LIST,
"\v+\n\v1,\nvrt_magic_string_end\v-", *e, NULL);
if (fmt != (*e)->fmt) {
diff --git a/lib/libvcc/vcc_types.c b/lib/libvcc/vcc_types.c
index cb446c8..dbeaacb 100644
--- a/lib/libvcc/vcc_types.c
+++ b/lib/libvcc/vcc_types.c
@@ -131,7 +131,11 @@ const struct type STEVEDORE[1] = {{
const struct type STRING[1] = {{
.magic = TYPE_MAGIC,
.name = "STRING",
- .tostring = "",
+}};
+
+const struct type STRANDS[1] = {{
+ .magic = TYPE_MAGIC,
+ .name = "STRANDS",
}};
const struct type STRINGS[1] = {{
More information about the varnish-commit
mailing list