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

Make large integers work in VCL.

Fixes: #2603
parent 46f1557d
......@@ -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
......@@ -80,6 +80,7 @@ tokens = {
# These have handwritten recognizers
"ID": None,
"CNUM": None,
"FNUM": None,
"CSTR": None,
"EOI": None,
"CSRC": None,
......
......@@ -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);
......
......@@ -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;
......
......@@ -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",
......
......@@ -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;
}
......
......@@ -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));
}
/*--------------------------------------------------------------------*/
......
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