[master] 6f6242b Rework VCC implementation of strings.

Poul-Henning Kamp phk at FreeBSD.org
Wed Dec 13 10:45:12 UTC 2017


commit 6f6242be57227ff0646b1909ebc185cb232a6ad3
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Wed Dec 13 10:43:25 2017 +0000

    Rework VCC implementation of strings.
    
    Add a new type "STRINGS" which is internal to vcc_expr.c only,
    and convert to "STRING" and "STRING_LIST" at the edge of vcc_expr.c
    and as necessary inside.  (More to come.)
    
    Various and sundry cleanups along the way.

diff --git a/lib/libvcc/generate.py b/lib/libvcc/generate.py
index f1cb87f..398b658 100755
--- a/lib/libvcc/generate.py
+++ b/lib/libvcc/generate.py
@@ -834,7 +834,8 @@ stv_variables = (
 # VCL to C type conversion
 
 vcltypes = {
-	'STRING_LIST':	"void*",
+	'STRINGS':		"void",
+	'STRING_LIST':		"void*",
 	'SUB':			"void*",
 }
 
diff --git a/lib/libvcc/vcc_compile.h b/lib/libvcc/vcc_compile.h
index bade028..47d8525 100644
--- a/lib/libvcc/vcc_compile.h
+++ b/lib/libvcc/vcc_compile.h
@@ -39,7 +39,6 @@
 #include "vqueue.h"
 #include "vsb.h"
 
-
 #include "vcc_token_defs.h"
 
 #ifndef NULL
diff --git a/lib/libvcc/vcc_expr.c b/lib/libvcc/vcc_expr.c
index eb9a3e6..7ad4bb0 100644
--- a/lib/libvcc/vcc_expr.c
+++ b/lib/libvcc/vcc_expr.c
@@ -26,7 +26,6 @@
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- * XXX: add VRT_count()'s
  */
 
 #include "config.h"
@@ -48,7 +47,9 @@ struct expr {
 #define EXPR_CONST	(1<<1)
 #define EXPR_STR_CONST	(1<<2)		// Last STRING_LIST elem is "..."
 	struct token	*t1, *t2;
+	int		nstr;
 };
+
 /*--------------------------------------------------------------------
  * Facility for carrying expressions around and do text-processing on
  * them.
@@ -61,11 +62,18 @@ vcc_isconst(const struct expr *e)
 	return (e->constant & EXPR_CONST);
 }
 
+static inline int
+vcc_islit(const struct expr *e)
+{
+	AN(e->constant);
+	return (e->constant & EXPR_STR_CONST);
+}
+
 static const char *
 vcc_utype(vcc_type_t t)
 {
-	if (t == STRING_LIST)
-		return (STRING->name);
+	if (t == STRINGS || t == STRING_LIST)
+		t = STRING;
 	return (t->name);
 }
 
@@ -73,31 +81,25 @@ static void vcc_expr0(struct vcc *tl, struct expr **e, vcc_type_t fmt);
 static void vcc_expr_cor(struct vcc *tl, struct expr **e, vcc_type_t fmt);
 
 static struct expr *
-vcc_new_expr(void)
+vcc_new_expr(vcc_type_t fmt)
 {
 	struct expr *e;
 
-	/* XXX: use TlAlloc() ? */
 	ALLOC_OBJ(e, EXPR_MAGIC);
 	AN(e);
 	e->vsb = VSB_new_auto();
-	e->fmt = VOID;
+	e->fmt = fmt;
 	e->constant = EXPR_VAR;
 	return (e);
 }
 
