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