[master] 9d40f55a0 Make large integers work in VCL.

Poul-Henning Kamp phk at FreeBSD.org
Tue Aug 14 07:47:11 UTC 2018


commit 9d40f55a0eba59f9762a54f5f529b6b3fa7da038
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Tue Aug 14 07:45:23 2018 +0000

    Make large integers work in VCL.
    
    Fixes: #2603

diff --git a/bin/varnishtest/tests/v00020.vtc b/bin/varnishtest/tests/v00020.vtc
index da563157f..4bebb20ae 100644
--- a/bin/varnishtest/tests/v00020.vtc
+++ b/bin/varnishtest/tests/v00020.vtc
@@ -326,10 +326,16 @@ varnish v1 -vcl+backend {
 		set resp.http.foo =
 		    (resp.http.foo + resp.http.bar) == ("X" + resp.http.foo);
 	}
+	sub vcl_deliver {
+		set resp.http.p = (0 + 9223372036854775807);
+		set resp.http.n = (0 - 9223372036854775807);
+	}
 } -start
 
 client c1 {
 	txreq
 	rxresp
 	expect resp.http.foo == "true"
+	expect resp.http.p == 9223372036854775807
+	expect resp.http.n == -9223372036854775807
 } -run
diff --git a/lib/libvcc/generate.py b/lib/libvcc/generate.py
index 6eba999d6..2b21aa0a2 100755
--- a/lib/libvcc/generate.py
+++ b/lib/libvcc/generate.py
@@ -80,6 +80,7 @@ tokens = {
 	# These have handwritten recognizers
 	"ID":		None,
 	"CNUM":		None,
+	"FNUM":		None,
 	"CSTR":		None,
 	"EOI":		None,
 	"CSRC":		None,
diff --git a/lib/libvcc/vcc_compile.h b/lib/libvcc/vcc_compile.h
index fef82ecef..3a6860abe 100644
--- a/lib/libvcc/vcc_compile.h
+++ b/lib/libvcc/vcc_compile.h
@@ -331,7 +331,6 @@ void Emit_UDS_Path(struct vcc *tl, const struct token *t_path,
     const char *errid);
 double vcc_TimeUnit(struct vcc *);
 void vcc_ByteVal(struct vcc *, double *);
-void vcc_NumVal(struct vcc *, double *, int *);
 void vcc_Duration(struct vcc *tl, double *);
 unsigned vcc_UintVal(struct vcc *tl);
 
diff --git a/lib/libvcc/vcc_expr.c b/lib/libvcc/vcc_expr.c
index 39a01af38..b420dedf8 100644
--- a/lib/libvcc/vcc_expr.c
+++ b/lib/libvcc/vcc_expr.c
@@ -677,6 +677,7 @@ vcc_Eval_SymFunc(struct vcc *tl, struct expr **e, struct token *t,
  *	'(' ExprCor ')'
  *	symbol
  *	CNUM
+ *	FNUM
  *	CSTR
  */
 
@@ -688,7 +689,6 @@ vcc_expr4(struct vcc *tl, struct expr **e, vcc_type_t fmt)
 	struct token *t;
 	struct symbol *sym;
 	double d;
-	int i;
 
 	sign = "";
 	*e = NULL;
@@ -782,34 +782,35 @@ vcc_expr4(struct vcc *tl, struct expr **e, vcc_type_t fmt)
 		*e = e1;
 		return;
 	case '-':
-		if (fmt != INT && fmt != REAL && fmt != DURATION)
+		if (fmt != INT &&
+		    fmt != REAL &&
+		    fmt != DURATION &&
+		    fmt != STRINGS)
 			break;
 		vcc_NextToken(tl);
-		ExpectErr(tl, CNUM);
+		if (tl->t->tok != FNUM && tl->t->tok != CNUM)
+			break;
 		sign = "-";
 		/* FALLTHROUGH */
+	case FNUM:
 	case CNUM:
-		/*
-		 * XXX: %g may not have enough decimals by default
-		 * XXX: but %a is ugly, isn't it ?
-		 */
 		assert(fmt != VOID);
 		if (fmt == BYTES) {
 			vcc_ByteVal(tl, &d);
 			ERRCHK(tl);
 			e1 = vcc_mk_expr(BYTES, "%.1f", d);
 		} else {
-			vcc_NumVal(tl, &d, &i);
-			ERRCHK(tl);
+			t = tl->t;
+			vcc_NextToken(tl);
 			if (tl->t->tok == ID) {
-				e1 = vcc_mk_expr(DURATION, "%s%g",
-				    sign, d * vcc_TimeUnit(tl));
+				e1 = vcc_mk_expr(DURATION, "(%s%.*s) * %g",
+				    sign, PF(t), vcc_TimeUnit(tl));
 				ERRCHK(tl);
-			} else if (i || fmt == REAL)
-				e1 = vcc_mk_expr(REAL, "%s%f", sign, d);
-			else
-				e1 = vcc_mk_expr(INT, "%s%jd",
-				    sign, (intmax_t)d);
+			} else if (fmt == REAL || t->tok == FNUM) {
+				e1 = vcc_mk_expr(REAL, "%s%.*s", sign, PF(t));
+			} else {
+				e1 = vcc_mk_expr(INT, "%s%.*s", sign, PF(t));
+			}
 		}
 		e1->constant = EXPR_CONST;
 		*e = e1;
diff --git a/lib/libvcc/vcc_parse.c b/lib/libvcc/vcc_parse.c
index a81950a6c..a4bbf1182 100644
--- a/lib/libvcc/vcc_parse.c
+++ b/lib/libvcc/vcc_parse.c
@@ -275,31 +275,22 @@ vcc_ParseFunction(struct vcc *tl)
 static void
 vcc_ParseVcl(struct vcc *tl)
 {
-	struct token *tok0, *tok1, *tok2;
+	struct token *tok0;
 	int syntax;
 
 	assert(vcc_IdIs(tl->t, "vcl"));
 	tok0 = tl->t;
 	vcc_NextToken(tl);
 
-	tok1 = tl->t;
-	Expect(tl, CNUM);
-	syntax = (*tl->t->b - '0') * 10;
-	vcc_NextToken(tl);
-	Expect(tl, '.');
-	vcc_NextToken(tl);
-
-	Expect(tl, CNUM);
-	tok2 = tl->t;
-	syntax += (*tl->t->b - '0');
-	vcc_NextToken(tl);
-
-	if (tok1->e - tok1->b != 1 || tok2->e - tok2->b != 1) {
+	Expect(tl, FNUM);
+	if (tl->t->e - tl->t->b != 3 || tl->t->b[1] != '.') {
 		VSB_printf(tl->sb,
 		    "Don't play silly buggers with VCL version numbers\n");
-		vcc_ErrWhere2(tl, tok0, tl->t);
+		vcc_ErrWhere(tl, tl->t);
 		ERRCHK(tl);
 	}
+	syntax = (tl->t->b[0] - '0') * 10 + (tl->t->b[2] - '0');
+	vcc_NextToken(tl);
 
 	if (syntax < VCL_LOW || syntax > VCL_HIGH) {
 		VSB_printf(tl->sb, "VCL version %.1f not supported.\n",
diff --git a/lib/libvcc/vcc_token.c b/lib/libvcc/vcc_token.c
index 894397d1e..fcd37796c 100644
--- a/lib/libvcc/vcc_token.c
+++ b/lib/libvcc/vcc_token.c
@@ -505,7 +505,15 @@ vcc_Lexer(struct vcc *tl, struct source *sp)
 			for (q = p; q < sp->e; q++)
 				if (!vct_isdigit(*q))
 					break;
-			vcc_AddToken(tl, CNUM, p, q);
+			if (*q != '.') {
+				vcc_AddToken(tl, CNUM, p, q);
+				p = q;
+				continue;
+			}
+			for (++q; q < sp->e; q++)
+				if (!vct_isdigit(*q))
+					break;
+			vcc_AddToken(tl, FNUM, p, q);
 			p = q;
 			continue;
 		}
diff --git a/lib/libvcc/vcc_utils.c b/lib/libvcc/vcc_utils.c
index 71db6a792..b28f1628f 100644
--- a/lib/libvcc/vcc_utils.c
+++ b/lib/libvcc/vcc_utils.c
@@ -348,50 +348,17 @@ vcc_UintVal(struct vcc *tl)
 	return (d);
 }
 
-/*--------------------------------------------------------------------
- * Recognize and convert { CNUM [ '.' [ CNUM ] ] } to double value
- * The tokenizer made sure we only get digits and a '.'
- */
-
-void
-vcc_NumVal(struct vcc *tl, double *d, int *frac)
-{
-	double e = 0.1;
-	const char *p;
-
-	*frac = 0;
-	*d = 0.0;
-	Expect(tl, CNUM);
-	if (tl->err) {
-		*d = NAN;
-		return;
-	}
-	for (p = tl->t->b; p < tl->t->e; p++) {
-		*d *= 10;
-		*d += *p - '0';
-	}
-	vcc_NextToken(tl);
-	if (tl->t->tok != '.')
-		return;
-	*frac = 1;
-	vcc_NextToken(tl);
-	if (tl->t->tok != CNUM)
-		return;
-	for (p = tl->t->b; p < tl->t->e; p++) {
-		*d += (*p - '0') * e;
-		e *= 0.1;
-	}
-	vcc_NextToken(tl);
-}
-
 static double
 vcc_DoubleVal(struct vcc *tl)
 {
-	double d;
-	int i;
+	const size_t l = tl->t->e - tl->t->b;
+	char buf[l + 1];
 
-	vcc_NumVal(tl, &d, &i);
-	return (d);
+	assert(tl->t->tok == CNUM || tl->t->tok == FNUM);
+	memcpy(buf, tl->t->b, l);
+	vcc_NextToken(tl);
+	buf[l] = '\0';
+	return (strtod(buf, NULL));
 }
 
 /*--------------------------------------------------------------------*/


More information about the varnish-commit mailing list