[6.0] 6ffcafc9f Make large integers work in VCL.
Dridi Boukelmoune
dridi.boukelmoune at gmail.com
Thu Aug 16 08:53:24 UTC 2018
commit 6ffcafc9fd3c379c82b1dba9e43cfe40ae65f122
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 05128ec21..ee49f55e4 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