Commit 9cc56b49 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

The new string concatenation syntax is STRING + STRING + STRING [...]

For now we assemble the string in the worker threads workspace.

I will reintroduce the optimization to pass it to VRT uncollected
where appropriate, once I get the new expression system pushed through.

Add a hacked up "regsub" function call for now, once functions gets
introduced it should be treated like any other function.

Add "true", "false" BOOL constants, REAL constants

Move the "set" statement over to the new expressions.

Fix testcases to use new string concat syntax where applicable.

"set req.url = 1;" was impossible before, now it works.


git-svn-id: http://www.varnish-cache.org/svn/trunk/varnish-cache@5131 d4fa192b-c00b-0410-8231-f00ffab90ce4
parent 9299780d
...@@ -143,13 +143,13 @@ VRT_GetHdr(const struct sess *sp, enum gethdr_e where, const char *n) ...@@ -143,13 +143,13 @@ VRT_GetHdr(const struct sess *sp, enum gethdr_e where, const char *n)
/*lint -e{818} ap,hp could be const */ /*lint -e{818} ap,hp could be const */
static char * static char *
vrt_assemble_string(struct http *hp, const char *h, const char *p, va_list ap) vrt_build_string(struct ws *ws, const char *h, const char *p, va_list ap)
{ {
char *b, *e; char *b, *e;
unsigned u, x; unsigned u, x;
u = WS_Reserve(hp->ws, 0); u = WS_Reserve(ws, 0);
e = b = hp->ws->f; e = b = ws->f;
e += u; e += u;
if (h != NULL) { if (h != NULL) {
x = strlen(h); x = strlen(h);
...@@ -173,16 +173,45 @@ vrt_assemble_string(struct http *hp, const char *h, const char *p, va_list ap) ...@@ -173,16 +173,45 @@ vrt_assemble_string(struct http *hp, const char *h, const char *p, va_list ap)
*b = '\0'; *b = '\0';
b++; b++;
if (b > e) { if (b > e) {
WS_Release(hp->ws, 0); WS_Release(ws, 0);
return (NULL); return (NULL);
} else { } else {
e = b; e = b;
b = hp->ws->f; b = ws->f;
WS_Release(hp->ws, e - b); WS_Release(ws, e - b);
return (b); return (b);
} }
} }
/*--------------------------------------------------------------------
* XXX: Optimize the single element case ?
*/
/*lint -e{818} ap,hp could be const */
static char *
vrt_assemble_string(struct http *hp, const char *h, const char *p, va_list ap)
{
return (vrt_build_string(hp->ws, h, p, ap));
}
/*--------------------------------------------------------------------
* Build a string on the worker threads workspace
*/
const char *
VRT_String(const struct sess *sp, const char *p, ...)
{
va_list ap;
char *b;
CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
va_start(ap, p);
b = vrt_build_string(sp->wrk->ws, NULL, p, ap);
va_end(ap);
return (b);
}
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
void void
...@@ -892,12 +921,14 @@ VRT_time_string(const struct sess *sp, double t) ...@@ -892,12 +921,14 @@ VRT_time_string(const struct sess *sp, double t)
} }
const char * const char *
VRT_backend_string(struct sess *sp) VRT_backend_string(struct sess *sp, const struct director *d)
{ {
CHECK_OBJ_NOTNULL(sp, SESS_MAGIC); CHECK_OBJ_NOTNULL(sp, SESS_MAGIC);
if (sp->director == NULL) if (d == NULL)
d = sp->director;
if (d == NULL)
return (NULL); return (NULL);
return (sp->director->vcl_name); return (d->vcl_name);
} }
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
......
...@@ -43,7 +43,7 @@ sub vcl_recv { ...@@ -43,7 +43,7 @@ sub vcl_recv {
if (req.restarts == 0) { if (req.restarts == 0) {
if (req.http.x-forwarded-for) { if (req.http.x-forwarded-for) {
set req.http.X-Forwarded-For = set req.http.X-Forwarded-For =
req.http.X-Forwarded-For ", " client.ip; req.http.X-Forwarded-For + ", " + client.ip;
} else { } else {
set req.http.X-Forwarded-For = client.ip; set req.http.X-Forwarded-For = client.ip;
} }
......
...@@ -13,8 +13,8 @@ server s1 { ...@@ -13,8 +13,8 @@ server s1 {
varnish v1 -vcl+backend { varnish v1 -vcl+backend {
sub vcl_fetch { sub vcl_fetch {
set beresp.http.Snafu1 = set beresp.http.Snafu1 =
"zoom" "zoom" +
regsub(beresp.http.Foomble, "ar", "\0\0") regsub(beresp.http.Foomble, "ar", "\0\0") +
"box"; "box";
} }
} -start } -start
......
...@@ -24,37 +24,37 @@ varnish v1 -arg "-p sess_workspace=1024" -vcl+backend { ...@@ -24,37 +24,37 @@ varnish v1 -arg "-p sess_workspace=1024" -vcl+backend {
sub vcl_recv { sub vcl_recv {
set req.http.foo = set req.http.foo =
req.http.bar req.http.bar +
"0123456789abcdef" "0123456789abcdef" "0123456789abcdef" + "0123456789abcdef" +
"0123456789abcdef" "0123456789abcdef" "0123456789abcdef" + "0123456789abcdef" +
"0123456789abcdef" "0123456789abcdef" "0123456789abcdef" + "0123456789abcdef" +
"0123456789abcdef" "0123456789abcdef" "0123456789abcdef" + "0123456789abcdef" +
"0123456789abcdef" "0123456789abcdef" "0123456789abcdef" + "0123456789abcdef" +
"0123456789abcdef" "0123456789abcdef" "0123456789abcdef" + "0123456789abcdef" +
"0123456789abcdef" "0123456789abcdef" "0123456789abcdef" + "0123456789abcdef" +
"0123456789abcdef" "0123456789abcdef" "0123456789abcdef" + "0123456789abcdef" +
"0123456789abcdef" "0123456789abcdef" "0123456789abcdef" + "0123456789abcdef" +
"0123456789abcdef" "0123456789abcdef" "0123456789abcdef" + "0123456789abcdef" +
"0123456789abcdef" "0123456789abcdef" "0123456789abcdef" + "0123456789abcdef" +
"0123456789abcdef" "0123456789abcdef" "0123456789abcdef" + "0123456789abcdef" +
"0123456789abcdef" "0123456789abcdef" "0123456789abcdef" + "0123456789abcdef" +
"0123456789abcdef" "0123456789abcdef" "0123456789abcdef" + "0123456789abcdef" +
"0123456789abcdef" "0123456789abcdef" "0123456789abcdef" + "0123456789abcdef" +
"0123456789abcdef" "0123456789abcdef" "0123456789abcdef" + "0123456789abcdef" +
"0123456789abcdef" "0123456789abcdef" "0123456789abcdef" + "0123456789abcdef" +
"0123456789abcdef" "0123456789abcdef" "0123456789abcdef" + "0123456789abcdef" +
"0123456789abcdef" "0123456789abcdef" "0123456789abcdef" + "0123456789abcdef" +
"0123456789abcdef" "0123456789abcdef" "0123456789abcdef" + "0123456789abcdef" +
"0123456789abcdef" "0123456789abcdef" "0123456789abcdef" + "0123456789abcdef" +
"0123456789abcdef" "0123456789abcdef" "0123456789abcdef" + "0123456789abcdef" +
"0123456789abcdef" "0123456789abcdef" "0123456789abcdef" + "0123456789abcdef" +
"0123456789abcdef" "0123456789abcdef" "0123456789abcdef" + "0123456789abcdef" +
"0123456789abcdef" "0123456789abcdef" "0123456789abcdef" + "0123456789abcdef" +
"0123456789abcdef" "0123456789abcdef" "0123456789abcdef" + "0123456789abcdef" +
"0123456789abcdef" "0123456789abcdef" "0123456789abcdef" + "0123456789abcdef" +
"0123456789abcdef" "0123456789abcdef" "0123456789abcdef" + "0123456789abcdef" +
"0123456789abcdef" "0123456789abcdef" "0123456789abcdef" + "0123456789abcdef" +
"0123456789abcdef" "0123456789abcdef" +
"01234567"; "01234567";
set req.http.baz = "BAZ"; set req.http.baz = "BAZ";
return (pass); return (pass);
......
...@@ -13,8 +13,8 @@ server s1 -start ...@@ -13,8 +13,8 @@ server s1 -start
varnish v1 -vcl+backend { varnish v1 -vcl+backend {
sub vcl_recv { sub vcl_recv {
set req.http.foobar = set req.http.foobar =
req.url req.url +
req.request req.request +
req.proto; req.proto;
set req.url = "/"; set req.url = "/";
set req.proto = "HTTP/1.2"; set req.proto = "HTTP/1.2";
...@@ -22,7 +22,7 @@ varnish v1 -vcl+backend { ...@@ -22,7 +22,7 @@ varnish v1 -vcl+backend {
} }
sub vcl_miss { sub vcl_miss {
set bereq.http.foobar = set bereq.http.foobar =
bereq.url bereq.url +
bereq.proto; bereq.proto;
set bereq.url = "/"; set bereq.url = "/";
set bereq.proto = "HTTP/1.2"; set bereq.proto = "HTTP/1.2";
...@@ -30,7 +30,7 @@ varnish v1 -vcl+backend { ...@@ -30,7 +30,7 @@ varnish v1 -vcl+backend {
} }
sub vcl_fetch { sub vcl_fetch {
set beresp.http.foobar = set beresp.http.foobar =
beresp.proto beresp.response beresp.status; beresp.proto + beresp.response + beresp.status;
set beresp.proto = "HTTP/1.2"; set beresp.proto = "HTTP/1.2";
set beresp.response = "For circular files"; set beresp.response = "For circular files";
set beresp.status = 903; set beresp.status = 903;
...@@ -42,9 +42,7 @@ varnish v1 -vcl+backend { ...@@ -42,9 +42,7 @@ varnish v1 -vcl+backend {
# XXX should be moved to it's own test # XXX should be moved to it's own test
set resp.http.x-served-by-hostname = server.hostname; set resp.http.x-served-by-hostname = server.hostname;
set resp.http.x-served-by-identity = server.identity; set resp.http.x-served-by-identity = server.identity;
set resp.http.foobar = set resp.http.foobar = resp.proto + resp.status;
resp.proto
resp.status;
} }
} -start } -start
......
...@@ -56,7 +56,7 @@ varnish v1 -badvcl { ...@@ -56,7 +56,7 @@ varnish v1 -badvcl {
sub vcl_hash { hash_data(req.hash); } sub vcl_hash { hash_data(req.hash); }
} }
varnish v1 -badvcl { varnish v1 -vcl {
backend b { .host = "127.0.0.1"; } backend b { .host = "127.0.0.1"; }
sub vcl_recv { set req.url = 1; } sub vcl_recv { set req.url = 1; }
} }
......
...@@ -189,10 +189,12 @@ char *VRT_IP_string(const struct sess *sp, const struct sockaddr *sa); ...@@ -189,10 +189,12 @@ char *VRT_IP_string(const struct sess *sp, const struct sockaddr *sa);
char *VRT_int_string(const struct sess *sp, int); char *VRT_int_string(const struct sess *sp, int);
char *VRT_double_string(const struct sess *sp, double); char *VRT_double_string(const struct sess *sp, double);
char *VRT_time_string(const struct sess *sp, double); char *VRT_time_string(const struct sess *sp, double);
const char *VRT_backend_string(struct sess *sp); const char *VRT_backend_string(struct sess *sp, const struct director *d);
#define VRT_done(sp, hand) \ #define VRT_done(sp, hand) \
do { \ do { \
VRT_handling(sp, hand); \ VRT_handling(sp, hand); \
return (1); \ return (1); \
} while (0) } while (0)
const char *VRT_String(const struct sess *sp, const char *p, ...);
...@@ -101,126 +101,64 @@ parse_error(struct vcc *tl) ...@@ -101,126 +101,64 @@ parse_error(struct vcc *tl)
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
#if 1 static const struct arith {
static void enum var_type type;
illegal_assignment(const struct vcc *tl, const char *type) unsigned oper;
{ enum var_type want;
} arith[] = {
vsb_printf(tl->sb, "Invalid assignment operator "); { INT, T_INCR, INT },
vcc_ErrToken(tl, tl->t); { INT, T_DECR, INT },
vsb_printf(tl->sb, { INT, T_MUL, INT },
" only '=' is legal for %s\n", type); { INT, T_DIV, INT },
} { INT, '=', INT },
#endif { INT, 0, INT },
{ TIME, T_INCR, DURATION },
{ TIME, T_DECR, DURATION },
{ TIME, T_MUL, REAL },
{ TIME, T_DIV, REAL },
{ TIME, '=', TIME },
{ TIME, 0, TIME },
{ DURATION, T_INCR, DURATION },
{ DURATION, T_DECR, DURATION },
{ DURATION, T_MUL, REAL },
{ DURATION, T_DIV, REAL },
{ DURATION, '=', DURATION },
{ DURATION, 0, DURATION },
{ VOID, '=', VOID }
};
static void static void
parse_set(struct vcc *tl) parse_set(struct vcc *tl)
{ {
const struct var *vp; const struct var *vp;
struct token *vt; const struct arith *ap;
struct token *at; enum var_type fmt;
vcc_NextToken(tl); vcc_NextToken(tl);
ExpectErr(tl, ID); ExpectErr(tl, ID);
vt = tl->t;
vp = vcc_FindVar(tl, tl->t, 1, "cannot be set"); vp = vcc_FindVar(tl, tl->t, 1, "cannot be set");
ERRCHK(tl); ERRCHK(tl);
assert(vp != NULL); assert(vp != NULL);
Fb(tl, 1, "%s", vp->lname); Fb(tl, 1, "%s", vp->lname);
#if 0
vcc_NextToken(tl); vcc_NextToken(tl);
SkipToken(tl, '='); fmt = vp->fmt;
vcc_Expr(tl, vp->fmt); for (ap = arith; ap->type != VOID; ap++) {
#else if (ap->type != fmt)
vcc_NextToken(tl); continue;
switch (vp->fmt) { if (ap->oper != tl->t->tok)
case INT: continue;
case TIME: if (ap->oper != '=')
case DURATION:
if (tl->t->tok != '=')
Fb(tl, 0, "%s %c ", vp->rname, *tl->t->b); Fb(tl, 0, "%s %c ", vp->rname, *tl->t->b);
at = tl->t;
vcc_NextToken(tl);
switch (at->tok) {
case T_MUL:
case T_DIV:
Fb(tl, 0, "%g", vcc_DoubleVal(tl));
break;
case T_INCR:
case T_DECR:
case '=':
vcc_VarVal(tl, vp, vt);
ERRCHK(tl);
break;
default:
vsb_printf(tl->sb, "Invalid assignment operator.\n");
vcc_ErrWhere(tl, at);
return;
}
Fb(tl, 0, ");\n");
break;
case BACKEND:
if (tl->t->tok != '=') {
illegal_assignment(tl, "backend");
return;
}
vcc_NextToken(tl);
vcc_ExpectCid(tl);
ERRCHK(tl);
vcc_AddRef(tl, tl->t, R_BACKEND);
Fb(tl, 0, "VGCDIR(_%.*s)", PF(tl->t));
vcc_NextToken(tl);
Fb(tl, 0, ");\n");
break;
case STRING:
if (tl->t->tok != '=') {
illegal_assignment(tl, "strings");
return;
}
vcc_NextToken(tl);
if (!vcc_StringVal(tl)) {
ERRCHK(tl);
vcc_ExpectedStringval(tl);
return;
}
do
Fb(tl, 0, ", ");
while (vcc_StringVal(tl));
if (tl->t->tok != ';') {
ERRCHK(tl);
vsb_printf(tl->sb,
"Expected variable, string or semicolon\n");
vcc_ErrWhere(tl, tl->t);
return;
}
Fb(tl, 0, "vrt_magic_string_end);\n");
break;
case BOOL:
if (tl->t->tok != '=') {
illegal_assignment(tl, "boolean");
return;
}
vcc_NextToken(tl);
ExpectErr(tl, ID);
if (vcc_IdIs(tl->t, "true")) {
Fb(tl, 0, " 1);\n", vp->lname);
} else if (vcc_IdIs(tl->t, "false")) {
Fb(tl, 0, " 0);\n", vp->lname);
} else {
vsb_printf(tl->sb,
"Expected true or false\n");
vcc_ErrWhere(tl, tl->t);
return;
}
vcc_NextToken(tl); vcc_NextToken(tl);
fmt = ap->want;
break; break;
default:
vsb_printf(tl->sb,
"Assignments not possible for type of '%s'\n", vp->name);
vcc_ErrWhere(tl, tl->t);
return;
} }
#endif if (ap->type == VOID)
SkipToken(tl, ap->oper);
vcc_Expr(tl, fmt);
if (vp->fmt == STRING)
Fb(tl, 1, ", vrt_magic_string_end");
Fb(tl, 0, ");\n");
} }
/*--------------------------------------------------------------------*/ /*--------------------------------------------------------------------*/
......
...@@ -273,8 +273,10 @@ vcc_expr_edit(enum var_type fmt, const char *p, struct expr *e1, struct expr *e2 ...@@ -273,8 +273,10 @@ vcc_expr_edit(enum var_type fmt, const char *p, struct expr *e1, struct expr *e2
vsb_cat(e->vsb, "\v+\n"); vsb_cat(e->vsb, "\v+\n");
if (*p == '1') if (*p == '1')
vsb_cat(e->vsb, vsb_data(e1->vsb)); vsb_cat(e->vsb, vsb_data(e1->vsb));
else else {
AN(e2);
vsb_cat(e->vsb, vsb_data(e2->vsb)); vsb_cat(e->vsb, vsb_data(e2->vsb));
}
if (q != NULL) if (q != NULL)
vsb_cat(e->vsb, "\v-\n"); vsb_cat(e->vsb, "\v-\n");
break; break;
...@@ -326,6 +328,35 @@ vcc_expr_fmt(struct vsb *d, int ind, const struct expr *e1) ...@@ -326,6 +328,35 @@ vcc_expr_fmt(struct vsb *d, int ind, const struct expr *e1)
} }
} }
/*--------------------------------------------------------------------
*/
static void
hack_regsub(struct vcc *tl, struct expr **e, int all)
{
struct expr *e2;
char *p;
char buf[128];
SkipToken(tl, ID);
SkipToken(tl, '(');
vcc_expr0(tl, &e2, STRING);
SkipToken(tl, ',');
ExpectErr(tl, CSTR);
p = vcc_regexp(tl);
vcc_NextToken(tl);
bprintf(buf, "VRT_regsub(sp, %d,\n\v1,\n%s\n", all, p);
*e = vcc_expr_edit(STRING, buf, e2, *e);
SkipToken(tl, ',');
vcc_expr0(tl, &e2, STRING);
*e = vcc_expr_edit(STRING, "\v1, \v2)", *e, e2);
SkipToken(tl, ')');
}
/*-------------------------------------------------------------------- /*--------------------------------------------------------------------
* SYNTAX: * SYNTAX:
* Expr4: * Expr4:
...@@ -354,10 +385,42 @@ vcc_expr4(struct vcc *tl, struct expr **e, enum var_type fmt) ...@@ -354,10 +385,42 @@ vcc_expr4(struct vcc *tl, struct expr **e, enum var_type fmt)
e1 = vcc_new_expr(); e1 = vcc_new_expr();
switch(tl->t->tok) { switch(tl->t->tok) {
case ID: case ID:
if (vcc_IdIs(tl->t, "regsub")) {
vcc_delete_expr(e1);
hack_regsub(tl, e, 0);
return;
}
if (vcc_IdIs(tl->t, "regsuball")) {
vcc_delete_expr(e1);
hack_regsub(tl, e, 1);
return;
}
if (vcc_IdIs(tl->t, "true")) {
vcc_NextToken(tl);
vsb_printf(e1->vsb, "(1==1)");
e1->fmt = BOOL;
break;
}
if (vcc_IdIs(tl->t, "false")) {
vcc_NextToken(tl);
vsb_printf(e1->vsb, "(0!=0)");
e1->fmt = BOOL;
break;
}
if (fmt == BACKEND) {
vcc_ExpectCid(tl);
vcc_AddRef(tl, tl->t, R_BACKEND);
vsb_printf(e1->vsb, "VGCDIR(_%.*s)", PF(tl->t));
e1->fmt = BACKEND;
vcc_NextToken(tl);
break;
}
sym = VCC_FindSymbol(tl, tl->t); sym = VCC_FindSymbol(tl, tl->t);
if (sym == NULL) { if (sym == NULL) {
vsb_printf(tl->sb, "Symbol not found: "); vsb_printf(tl->sb, "Symbol not found: ");
vcc_ErrToken(tl, tl->t); vcc_ErrToken(tl, tl->t);
vsb_printf(tl->sb, " (expected type %s):\n",
vcc_Type(fmt));
vcc_ErrWhere(tl, tl->t); vcc_ErrWhere(tl, tl->t);
return; return;
} }
...@@ -385,6 +448,9 @@ vcc_expr4(struct vcc *tl, struct expr **e, enum var_type fmt) ...@@ -385,6 +448,9 @@ vcc_expr4(struct vcc *tl, struct expr **e, enum var_type fmt)
ERRCHK(tl); ERRCHK(tl);
vsb_printf(e1->vsb, "%g", d); vsb_printf(e1->vsb, "%g", d);
e1->fmt = DURATION; e1->fmt = DURATION;
} else if (fmt == REAL) {
vsb_printf(e1->vsb, "%g", vcc_DoubleVal(tl));
e1->fmt = REAL;
} else { } else {
vsb_printf(e1->vsb, "%.*s", PF(tl->t)); vsb_printf(e1->vsb, "%.*s", PF(tl->t));
vcc_NextToken(tl); vcc_NextToken(tl);
...@@ -422,7 +488,7 @@ vcc_expr_mul(struct vcc *tl, struct expr **e, enum var_type fmt) ...@@ -422,7 +488,7 @@ vcc_expr_mul(struct vcc *tl, struct expr **e, enum var_type fmt)
switch(f2) { switch(f2) {
case INT: f2 = INT; break; case INT: f2 = INT; break;
case DURATION: f2 = INT; break; /* XXX: should be Double */ case DURATION: f2 = REAL; break;
default: default:
return; return;
} }
...@@ -454,6 +520,19 @@ vcc_expr_add(struct vcc *tl, struct expr **e, enum var_type fmt) ...@@ -454,6 +520,19 @@ vcc_expr_add(struct vcc *tl, struct expr **e, enum var_type fmt)
ERRCHK(tl); ERRCHK(tl);
f2 = (*e)->fmt; f2 = (*e)->fmt;
if (f2 == STRING && tl->t->tok == '+') {
*e = vcc_expr_edit(STRING, "\v+VRT_String(sp,\n\v1", *e, NULL);
while (tl->t->tok == '+') {
vcc_NextToken(tl);
vcc_expr0(tl, &e2, STRING);
assert(e2->fmt == STRING);
*e = vcc_expr_edit(STRING, "\v1, \v2", *e, e2);
}
*e = vcc_expr_edit(STRING, "\v1, vrt_magic_string_end)",
*e, NULL);
return;
}
switch(f2) { switch(f2) {
case INT: break; case INT: break;
case TIME: f2 = DURATION; break; case TIME: f2 = DURATION; break;
...@@ -517,6 +596,7 @@ vcc_expr_cmp(struct vcc *tl, struct expr **e, enum var_type fmt) ...@@ -517,6 +596,7 @@ vcc_expr_cmp(struct vcc *tl, struct expr **e, enum var_type fmt)
char buf[256]; char buf[256];
char *re; char *re;
const char *not; const char *not;
const char *p;
struct token *tk; struct token *tk;
*e = NULL; *e = NULL;
...@@ -602,6 +682,20 @@ vcc_expr_cmp(struct vcc *tl, struct expr **e, enum var_type fmt) ...@@ -602,6 +682,20 @@ vcc_expr_cmp(struct vcc *tl, struct expr **e, enum var_type fmt)
break; break;
} }
} }
if (fmt == STRING) {
p = NULL;
switch((*e)->fmt) {
case BACKEND: p = "VRT_backend_string(sp, \v1)"; break;
case INT: p = "VRT_int_string(sp, \v1)"; break;
case IP: p = "VRT_IP_string(sp, \v1)"; break;
case TIME: p = "VRT_time_string(sp, \v1)"; break;
default: break;
}
if (p != NULL) {
*e = vcc_expr_edit(STRING, p, *e, NULL);
return;
}
}
if (fmt == VOID || fmt != (*e)->fmt) { if (fmt == VOID || fmt != (*e)->fmt) {
vsb_printf(tl->sb, "WANT: %s has %s next %.*s (%s)\n", vsb_printf(tl->sb, "WANT: %s has %s next %.*s (%s)\n",
vcc_Type(fmt), vcc_Type((*e)->fmt), vcc_Type(fmt), vcc_Type((*e)->fmt),
......
...@@ -185,7 +185,7 @@ vcc_StringVal(struct vcc *tl) ...@@ -185,7 +185,7 @@ vcc_StringVal(struct vcc *tl)
Fb(tl, 0, "VRT_double_string(sp, %s)", vp->rname); Fb(tl, 0, "VRT_double_string(sp, %s)", vp->rname);
break; break;
case BACKEND: case BACKEND:
Fb(tl, 0, "VRT_backend_string(sp)"); Fb(tl, 0, "VRT_backend_string(sp, NULL)");
break; break;
default: default:
vsb_printf(tl->sb, "String representation of '%s'" vsb_printf(tl->sb, "String representation of '%s'"
......
...@@ -37,3 +37,4 @@ VCC_TYPE(DURATION) ...@@ -37,3 +37,4 @@ VCC_TYPE(DURATION)
VCC_TYPE(STRING) VCC_TYPE(STRING)
VCC_TYPE(IP) VCC_TYPE(IP)
VCC_TYPE(HEADER) VCC_TYPE(HEADER)
VCC_TYPE(REAL)
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