-static struct expr *
-vcc_mk_expr(vcc_type_t fmt, const char *str, ...)
-    v_printflike_(2, 3);
-
-static struct expr *
+static struct expr * v_printflike_(2, 3)
 vcc_mk_expr(vcc_type_t fmt, const char *str, ...)
 {
 	va_list ap;
 	struct expr *e;
 
-	e = vcc_new_expr();
-	e->fmt = fmt;
+	e = vcc_new_expr(fmt);
 	va_start(ap, str);
 	VSB_vprintf(e->vsb, str, ap);
 	va_end(ap);
@@ -126,6 +128,7 @@ vcc_delete_expr(struct expr *e)
  * We use '\v' as the magic escape character.
  *	\v1  insert subexpression 1
  *	\v2  insert subexpression 2
+ *	\vS  insert subexpression 1(STRINGS) as STRING
  *	\v+  increase indentation
  *	\v-  decrease indentation
  *	anything else is literal
@@ -144,7 +147,7 @@ vcc_expr_edit(vcc_type_t fmt, const char *p, struct expr *e1,
 	int nl = 1;
 
 	AN(e1);
-	e = vcc_new_expr();
+	e = vcc_new_expr(fmt);
 	while (*p != '\0') {
 		if (*p != '\v') {
 			if (*p != '\n' || !nl)
@@ -157,6 +160,16 @@ vcc_expr_edit(vcc_type_t fmt, const char *p, struct expr *e1,
 		switch (*++p) {
 		case '+': VSB_cat(e->vsb, "\v+"); break;
 		case '-': VSB_cat(e->vsb, "\v-"); break;
+		case 'S':
+			assert(e1->fmt == STRINGS);
+			if (e1->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,
+				    ",\nvrt_magic_string_end)\v-\n");
+			break;
 		case '1':
 			VSB_cat(e->vsb, VSB_data(e1->vsb));
 			break;
@@ -176,7 +189,6 @@ vcc_expr_edit(vcc_type_t fmt, const char *p, struct expr *e1,
 		e->t2 = e2->t2;
 	vcc_delete_expr(e1);
 	vcc_delete_expr(e2);
-	e->fmt = fmt;
 	return (e);
 }
 
@@ -196,26 +208,20 @@ vcc_expr_fmt(struct vsb *d, int ind, const struct expr *e1)
 	while (*p != '\0') {
 		if (*p == '\n') {
 			VSB_putc(d, '\n');
-			if (p[1] != '\0') {
-				for (i = 0; i < ind; i++)
-					VSB_cat(d, " ");
+			if (++p == '\0')
+				break;
+			for (i = 0; i < ind; i++)
+				VSB_cat(d, " ");
+		} else if (*p != '\v') {
+			VSB_putc(d, *p++);
+		} else {
+			switch (*++p) {
+			case '+': ind += 2; break;
+			case '-': ind -= 2; break;
+			default:  WRONG("Illegal format in VCC expression");
 			}
 			p++;
-			continue;
-		}
-		if (*p != '\v') {
-			VSB_putc(d, *p);
-			p++;
-			continue;
 		}
-		p++;
-		switch (*p) {
-		case '+': ind += 2; break;
-		case '-': ind -= 2; break;
-		default:
-			WRONG("Illegal format in VCC expression");
-		}
-		p++;
 	}
 }
 
@@ -229,33 +235,26 @@ vcc_expr_tostring(struct vcc *tl, struct expr **e, vcc_type_t fmt)
 	uint8_t	constant = EXPR_VAR;
 
 	CHECK_OBJ_NOTNULL(*e, EXPR_MAGIC);
-	assert(fmt == STRING || fmt == STRING_LIST);
+	assert(fmt == STRINGS || fmt == STRING_LIST || fmt == STRING);
 	assert(fmt != (*e)->fmt);
 
-	if ((*e)->fmt == STRING ||
-	    ((*e)->fmt == STRING_LIST && vcc_isconst(*e))) {
-		(*e)->fmt = fmt;
-		return;
-	}
 	p = (*e)->fmt->tostring;
-	if (p == NULL && (*e)->fmt == BLOB) {
-		VSB_printf(tl->sb,
-		    "Wrong use of BLOB value.\n"
-		    "BLOBs can only be used as arguments to VMOD"
-		    " functions.\n");
-		vcc_ErrWhere2(tl, (*e)->t1, tl->t);
-		return;
-	}
-	if (p == NULL) {
-		VSB_printf(tl->sb,
-		    "Cannot convert %s to STRING.\n", vcc_utype((*e)->fmt));
-		vcc_ErrWhere2(tl, (*e)->t1, tl->t);
-		return;
-	}
-	AN(p);
-	if (*p != '\0') {
+	if (p != NULL) {
+		AN(*p);
 		*e = vcc_expr_edit(fmt, p, *e, NULL);
 		(*e)->constant = constant;
+		(*e)->nstr = 1;
+	} else {
+		if ((*e)->fmt == BLOB)
+			VSB_printf(tl->sb,
+			    "Wrong use of BLOB value.\n"
+			    "BLOBs can only be used as arguments to VMOD"
+			    " functions.\n");
+		else
+			VSB_printf(tl->sb,
+			    "Cannot convert %s to STRING.\n",
+			    vcc_utype((*e)->fmt));
+		vcc_ErrWhere2(tl, (*e)->t1, tl->t);
 	}
 }
 
@@ -272,25 +271,20 @@ vcc_Eval_Regsub(struct vcc *tl, struct expr **e, const struct symbol *sym,
 	char buf[128];
 
 	(void)fmt;
-	vcc_delete_expr(*e);
 	SkipToken(tl, ID);
 	SkipToken(tl, '(');
-
 	vcc_expr0(tl, &e2, STRING);
 	ERRCHK(tl);
-
 	SkipToken(tl, ',');
 	ExpectErr(tl, CSTR);
 	p = vcc_regexp(tl);
-	vcc_NextToken(tl);
-
 	bprintf(buf, "VRT_regsub(ctx, %d,\v+\n\v1,\n%s", all, p);
 	*e = vcc_expr_edit(STRING, buf, e2, NULL);
-
 	SkipToken(tl, ',');
 	vcc_expr0(tl, &e2, STRING);
 	ERRCHK(tl);
-	*e = vcc_expr_edit(STRING, "\v1,\n\v2)\v-", *e, e2);
+	*e = vcc_expr_edit(STRINGS, "\v1,\n\v2)\v-", *e, e2);
+	(*e)->nstr = 1;
 	SkipToken(tl, ')');
 }
 
@@ -318,14 +312,19 @@ vcc_Eval_Handle(struct vcc *tl, struct expr **e, const struct symbol *sym,
 
 	AN(sym->rname);
 
-	if (sym->fmt != STRING && (fmt == STRING || fmt == STRING_LIST)) {
-		*e = vcc_mk_expr(STRING, "\"%s\"", sym->name);
+	if (sym->fmt != STRING && fmt == STRINGS) {
 		(void)vcc_AddRef(tl, tl->t, sym->kind);
+		*e = vcc_mk_expr(STRINGS, "\"%s\"", sym->name);
+		(*e)->nstr = 1;
+		(*e)->constant |= EXPR_CONST | EXPR_STR_CONST;
 	} else {
 		vcc_ExpectVid(tl, "handle");
 		(void)vcc_AddRef(tl, tl->t, sym->kind);
 		*e = vcc_mk_expr(sym->fmt, "%s", sym->rname);
-		(*e)->constant = EXPR_VAR;	/* XXX ? */
+		(*e)->constant = EXPR_VAR;
+		(*e)->nstr = 1;
+		if ((*e)->fmt == STRING)
+			(*e)->fmt = STRINGS;
 	}
 	vcc_NextToken(tl);
 }
@@ -343,6 +342,10 @@ vcc_Eval_Var(struct vcc *tl, struct expr **e, const struct symbol *sym,
 	vcc_AddUses(tl, tl->t, sym->r_methods, "Not available");
 	ERRCHK(tl);
 	*e = vcc_mk_expr(sym->fmt, "%s", sym->rname);
+	(*e)->constant = EXPR_VAR;
+	(*e)->nstr = 1;
+	if ((*e)->fmt == STRING)
+		(*e)->fmt = STRINGS;
 	vcc_NextToken(tl);
 }
 
@@ -551,11 +554,8 @@ vcc_func(struct vcc *tl, struct expr **e, const char *spec,
 		}
 		free(fa);
 	}
-	e1 = vcc_expr_edit(e1->fmt, "\v1\n)\v-", e1, NULL);
-	*e = e1;
-
+	*e = vcc_expr_edit(e1->fmt, "\v1\n)\v-", e1, NULL);
 	SkipToken(tl, ')');
-
 }
 
 /*--------------------------------------------------------------------
@@ -589,6 +589,11 @@ vcc_Eval_SymFunc(struct vcc *tl, struct expr **e, const struct symbol *sym,
 	SkipToken(tl, ID);
 	assert(sym->fmt == VCC_Type(sym->eval_priv));
 	vcc_func(tl, e, sym->eval_priv, sym->extra, sym);
+	ERRCHK(tl);
+	if ((*e)->fmt == STRING) {
+		(*e)->fmt = STRINGS;
+		(*e)->nstr = 1;
+	}
 }
 
 /*--------------------------------------------------------------------
@@ -617,13 +622,10 @@ vcc_expr4(struct vcc *tl, struct expr **e, vcc_type_t fmt)
 		vcc_expr_cor(tl, &e2, fmt);
 		ERRCHK(tl);
 		SkipToken(tl, ')');
-		if (e2->fmt == STRING_LIST) {
+		if (e2->fmt == STRINGS)
 			*e = e2;
-			if (fmt == STRING)
-				vcc_expr_tostring(tl, e, STRING);
-		} else {
+		else
 			*e = vcc_expr_edit(e2->fmt, "(\v1)", e2, NULL);
-		}
 		return;
 	}
 	switch (tl->t->tok) {
@@ -665,7 +667,7 @@ vcc_expr4(struct vcc *tl, struct expr **e, vcc_type_t fmt)
 			ERRCHK(tl);
 			/* Unless asked for a HEADER, fold to string here */
 			if (*e && fmt != HEADER && (*e)->fmt == HEADER) {
-				vcc_expr_tostring(tl, e, STRING);
+				vcc_expr_tostring(tl, e, STRINGS);
 				ERRCHK(tl);
 			}
 			return;
@@ -687,13 +689,11 @@ vcc_expr4(struct vcc *tl, struct expr **e, vcc_type_t fmt)
 			e1 = vcc_mk_expr(IP, "%s", ip);
 			ERRCHK(tl);
 		} else {
-			e1 = vcc_new_expr();
+			e1 = vcc_new_expr(STRINGS);
 			EncToken(e1->vsb, tl->t);
-			e1->fmt = STRING;
 			AZ(VSB_finish(e1->vsb));
 			e1->constant |= EXPR_STR_CONST;
-			if (fmt == STRING_LIST)
-				e1->fmt = fmt;
+			e1->nstr = 1;
 		}
 		e1->t1 = tl->t;
 		e1->constant |= EXPR_CONST;
@@ -774,9 +774,8 @@ vcc_expr_mul(struct vcc *tl, struct expr **e, vcc_type_t fmt)
 		vcc_expr4(tl, &e2, f2);
 		ERRCHK(tl);
 		if (e2->fmt != INT && e2->fmt != f2) {
-			VSB_printf(tl->sb,
-			    "%s %.*s %s not possible.\n",
-			    vcc_utype(f2), PF(tk), vcc_utype(e2->fmt));
+			VSB_printf(tl->sb, "%s %.*s %s not possible.\n",
+			    vcc_utype((*e)->fmt), PF(tk), vcc_utype(e2->fmt));
 			vcc_ErrWhere(tl, tk);
 			return;
 		}
@@ -791,45 +790,8 @@ vcc_expr_mul(struct vcc *tl, struct expr **e, vcc_type_t fmt)
  * SYNTAX:
  *    ExprAdd:
  *      ExprMul { {'+'|'-'} ExprMul } *
- *
- * For reasons of memory allocation/copying and general performance,
- * STRINGs in VCL are quite special.   Addition/concatenation is split
- * into it's own subfunction to encapsulate this.
  */
 
-static void
-vcc_expr_string_add(struct vcc *tl, struct expr **e, struct expr *e2)
-{
-	vcc_type_t f2;
-
-	AN(e);
-	AN(*e);
-	AN(e2);
-	f2 = (*e)->fmt;
-	assert (f2 == STRING || f2 == STRING_LIST);
-
-	while (e2 != NULL || tl->t->tok == '+') {
-		if (e2 == NULL) {
-			vcc_NextToken(tl);
-			vcc_expr_mul(tl, &e2, f2);
-		}
-		ERRCHK(tl);
-		if (e2->fmt != STRING && e2->fmt != STRING_LIST)
-			vcc_expr_tostring(tl, &e2, f2);
-		ERRCHK(tl);
-		assert(e2->fmt == STRING || e2->fmt == STRING_LIST);
-
-		if (((*e)->constant & EXPR_STR_CONST) && vcc_isconst(e2)) {
-			*e = vcc_expr_edit((*e)->fmt, "\v1\n\v2", *e, e2);
-			(*e)->constant = EXPR_CONST | EXPR_STR_CONST;
-		} else {
-			*e = vcc_expr_edit(STRING_LIST, "\v1,\n\v2", *e, e2);
-			(*e)->constant = EXPR_VAR;
-		}
-		e2 = NULL;
-	}
-}
-
 static const struct adds {
 	unsigned	op;
 	vcc_type_t	a;
@@ -852,7 +814,7 @@ static const struct adds {
 	{ '+', TIME,		DURATION,	TIME },
 	{ '-', TIME,		DURATION,	TIME },
 
-	{ EOI, VOID, VOID, VOID }
+	{ EOI, VOID,		VOID,		VOID }
 };
 
 static void
@@ -860,66 +822,59 @@ vcc_expr_add(struct vcc *tl, struct expr **e, vcc_type_t fmt)
 {
 	const struct adds *ap;
 	struct expr  *e2;
-	vcc_type_t f2;
 	struct token *tk;
-	char buf[128];
+	int n;
 
 	*e = NULL;
 	vcc_expr_mul(tl, e, fmt);
 	ERRCHK(tl);
 
-	if (tl->t->tok != '+' && tl->t->tok != '-')
-		return;
-
-	f2 = (*e)->fmt;
-	for (ap = vcc_adds; ap->op != EOI; ap++)
-		if (ap->a == f2 && ap->op == tl->t->tok)
-			break;
-
-	if (ap->op == EOI &&
-	    (fmt == STRING || fmt == STRING_LIST) &&
-	    f2 != STRING && f2 != STRING_LIST) {
-		vcc_expr_tostring(tl, e, fmt);
-		f2 = (*e)->fmt;
-	}
-
 	while (tl->t->tok == '+' || tl->t->tok == '-') {
 		tk = tl->t;
+		for (ap = vcc_adds; ap->op != EOI; ap++)
+			if (tk->tok == ap->op && (*e)->fmt == ap->a)
+				break;
 		vcc_NextToken(tl);
-		vcc_expr_mul(tl, &e2, f2);
+		if (ap->op == EOI && fmt == STRINGS)
+			vcc_expr_mul(tl, &e2, STRINGS);
+		else
+			vcc_expr_mul(tl, &e2, (*e)->fmt);
 		ERRCHK(tl);
 
-		for (ap = vcc_adds; ap->op != EOI; ap++) {
+		for (ap = vcc_adds; ap->op != EOI; ap++)
 			if (tk->tok == ap->op && (*e)->fmt == ap->a &&
 			    e2->fmt == ap->b)
 				break;
-		}
 
-		if (ap->fmt != VOID) {
-			bprintf(buf, "(\v1 %c \v2)", ap->op);
-			*e = vcc_expr_edit(ap->fmt, buf, *e, e2);
-			continue;
-		}
-
-		if (tk->tok == '+' && ap->op == EOI) {
-			if ((*e)->fmt == STRING && e2->fmt == STRING) {
-				vcc_expr_string_add(tl, e, e2);
-				return;
-			}
-
-			if (fmt == STRING || fmt == STRING_LIST) {
-				/* Time to fold and add as string */
-				if ((*e)->fmt != fmt)
-					vcc_expr_tostring(tl, e, fmt);
-				vcc_expr_string_add(tl, e, e2);
-				return;
+		if (ap->op == '+') {
+			*e = vcc_expr_edit(ap->fmt, "(\v1 + \v2)", *e, e2);
+		} else if (ap->op == '-') {
+			*e = vcc_expr_edit(ap->fmt, "(\v1 - \v2)", *e, e2);
+		} else if (tk->tok == '+' &&
+		    ((*e)->fmt == STRINGS || fmt == STRINGS)) {
+			if ((*e)->fmt != STRINGS)
+				vcc_expr_tostring(tl, e, STRINGS);
+			if (e2->fmt != STRINGS)
+				vcc_expr_tostring(tl, &e2, STRINGS);
+			if (vcc_islit(*e) && vcc_isconst(e2)) {
+				*e = vcc_expr_edit(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,
+				    "\v1,\n\v2", *e, e2);
+				(*e)->constant = EXPR_VAR;
+				(*e)->nstr = n;
 			}
+		} else {
+			VSB_printf(tl->sb, "%s %.*s %s not possible.\n",
+			    vcc_utype((*e)->fmt), PF(tk), vcc_utype(e2->fmt));
+			vcc_ErrWhere2(tl, tk, tl->t);
+			return;
 		}
-
-		VSB_printf(tl->sb, "%s %.*s %s not possible.\n",
-		    vcc_utype((*e)->fmt), PF(tk), vcc_utype(e2->fmt));
-		vcc_ErrWhere2(tl, tk, tl->t);
-		return;
 	}
 }
 
@@ -955,22 +910,16 @@ cmp_simple(struct vcc *tl, struct expr **e, const struct cmps *cp)
 
 	tk = tl->t;
 	vcc_NextToken(tl);
-	if ((*e)->fmt == STRING_LIST)
-		vcc_expr_tostring(tl, e, STRING);
 	vcc_expr_add(tl, &e2, (*e)->fmt);
 	ERRCHK(tl);
-	if (e2->fmt == STRING_LIST)
-		vcc_expr_tostring(tl, &e2, STRING);
-
-	if (e2->fmt != (*e)->fmt) { /* XXX */
-		VSB_printf(tl->sb, "Comparison of different types: ");
-		VSB_printf(tl->sb, "%s ", vcc_utype((*e)->fmt));
-		vcc_ErrToken(tl, tk);
-		VSB_printf(tl->sb, " %s\n", vcc_utype(e2->fmt));
+
+	if (e2->fmt != (*e)->fmt) {
+		VSB_printf(tl->sb,
+		    "Comparison of different types: %s '%.*s' %s\n",
+		    vcc_utype((*e)->fmt), PF(tk), vcc_utype(e2->fmt));
 		vcc_ErrWhere(tl, tk);
-		return;
-	}
-	*e = vcc_expr_edit(BOOL, cp->emit, *e, e2);
+	} else
+		*e = vcc_expr_edit(BOOL, cp->emit, *e, e2);
 }
 
 static void v_matchproto_(cmp_f)
@@ -979,13 +928,11 @@ cmp_regexp(struct vcc *tl, struct expr **e, const struct cmps *cp)
 	char buf[128];
 	const char *re;
 
-	if ((*e)->fmt != STRING)
-		vcc_expr_tostring(tl, e, STRING);
+	*e = vcc_expr_edit(STRING, "\vS", *e, NULL);
 	vcc_NextToken(tl);
 	ExpectErr(tl, CSTR);
 	re = vcc_regexp(tl);
 	ERRCHK(tl);
-	vcc_NextToken(tl);
 	bprintf(buf, "%sVRT_re_match(ctx, \v1, %s)", cp->emit, re);
 	*e = vcc_expr_edit(BOOL, buf, *e, NULL);
 }
@@ -1005,6 +952,28 @@ cmp_acl(struct vcc *tl, struct expr **e, const struct cmps *cp)
 	*e = vcc_expr_edit(BOOL, buf, *e, NULL);
 }
 
+static void v_matchproto_(cmp_f)
+cmp_string(struct vcc *tl, struct expr **e, const struct cmps *cp)
+{
+	struct expr *e2;
+	struct token *tk;
+
+	tk = tl->t;
+	vcc_NextToken(tl);
+	vcc_expr_add(tl, &e2, STRINGS);
+	ERRCHK(tl);
+	if (e2->fmt != STRINGS) {
+		VSB_printf(tl->sb,
+		    "Comparison of different types: %s '%.*s' %s\n",
+		    vcc_utype((*e)->fmt), PF(tk), vcc_utype(e2->fmt));
+		vcc_ErrWhere(tl, tk);
+	} 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);
+	}
+}
+
 #define IDENT_REL(typ)							\
 	{typ,		T_EQ,		cmp_simple, "(\v1 == \v2)" },	\
 	{typ,		T_NEQ,		cmp_simple, "(\v1 != \v2)" }
@@ -1035,17 +1004,13 @@ static const struct cmps vcc_cmps[] = {
 	{IP,		'~',		cmp_acl, "" },
 	{IP,		T_NOMATCH,	cmp_acl, "!" },
 
-	{STRING,	T_EQ,		cmp_simple, "!VRT_strcmp(\v1, \v2)" },
-	{STRING_LIST,	T_EQ,		cmp_simple, "!VRT_strcmp(\v1, \v2)" },
-	{STRING,	T_NEQ,		cmp_simple, "VRT_strcmp(\v1, \v2)" },
-	{STRING_LIST,	T_NEQ,		cmp_simple, "VRT_strcmp(\v1, \v2)" },
+	{STRINGS,	T_EQ,		cmp_string, "!VRT_strcmp(\v1, \v2)" },
+	{STRINGS,	T_NEQ,		cmp_string, "VRT_strcmp(\v1, \v2)" },
 
-	{STRING,	'~',		cmp_regexp, "" },
-	{STRING_LIST,	'~',		cmp_regexp, "" },
-	{STRING,	T_NOMATCH,	cmp_regexp, "!" },
-	{STRING_LIST,	T_NOMATCH,	cmp_regexp, "!" },
+	{STRINGS,	'~',		cmp_regexp, "" },
+	{STRINGS,	T_NOMATCH,	cmp_regexp, "!" },
 
-	{VOID, 0, NULL, NULL}
+	{VOID,		0,		NULL, NULL}
 };
 
 #undef IDENT_REL
@@ -1091,10 +1056,12 @@ vcc_expr_cmp(struct vcc *tl, struct expr **e, vcc_type_t fmt)
 	}
 	if (fmt != BOOL)
 		return;
-	if ((*e)->fmt == STRING || (*e)->fmt == BACKEND || (*e)->fmt == INT)
+	if ((*e)->fmt == BACKEND || (*e)->fmt == INT)
 		*e = vcc_expr_edit(BOOL, "(\v1 != 0)", *e, NULL);
 	else if ((*e)->fmt == DURATION)
 		*e = vcc_expr_edit(BOOL, "(\v1 > 0)", *e, NULL);
+	else if ((*e)->fmt == STRINGS)
+		*e = vcc_expr_edit(BOOL, "(\vS != 0)", *e, NULL);
 	else
 		INCOMPL();
 }
