Commit b317d959 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

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.
parent 6f6242be
......@@ -156,6 +156,64 @@ VRT_GetHdr(VRT_CTX, const struct gethdr_s *hs)
return (p);
}
/*--------------------------------------------------------------------
* 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)
{
......
......@@ -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
......
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
......@@ -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,
......
......@@ -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) {
......
......@@ -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] = {{
......
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