Commit 2d39b079 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

Collect VCL_DURATION type conversion in a single function and restrict

acceptable whitespace to SP and TAB.

Part of fix for #2882
parent 399619e8
......@@ -30,7 +30,7 @@ varnish v1 -errvcl {include not followed by string constant.} {
{ } ( ) * + - / % > < = ; ! & . | ~ ,
}
varnish v1 -errvcl {Unknown time unit 'k'. Legal are 'ms', 's', 'm', 'h', 'd', 'w' and 'y'} {
varnish v1 -errvcl {Unknown duration unit 'k'} {
backend b { .host = "127.0.0.1"; }
sub vcl_backend_response { set beresp.ttl = 1. k; }
}
......
......@@ -31,5 +31,9 @@
/* from libvarnish/vnum.c */
double VNUM(const char *p);
double VNUMpfx(const char *p, const char **e);
vtim_dur VNUM_duration_unit(vtim_dur r, const char *b, const char *e);
vtim_dur VNUM_duration(const char *p);
const char *VNUM_2bytes(const char *p, uintmax_t *r, uintmax_t rel);
#define VNUM_LEGAL_DURATION \
"Legal duration units are 'ms', 's', 'm', 'h', 'd', 'w' and 'y'"
......@@ -51,7 +51,7 @@ binheap_CFLAGS = -DTEST_DRIVER
vnum_c_test_SOURCES = vnum.c vas.c
vnum_c_test_CFLAGS = -DNUM_C_TEST -include config.h
vnum_c_test_LDADD = ${LIBM}
vnum_c_test_LDADD = ${LIBM} libvarnish.a
vjsn_test_SOURCES = vjsn.c
vjsn_test_CFLAGS = -DVJSN_TEST @SAN_CFLAGS@
......
......@@ -30,14 +30,15 @@
#include "config.h"
#include <ctype.h>
#include <math.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "vdef.h"
#include "vct.h"
#include "vnum.h"
#include "vas.h"
......@@ -61,14 +62,14 @@ VNUMpfx(const char *p, const char **t)
AN(p);
AN(t);
*t = NULL;
while (isspace(*p))
while (vct_issp(*p))
p++;
if (*p == '-' || *p == '+')
ms = (*p++ == '-' ? -1.0 : 1.0);
for (; *p != '\0'; p++) {
if (isdigit(*p)) {
if (vct_isdigit(*p)) {
m = m * 10. + *p - '0';
e = ne;
if (e)
......@@ -84,12 +85,12 @@ VNUMpfx(const char *p, const char **t)
p++;
if (*p == '-' || *p == '+')
es = (*p++ == '-' ? -1.0 : 1.0);
if (!isdigit(*p))
if (!vct_isdigit(*p))
return (nan(""));
for (; isdigit(*p); p++)
for (; vct_isdigit(*p); p++)
ee = ee * 10. + *p - '0';
}
while (isspace(*p))
while (vct_issp(*p))
p++;
if (*p != '\0')
*t = p;
......@@ -111,31 +112,25 @@ VNUM(const char *p)
/**********************************************************************/
vtim_dur
VNUM_duration(const char *p)
VNUM_duration_unit(vtim_dur r, const char *b, const char *e)
{
const char *t;
vtim_dur r;
double sc = 1.0;
if (p == NULL)
return (nan(""));
r = VNUMpfx(p, &t);
if (e == NULL)
e = strchr(b, '\0');
if (isnan(r) || t == NULL)
while (b < e && vct_issp(*b))
b++;
if (b == e)
return (nan(""));
while (isspace(*t))
t++;
// keep in sync with vcc_expr.c vcc_TimeUnit()
switch (*t++) {
switch (*b++) {
case 's':
break;
case 'm':
if (*t == 's') {
if (b < e && *b == 's') {
sc = 1e-3;
t++;
b++;
} else
sc = 60.0;
break;
......@@ -155,15 +150,32 @@ VNUM_duration(const char *p)
return (nan(""));
}
while (isspace(*t))
t++;
while (b < e && vct_issp(*b))
b++;
if (*t != '\0')
if (b < e)
return (nan(""));
return (r * sc);
}
vtim_dur
VNUM_duration(const char *p)
{
const char *t;
vtim_dur r;
if (p == NULL)
return (nan(""));
r = VNUMpfx(p, &t);
if (isnan(r) || t == NULL)
return (nan(""));
return (VNUM_duration_unit(r, t, NULL));
}
/**********************************************************************/
const char *
......
......@@ -20,6 +20,7 @@ libvarnishapi_la_SOURCES = \
../../include/vcs_version.h \
../libvarnish/version.c \
../libvarnish/vcli_proto.c \
../libvarnish/vct.c \
../libvarnish/vfil.c \
../libvarnish/vfl.c \
../libvarnish/vin.c \
......
......@@ -334,7 +334,7 @@ void Resolve_Sockaddr(struct vcc *tl, const char *host, const char *defport,
const struct token *t_err, const char *errid);
void Emit_UDS_Path(struct vcc *tl, const struct token *t_path,
const char *errid);
double vcc_TimeUnit(struct vcc *);
double vcc_DurationUnit(struct vcc *);
void vcc_ByteVal(struct vcc *, double *);
void vcc_Duration(struct vcc *tl, double *);
unsigned vcc_UintVal(struct vcc *tl);
......
......@@ -838,7 +838,7 @@ vcc_expr4(struct vcc *tl, struct expr **e, vcc_type_t fmt)
vcc_NextToken(tl);
if (tl->t->tok == ID) {
e1 = vcc_mk_expr(DURATION, "(%s%.*s) * %g",
sign, PF(t), vcc_TimeUnit(tl));
sign, PF(t), vcc_DurationUnit(tl));
ERRCHK(tl);
} else if (fmt == REAL || t->tok == FNUM) {
e1 = vcc_mk_expr(REAL, "%s%.*s", sign, PF(t));
......
......@@ -40,6 +40,7 @@
#include "vcc_compile.h"
#include "vre.h"
#include "vnum.h"
#include "vsa.h"
#include "vss.h"
#include "vtcp.h"
......@@ -296,39 +297,25 @@ Emit_UDS_Path(struct vcc *tl, const struct token *t_path, const char *errid)
}
/*--------------------------------------------------------------------
* Recognize and convert units of time, return seconds.
* Recognize and convert units of duration, return seconds.
*/
double
vcc_TimeUnit(struct vcc *tl)
vcc_DurationUnit(struct vcc *tl)
{
double sc = 1.0;
double sc;
assert(tl->t->tok == ID);
if (vcc_IdIs(tl->t, "ms"))
sc = 1e-3;
else if (vcc_IdIs(tl->t, "s"))
sc = 1.0;
else if (vcc_IdIs(tl->t, "m"))
sc = 60.0;
else if (vcc_IdIs(tl->t, "h"))
sc = 60.0 * 60.0;
else if (vcc_IdIs(tl->t, "d"))
sc = 60.0 * 60.0 * 24.0;
else if (vcc_IdIs(tl->t, "w"))
sc = 60.0 * 60.0 * 24.0 * 7.0;
else if (vcc_IdIs(tl->t, "y"))
sc = 60.0 * 60.0 * 24.0 * 365.0;
else {
VSB_printf(tl->sb, "Unknown time unit ");
vcc_ErrToken(tl, tl->t);
VSB_printf(tl->sb,
". Legal are 'ms', 's', 'm', 'h', 'd', 'w' and 'y'\n");
vcc_ErrWhere(tl, tl->t);
return (1.0);
sc = VNUM_duration_unit(1.0, tl->t->b, tl->t->e);
if (!isnan(sc)) {
vcc_NextToken(tl);
return (sc);
}
vcc_NextToken(tl);
return (sc);
VSB_printf(tl->sb, "Unknown duration unit ");
vcc_ErrToken(tl, tl->t);
VSB_printf(tl->sb, "\n%s\n", VNUM_LEGAL_DURATION);
vcc_ErrWhere(tl, tl->t);
return (1.0);
}
/*--------------------------------------------------------------------
......@@ -374,7 +361,7 @@ vcc_Duration(struct vcc *tl, double *d)
v = vcc_DoubleVal(tl);
ERRCHK(tl);
ExpectErr(tl, ID);
sc = vcc_TimeUnit(tl);
sc = vcc_DurationUnit(tl);
*d = v * sc;
}
......
......@@ -47,10 +47,10 @@
VCL_DURATION v_matchproto_(td_std_duration)
vmod_duration(VRT_CTX, VCL_STRING p, VCL_DURATION d)
{
double r = VNUM_duration(p);
(void) ctx;
double r;
CHECK_OBJ_NOTNULL(ctx, VRT_CTX_MAGIC);
r = VNUM_duration(p);
return (isnan(r) ? d : r);
}
......
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