@@ -1210,25 +1177,34 @@ vcc_expr0(struct vcc *tl, struct expr **e, vcc_type_t fmt)
 {
 	struct token *t1;
 
-	*e = NULL;
 	assert(fmt != VOID);
+	assert(fmt != STRINGS);
+	*e = NULL;
 	t1 = tl->t;
-	vcc_expr_cor(tl, e, fmt);
+	if (fmt == STRING_LIST || fmt == STRING)
+		vcc_expr_cor(tl, e, STRINGS);
+	else
+		vcc_expr_cor(tl, e, fmt);
 	ERRCHK(tl);
-	if (fmt != (*e)->fmt && (fmt == STRING || fmt == STRING_LIST)) {
+	assert((*e)->fmt != STRING_LIST && (*e)->fmt != STRING);
+
+	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))
 		vcc_expr_tostring(tl, e, fmt);
-		ERRCHK(tl);
-	}
-	if (fmt != (*e)->fmt)  {
-		VSB_printf(tl->sb, "Expression has type %s, expected %s\n",
-		    vcc_utype((*e)->fmt), vcc_utype(fmt));
-		tl->err = 1;
-	}
+
 	if ((*e)->fmt == STRING_LIST)
 		*e = vcc_expr_edit(STRING_LIST,
 		    "\v+\n\v1,\nvrt_magic_string_end\v-", *e, NULL);
