r5034 - trunk/varnish-cache/lib/libvcl
phk at varnish-cache.org
phk at varnish-cache.org
Wed Jul 7 17:11:33 CEST 2010
Author: phk
Date: 2010-07-07 17:11:33 +0200 (Wed, 07 Jul 2010)
New Revision: 5034
Modified:
trunk/varnish-cache/lib/libvcl/vcc_compile.c
trunk/varnish-cache/lib/libvcl/vcc_expr.c
trunk/varnish-cache/lib/libvcl/vcc_parse.c
trunk/varnish-cache/lib/libvcl/vcc_symb.c
trunk/varnish-cache/lib/libvcl/vcc_types.h
Log:
Add initial stage of expression support for numeric types so far.
You can now say:
if (beresp.ttl >= beresp.grace + 30 s) {
}
and similar.
Modified: trunk/varnish-cache/lib/libvcl/vcc_compile.c
===================================================================
--- trunk/varnish-cache/lib/libvcl/vcc_compile.c 2010-07-07 14:03:39 UTC (rev 5033)
+++ trunk/varnish-cache/lib/libvcl/vcc_compile.c 2010-07-07 15:11:33 UTC (rev 5034)
@@ -383,7 +383,7 @@
/*--------------------------------------------------------------------*/
static struct source *
-vcc_file_source(struct vcc *tl, struct vsb *sb, const char *fn)
+vcc_file_source(const struct vcc *tl, struct vsb *sb, const char *fn)
{
char *f;
struct source *sp;
Modified: trunk/varnish-cache/lib/libvcl/vcc_expr.c
===================================================================
--- trunk/varnish-cache/lib/libvcl/vcc_expr.c 2010-07-07 14:03:39 UTC (rev 5033)
+++ trunk/varnish-cache/lib/libvcl/vcc_expr.c 2010-07-07 15:11:33 UTC (rev 5034)
@@ -51,10 +51,12 @@
tl->indent -= INDENT; \
} while (0)
+#if 0
#define C(tl, sep) do { \
Fb(tl, 1, "VRT_count(sp, %u)%s\n", ++tl->cnt, sep); \
tl->t->cnt = tl->cnt; \
} while (0)
+#endif
/*--------------------------------------------------------------------
* Recognize and convert units of time, return seconds.
@@ -114,30 +116,44 @@
* The tokenizer made sure we only get digits and a '.'
*/
-double
-vcc_DoubleVal(struct vcc *tl)
+static void
+vcc_NumVal(struct vcc *tl, double *d, int *frac)
{
- double d = 0.0, e = 0.1;
+ double e = 0.1;
const char *p;
+ *frac = 0;
+ *d = 0.0;
Expect(tl, CNUM);
- if (tl->err)
- return (NAN);
+ if (tl->err) {
+ *d = NAN;
+ return;
+ }
for (p = tl->t->b; p < tl->t->e; p++) {
- d *= 10;
- d += *p - '0';
+ *d *= 10;
+ *d += *p - '0';
}
vcc_NextToken(tl);
if (tl->t->tok != '.')
- return (d);
+ return;
+ *frac = 1;
vcc_NextToken(tl);
if (tl->t->tok != CNUM)
- return (d);
+ return;
for (p = tl->t->b; p < tl->t->e; p++) {
- d += (*p - '0') * e;
+ *d += (*p - '0') * e;
e *= 0.1;
}
vcc_NextToken(tl);
+}
+
+double
+vcc_DoubleVal(struct vcc *tl)
+{
+ double d;
+ int i;
+
+ vcc_NumVal(tl, &d, &i);
return (d);
}
@@ -176,27 +192,156 @@
/*--------------------------------------------------------------------*/
+static void
+vcc_Expr2(struct vcc *tl, enum var_type *fmt)
+{
+ const struct symbol *sym;
+ const struct var *vp;
+ double d;
+ int frac;
+
+ *fmt = VOID;
+ switch(tl->t->tok) {
+ case ID:
+ sym = VCC_FindSymbol(tl, tl->t);
+ if (sym == NULL) {
+ vsb_printf(tl->sb,
+ "Unknown symbol in numeric expression:\n");
+ vcc_ErrToken(tl, tl->t);
+ vsb_printf(tl->sb, "\n");
+ vcc_ErrWhere(tl, tl->t);
+ return;
+ }
+ vcc_AddUses(tl, tl->t, sym->r_methods, "Not available");
+ AN(sym->var);
+ vp = vcc_FindVar(tl, tl->t, 0, "cannot be read");
+ ERRCHK(tl);
+ assert(vp != NULL);
+ Fb(tl, 1, "%s\n", vp->rname);
+ *fmt = sym->fmt;
+ vcc_NextToken(tl);
+ return;
+ case CNUM:
+ vcc_NumVal(tl, &d, &frac);
+ ERRCHK(tl);
+ if (tl->t->tok == ID) {
+ d *= vcc_TimeUnit(tl);
+ ERRCHK(tl);
+ *fmt = DURATION;
+ } else if (!frac) {
+ *fmt = INT;
+ } else {
+ WRONG("numeric constant botch");
+ }
+ Fb(tl, 1, "%g\n", d);
+ return;
+
+ default:
+ vsb_printf(tl->sb,
+ "Unknown token in numeric expression:\n");
+ vcc_ErrToken(tl, tl->t);
+ vsb_printf(tl->sb, "\n");
+ vcc_ErrWhere(tl, tl->t);
+ return;
+ }
+}
+
+static void
+vcc_Expr1(struct vcc *tl, enum var_type fmt)
+{
+ enum var_type lfmt, rfmt, afmt;
+ struct token *top;
+ struct token *tfirst;
+
+ tfirst = tl->t;
+ Fb(tl, 1, "(\n");
+ L(tl, vcc_Expr2(tl, &lfmt));
+ ERRCHK(tl);
+ afmt = lfmt;
+ while (1) {
+ top = tl->t;
+ if (tl->t->tok == '+') {
+ vcc_NextToken(tl);
+ Fb(tl, 1, " +\n");
+ L(tl, vcc_Expr2(tl, &rfmt));
+ ERRCHK(tl);
+ if (lfmt == INT && rfmt == INT)
+ afmt = INT;
+ else if (lfmt == DURATION && rfmt == DURATION)
+ afmt = DURATION;
+ else if (lfmt == TIME && rfmt == DURATION)
+ afmt = TIME;
+ else if (lfmt == DURATION && rfmt == TIME)
+ afmt = TIME;
+ else {
+ vsb_printf(tl->sb,
+ /* XXX print actual types */
+ "Incompatible types in addition.\n"
+ "Legal combinations:\n"
+ "\tINT+INT,\n"
+ "\tDURATION+DURATION,\n"
+ "\tDURATION+TIME,\n"
+ "\tTIME+DURATION\n");
+ vcc_ErrWhere(tl, top);
+ return;
+ }
+ } else if (tl->t->tok == '-') {
+ vcc_NextToken(tl);
+ Fb(tl, 1, " -\n");
+ L(tl, vcc_Expr2(tl, &rfmt));
+ if (lfmt == INT && rfmt == INT)
+ afmt = INT;
+ else if (lfmt == DURATION && rfmt == DURATION)
+ afmt = DURATION;
+ else if (lfmt == TIME && rfmt == DURATION)
+ afmt = TIME;
+ else if (lfmt == TIME && rfmt == TIME)
+ afmt = DURATION;
+ else {
+ vsb_printf(tl->sb,
+ /* XXX print actual types */
+ "Incompatible types in subtraction.\n"
+ "Legal combinations:\n"
+ "\tINT-INT,\n"
+ "\tDURATION-DURATION,\n"
+ "\tTIME-DURATION,\n"
+ "\tTIME-TIME,\n");
+ vcc_ErrWhere(tl, top);
+ return;
+ }
+ } else
+ break;
+ lfmt = afmt;
+ }
+ Fb(tl, 1, ")\n");
+ if (fmt != afmt) {
+ vsb_printf(tl->sb,
+ /* XXX print actual types */
+ "Add/Subtract results in wrong type.\n"
+ "\nExpression starting at:\n" );
+ vcc_ErrWhere(tl, tfirst);
+ vsb_printf(tl->sb, "\nending before:\n\n");
+ vcc_ErrWhere(tl, tl->t);
+ return;
+ }
+}
+
void
vcc_Expr(struct vcc *tl, enum var_type fmt)
{
- double d;
- switch(fmt) {
+ switch (fmt) {
case DURATION:
- vcc_RTimeVal(tl, &d);
- ERRCHK(tl);
- Fb(tl, 0, "%g\n", d);
- break;
+ case INT:
case TIME:
- vcc_RTimeVal(tl, &d);
+ /* These types support addition and subtraction */
+ Fb(tl, 1, "(\n");
+ L(tl, vcc_Expr1(tl, fmt));
ERRCHK(tl);
- Fb(tl, 0, "%g\n", d);
- break;
- case INT:
- Fb(tl, 0, "%u\n", vcc_UintVal(tl));
- ERRCHK(tl);
- break;
+ Fb(tl, 1, ")\n");
+ return;
default:
- WRONG("missing type support");
+ WRONG("type not implemented yet");
}
}
+
Modified: trunk/varnish-cache/lib/libvcl/vcc_parse.c
===================================================================
--- trunk/varnish-cache/lib/libvcl/vcc_parse.c 2010-07-07 14:03:39 UTC (rev 5033)
+++ trunk/varnish-cache/lib/libvcl/vcc_parse.c 2010-07-07 15:11:33 UTC (rev 5034)
@@ -34,7 +34,6 @@
#include <stdio.h>
#include <string.h>
-#include <math.h>
#include "vsb.h"
@@ -96,6 +95,7 @@
case '>':
case '<':
vcc_inval_test(tl, "STRING", "'==', '!=', '~' and '!~'");
+ break;
case T_EQ:
case T_NEQ:
Fb(tl, 1, "%sVRT_strcmp(%s, ",
@@ -114,7 +114,7 @@
}
static void
-vcc_Cond_Bool(struct vcc *tl, const char *a1)
+vcc_Cond_Bool(const struct vcc *tl, const char *a1)
{
Fb(tl, 1, "%s\n", a1);
@@ -152,7 +152,7 @@
case T_GEQ:
case '>':
case '<':
- Fb(tl, 0, "%.*s ", PF(tl->t));
+ Fb(tl, 0, "%.*s\n", PF(tl->t));
vcc_NextToken(tl);
vcc_Expr(tl, fmt);
break;
Modified: trunk/varnish-cache/lib/libvcl/vcc_symb.c
===================================================================
--- trunk/varnish-cache/lib/libvcl/vcc_symb.c 2010-07-07 14:03:39 UTC (rev 5033)
+++ trunk/varnish-cache/lib/libvcl/vcc_symb.c 2010-07-07 15:11:33 UTC (rev 5034)
@@ -56,7 +56,9 @@
WRONG("name collision");
}
ALLOC_OBJ(sym, SYMBOL_MAGIC);
+ AN(sym);
REPLACE(sym->name, name);
+ AN(name);
sym->nlen = strlen(name);
VTAILQ_INSERT_TAIL(&tl->symbols, sym, list);
return (sym);
Modified: trunk/varnish-cache/lib/libvcl/vcc_types.h
===================================================================
--- trunk/varnish-cache/lib/libvcl/vcc_types.h 2010-07-07 14:03:39 UTC (rev 5033)
+++ trunk/varnish-cache/lib/libvcl/vcc_types.h 2010-07-07 15:11:33 UTC (rev 5034)
@@ -28,6 +28,7 @@
* $Id$
*/
+VCC_TYPE(VOID)
VCC_TYPE(BACKEND)
VCC_TYPE(BOOL)
VCC_TYPE(INT)
More information about the varnish-commit
mailing list