-	if (tl->err)
+
+	if (fmt != (*e)->fmt)  {
+		VSB_printf(tl->sb, "Expression has type %s, expected %s\n",
+		    vcc_utype((*e)->fmt), vcc_utype(fmt));
 		vcc_ErrWhere2(tl, t1, tl->t);
+		return;
+	}
 }
 
 /*--------------------------------------------------------------------
@@ -1244,6 +1220,7 @@ vcc_Expr(struct vcc *tl, vcc_type_t fmt)
 	struct expr *e = NULL;
 
 	assert(fmt != VOID);
+	assert(fmt != STRINGS);
 	vcc_expr0(tl, &e, fmt);
 	ERRCHK(tl);
 	vcc_expr_fmt(tl->fb, tl->indent, e);
diff --git a/lib/libvcc/vcc_types.c b/lib/libvcc/vcc_types.c
index 00a2198..cb446c8 100644
--- a/lib/libvcc/vcc_types.c
+++ b/lib/libvcc/vcc_types.c
@@ -134,10 +134,15 @@ const struct type STRING[1] = {{
 	.tostring =		"",
 }};
 
+const struct type STRINGS[1] = {{
+	.magic =		TYPE_MAGIC,
+	.name =			"STRINGS",
+	.tostring =		"",
+}};
+
 const struct type STRING_LIST[1] = {{
 	.magic =		TYPE_MAGIC,
 	.name =			"STRING_LIST",
-	.tostring =		"VRT_CollectString(ctx,\n\v1,\nvrt_magic_string_end)",
 }};
 
 const struct type SUB[1] = {{
diff --git a/lib/libvcc/vcc_utils.c b/lib/libvcc/vcc_utils.c
index 8d83897..a793c62 100644
--- a/lib/libvcc/vcc_utils.c
+++ b/lib/libvcc/vcc_utils.c
@@ -73,6 +73,7 @@ vcc_regexp(struct vcc *tl)
 	EncToken(ifp->ini, tl->t);
 	VSB_printf(ifp->ini, ");");
 	VSB_printf(ifp->fin, "\t\tVRT_re_fini(%s);", buf);
+	vcc_NextToken(tl);
 	return (p);
 }
 


More information about the varnish-commit mailing list