r545 - trunk/varnish-cache/lib/libvcl

phk at projects.linpro.no phk at projects.linpro.no
Fri Jul 21 22:43:56 CEST 2006


Author: phk
Date: 2006-07-21 22:43:56 +0200 (Fri, 21 Jul 2006)
New Revision: 545

Added:
   trunk/varnish-cache/lib/libvcl/vcc_gen_obj.tcl
Modified:
   trunk/varnish-cache/lib/libvcl/Makefile.am
   trunk/varnish-cache/lib/libvcl/vcc_compile.c
   trunk/varnish-cache/lib/libvcl/vcc_compile.h
   trunk/varnish-cache/lib/libvcl/vcc_gen_fixed_token.tcl
   trunk/varnish-cache/lib/libvcl/vcc_obj.c
   trunk/varnish-cache/lib/libvcl/vcc_token.c
Log:
Automate generation of tables and prototypes for the objects which
VCL programs can manipulate.




Property changes on: trunk/varnish-cache/lib/libvcl/Makefile.am
___________________________________________________________________
Name: svn:keywords
   + Id

Modified: trunk/varnish-cache/lib/libvcl/vcc_compile.c
===================================================================
--- trunk/varnish-cache/lib/libvcl/vcc_compile.c	2006-07-21 18:12:56 UTC (rev 544)
+++ trunk/varnish-cache/lib/libvcl/vcc_compile.c	2006-07-21 20:43:56 UTC (rev 545)
@@ -1,5 +1,5 @@
 /*
- * $Id: vcl_compile.c 531 2006-07-20 22:08:43Z phk $
+ * $Id$
  */
 
 /*
@@ -791,7 +791,7 @@
 		vp = FindVar(tl, tl->t, vcc_vars);
 		ERRCHK(tl);
 		assert(vp != NULL);
-		Fc(tl, 1, "%s ", vp->rname);
+		Fc(tl, 1, "%s", vp->lname);
 		vcc_NextToken(tl);
 		switch (vp->fmt) {
 		case INT:
@@ -799,7 +799,8 @@
 		case RATE:
 		case TIME:
 		case FLOAT:
-			Fc(tl, 0, "%T ", tl->t);
+			if (tl->t->tok != '=') 
+				Fc(tl, 0, "%s %c ", vp->rname, *tl->t->b);
 			a = tl->t->tok;
 			vcc_NextToken(tl);
 			if (a == T_MUL || a == T_DIV)
@@ -812,7 +813,7 @@
 				RateVal(tl);
 			else 
 				Fc(tl, 0, "%g", DoubleVal(tl));
-			Fc(tl, 0, ";\n");
+			Fc(tl, 0, ");\n");
 			break;
 		case IP:
 			if (tl->t->tok == '=') {
@@ -1007,19 +1008,13 @@
 		case HOSTNAME:
 			ExpectErr(tl, CSTR);
 			t_host = tl->t;
-			Fc(tl, 1, "\tp = %T;\n", tl->t);
-			Fc(tl, 1, "\t");
-			Fc(tl, 0, vp->lname, "p");
-			Fc(tl, 0, ";\n");
+			Fc(tl, 1, "\t%s %T);\n", vp->lname, tl->t);
 			vcc_NextToken(tl);
 			break;
 		case PORTNAME:
 			ExpectErr(tl, CSTR);
 			t_port = tl->t;
-			Fc(tl, 1, "\tp = %T;\n", tl->t);
-			Fc(tl, 1, "\t");
-			Fc(tl, 0, vp->lname, "p");
-			Fc(tl, 0, ";\n");
+			Fc(tl, 1, "\t%s %T);\n", vp->lname, tl->t);
 			vcc_NextToken(tl);
 			break;
 		default:
@@ -1381,6 +1376,7 @@
 	FILE *fo;
 	char *of = NULL;
 	char buf[BUFSIZ];
+	int i;
 
 	memset(&tokens, 0, sizeof tokens);
 	TAILQ_INIT(&tokens.tokens);
@@ -1434,6 +1430,7 @@
 	assert(fo != NULL);
 
 	vcl_output_lang_h(fo);
+	fputs(vrt_obj_h, fo);
 
 	sbuf_finish(tokens.fh);
 	fputs(sbuf_data(tokens.fh), fo);
@@ -1443,7 +1440,14 @@
 	fputs(sbuf_data(tokens.fc), fo);
 	sbuf_delete(tokens.fc);
 
-	pclose(fo);
+	i = pclose(fo);
+	fprintf(stderr, "pclose=%d\n", i);
+	if (i) {
+		sbuf_printf(sb, "Internal error: GCC returned 0x%04x\n", i);
+		unlink(of);
+		free(of);
+		return (NULL);
+	}
 done:
 
 	/* Free References */


Property changes on: trunk/varnish-cache/lib/libvcl/vcc_compile.c
___________________________________________________________________
Name: svn:keywords
   + Id

Modified: trunk/varnish-cache/lib/libvcl/vcc_compile.h
===================================================================
--- trunk/varnish-cache/lib/libvcl/vcc_compile.h	2006-07-21 18:12:56 UTC (rev 544)
+++ trunk/varnish-cache/lib/libvcl/vcc_compile.h	2006-07-21 20:43:56 UTC (rev 545)
@@ -63,7 +63,7 @@
 struct var {
 	const char		*name;
 	enum var_type		fmt;
-	int			len;
+	unsigned		len;
 	const char		*rname;
 	const char		*lname;
 };
@@ -107,6 +107,7 @@
 /* vcc_obj.c */
 extern struct var vcc_be_vars[];
 extern struct var vcc_vars[];
+const char *vrt_obj_h;
 
 /* vcc_token.c */
 void vcc_ErrToken(struct tokenlist *tl, struct token *t);


Property changes on: trunk/varnish-cache/lib/libvcl/vcc_compile.h
___________________________________________________________________
Name: svn:keywords
   + Id


Property changes on: trunk/varnish-cache/lib/libvcl/vcc_gen_fixed_token.tcl
___________________________________________________________________
Name: svn:keywords
   + Id

Added: trunk/varnish-cache/lib/libvcl/vcc_gen_obj.tcl
===================================================================
--- trunk/varnish-cache/lib/libvcl/vcc_gen_obj.tcl	2006-07-21 18:12:56 UTC (rev 544)
+++ trunk/varnish-cache/lib/libvcl/vcc_gen_obj.tcl	2006-07-21 20:43:56 UTC (rev 545)
@@ -0,0 +1,95 @@
+#!/usr/local/bin/tclsh8.4
+#
+# Generate various .c and .h files for the VCL compiler and the interfaces
+# for it.
+
+# Objects which operate on backends
+set beobj {
+	{ backend.host	HOSTNAME }
+	{ backend.port	PORTNAME }
+}
+
+# Objects which operate on sessions
+
+set spobj {
+	{ req.request	STRING }
+        { req.url	STRING }
+        { obj.valid	BOOL }
+        { obj.cacheable	BOOL }
+        { obj.backend	BACKEND }
+        { obj.ttl	TIME }
+        { req.http.	HEADER }
+}
+
+set tt(STRING)	"char *"
+set tt(BOOL)	"double"
+set tt(BACKEND)	"struct backend *"
+set tt(TIME)	"double"
+set tt(HEADER)	"char *"
+set tt(HOSTNAME) "char *"
+set tt(PORTNAME) "char *"
+
+#----------------------------------------------------------------------
+# Boilerplate warning for all generated files.
+
+proc warns {fd} {
+
+	puts $fd "/*"
+	puts $fd { * $Id$}
+	puts $fd " *"
+	puts $fd " * NB:  This file is machine generated, DO NOT EDIT!"
+	puts $fd " *"
+	puts $fd " * Edit vcc_gen_obj.tcl instead"
+	puts $fd " */"
+	puts $fd ""
+}
+
+set fo [open vcc_obj.c w]
+warns $fo
+set fp [open ../../include/vrt_obj.h w]
+warns $fp
+
+proc vars {v ty pa} {
+	global tt fo fp
+
+	foreach v $v {
+		set n [lindex $v 0]
+		regsub -all {[.]} $n "_" m
+		set t [lindex $v 1]
+		puts $fo  "\t\{ \"$n\", $t, [string length $n],"
+		puts $fo  "\t    \"VRT_r_${m}($pa)\","
+		puts $fo  "\t    \"VRT_l_${m}($pa, \","
+		puts $fo "\t\},"
+
+		puts $fp  "$tt($t) VRT_r_${m}($ty);"
+		puts $fp  "void VRT_l_${m}($ty, $tt($t));"
+	}
+	puts $fo "\t{ NULL }"
+}
+
+puts $fo "#include <stdio.h>"
+puts $fo "#include \"vcc_compile.h\""
+puts $fo ""
+
+puts $fo "struct var vcc_be_vars\[\] = {"
+vars $beobj "struct backend *" "backend"
+puts $fo "};"
+
+puts $fo ""
+
+puts $fo "struct var vcc_vars\[\] = {"
+vars $spobj "struct sess *" "sp"
+puts $fo "};"
+
+close $fp
+set fp [open ../../include/vrt_obj.h]
+
+puts $fo ""
+puts $fo "const char *vrt_obj_h = "
+while {[gets $fp a] >= 0} {
+	puts $fo "\t\"$a\\n\""
+}
+puts $fo ";"
+
+close $fo
+close $fp


Property changes on: trunk/varnish-cache/lib/libvcl/vcc_gen_obj.tcl
___________________________________________________________________
Name: svn:executable
   + *
Name: svn:keywords
   + Id

Modified: trunk/varnish-cache/lib/libvcl/vcc_obj.c
===================================================================
--- trunk/varnish-cache/lib/libvcl/vcc_obj.c	2006-07-21 18:12:56 UTC (rev 544)
+++ trunk/varnish-cache/lib/libvcl/vcc_obj.c	2006-07-21 20:43:56 UTC (rev 545)
@@ -1,1843 +1,83 @@
 /*
  * $Id$
+ *
+ * NB:  This file is machine generated, DO NOT EDIT!
+ *
+ * Edit vcc_gen_obj.tcl instead
  */
 
 #include <stdio.h>
-
 #include "vcc_compile.h"
 
 struct var vcc_be_vars[] = {
-	{ "backend.host",
-		HOSTNAME, 0,  NULL, "VRT_set_backend_hostname(backend, %s)" },
-	{ "backend.port",
-		PORTNAME, 0,  NULL, "VRT_set_backend_portname(backend, %s)" },
+	{ "backend.host", HOSTNAME, 12,
+	    "VRT_r_backend_host(backend)",
+	    "VRT_l_backend_host(backend, ",
+	},
+	{ "backend.port", PORTNAME, 12,
+	    "VRT_r_backend_port(backend)",
+	    "VRT_l_backend_port(backend, ",
+	},
+	{ NULL }
 };
 
-
 struct var vcc_vars[] = {
-	{ "req.request",		STRING,	  0,  "VRT_GetReq(sp)"	     },
-	{ "obj.valid",			BOOL,	  0,  "VRT_obj_valid(sp)"     },
-	{ "obj.cacheable",		BOOL,	  0,  "VRT_obj_cacheable(sp)" },
-	{ "obj.backend",		BACKEND,  0,  "VRT_obj_backend(sp)"   },
-	{ "req.http.",			HEADER,	  0,  NULL },
-#if 0
-	{ "req.ttlfactor",		FLOAT, 0,   "req->ttlfactor" },
-	{ "req.url.host",		STRING, 0,  "req->url.host" },
-	{ "req.url.path",		STRING, 0,  "req->url.path" },
-	{ "req.useragent",		STRING, 0,  "req->useragent" },
-	{ "req.backend",		BACKEND, 0, "req->backend"   },
-	{ "client.ip",			IP, 0,	    "client->ip"     },
-	{ "backend.response_time",	TIME, 0,    "backend->responsetime" },
-	{ "backend.down",		BOOL, 0,    "backend->down"  },
-	{ "backend.timeout",		TIME, 0,    "backend->timeout" },
-	{ "backend.bandwidth",		RATE, 0,    "backend->bandwidth" },
-	{ "obj.exist",			BOOL, 0,    "obj->exists" },
-	{ "obj.ttl",			TIME, 0,    "obj->ttl" },
-	{ "obj.result",			INT, 0,     "obj->result" },
-	{ "obj.size",			SIZE, 0,    "obj->size" },
-	{ "obj.usage",			INT, 0,     "obj->usage" },
-#endif
-	{ NULL,				INT, 0,	    "NULL" }
+	{ "req.request", STRING, 11,
+	    "VRT_r_req_request(sp)",
+	    "VRT_l_req_request(sp, ",
+	},
+	{ "req.url", STRING, 7,
+	    "VRT_r_req_url(sp)",
+	    "VRT_l_req_url(sp, ",
+	},
+	{ "obj.valid", BOOL, 9,
+	    "VRT_r_obj_valid(sp)",
+	    "VRT_l_obj_valid(sp, ",
+	},
+	{ "obj.cacheable", BOOL, 13,
+	    "VRT_r_obj_cacheable(sp)",
+	    "VRT_l_obj_cacheable(sp, ",
+	},
+	{ "obj.backend", BACKEND, 11,
+	    "VRT_r_obj_backend(sp)",
+	    "VRT_l_obj_backend(sp, ",
+	},
+	{ "obj.ttl", TIME, 7,
+	    "VRT_r_obj_ttl(sp)",
+	    "VRT_l_obj_ttl(sp, ",
+	},
+	{ "req.http.", HEADER, 9,
+	    "VRT_r_req_http_(sp)",
+	    "VRT_l_req_http_(sp, ",
+	},
+	{ NULL }
 };
 
-
-#if 0
-
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-
-#include <assert.h>
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <netdb.h>
-#include <stdio.h>
-#include <printf.h>
-#include <stdarg.h>
-#include <sbuf.h>
-#include <stdlib.h>
-#include <string.h>
-#include <queue.h>
-#include <unistd.h>
-
-#include "vcl_priv.h"
-#include "vcl_returns.h"
-#include "vcl_compile.h"
-
-#include "libvcl.h"
-
-#define ERRCHK(tl)	do { if ((tl)->err) return; } while (0)
-
-#define INDENT		2
-
-/*--------------------------------------------------------------------
- * Consistency check
- */
-
-static struct method {
-	const char		*name;
-	const char		*defname;
-	unsigned		returns;
-} method_tab[] = {
-#define VCL_RET_MAC(a,b,c)
-#define VCL_MET_MAC(a,b,c)	{ "vcl_"#a, "default_vcl_"#a, c },
-#include "vcl_returns.h"
-#undef VCL_MET_MAC
-#undef VCL_RET_MAC
-	{ NULL, 0U }
-};
-
-struct proccall {
-	TAILQ_ENTRY(proccall)	list;
-	struct proc		*p;
-	struct token		*t;
-};
-
-struct proc {
-	TAILQ_ENTRY(proc)	list;
-	TAILQ_HEAD(,proccall)	calls;
-	struct token		*name;
-	unsigned		returns;
-	unsigned		exists;
-	unsigned		called;
-	unsigned		active;
-	struct token		*returnt[VCL_RET_MAX];
-};
-
-/*--------------------------------------------------------------------*/
-
-
-static void Compound(struct tokenlist *tl);
-static void Cond_0(struct tokenlist *tl);
-static struct proc *AddProc(struct tokenlist *tl, struct token *t, int def);
-static void AddCall(struct tokenlist *tl, struct token *t);
-static const char *vcc_default_vcl_b, *vcc_default_vcl_e;
-
-/*--------------------------------------------------------------------*/
-
-static void
-ErrToken(struct tokenlist *tl, struct token *t)
-{
-
-	if (t->tok == EOI)
-		sbuf_printf(tl->sb, "end of input");
-	else
-		sbuf_printf(tl->sb, "'%T'", t);
-}
-
-static void
-_ErrInternal(struct tokenlist *tl, const char *func, unsigned line)
-{
-
-	sbuf_printf(tl->sb, "VCL compiler internal error at %s():%u\n",
-	    func, line);
-	tl->err = 1;
-}
-
-#define ErrInternal(tl) _ErrInternal(tl, __func__, __LINE__)
-
-static void
-ErrWhere(struct tokenlist *tl, struct token *t)
-{
-	unsigned lin, pos, x, y;
-	const char *p, *l, *f, *b, *e;
-	
-	lin = 1;
-	pos = 0;
-	if (t->tok == METHOD)
-		return;
-	if (t->b >= vcc_default_vcl_b && t->b < vcc_default_vcl_e) {
-		f = "Default VCL code (compiled in)";
-		b = vcc_default_vcl_b;
-		e = vcc_default_vcl_e;
-	} else {
-		f = "VCL code";
-		b = tl->b;
-		e = tl->e;
-	}
-	for (l = p = b; p < t->b; p++) {
-		if (*p == '\n') {
-			lin++;
-			pos = 0;
-			l = p + 1;
-		} else if (*p == '\t') {
-			pos &= ~7;
-			pos += 8;
-		} else
-			pos++;
-	}
-	sbuf_printf(tl->sb, "In %s Line %d Pos %d\n", f, lin, pos);
-	x = y = 0;
-	for (p = l; p < e && *p != '\n'; p++) {
-		if (*p == '\t') {
-			y &= ~7;
-			y += 8;
-			while (x < y) {
-				sbuf_bcat(tl->sb, " ", 1);
-				x++;
-			}
-		} else {
-			x++;
-			y++;
-			sbuf_bcat(tl->sb, p, 1);
-		}
-	}
-	sbuf_cat(tl->sb, "\n");
-	x = y = 0;
-	for (p = l; p < e && *p != '\n'; p++) {
-		if (p >= t->b && p < t->e) {
-			sbuf_bcat(tl->sb, "#", 1);
-			x++;
-			y++;
-			continue;
-		}
-		if (*p == '\t') {
-			y &= ~7;
-			y += 8;
-		} else
-			y++;
-		while (x < y) {
-			sbuf_bcat(tl->sb, "-", 1);
-			x++;
-		}
-	}
-	sbuf_cat(tl->sb, "\n");
-	tl->err = 1;
-}
-
-/*--------------------------------------------------------------------*/
-
-static void
-NextToken(struct tokenlist *tl)
-{
-	tl->t = TAILQ_NEXT(tl->t, list);
-	if (tl->t == NULL) {
-		sbuf_printf(tl->sb,
-		    "Ran out of input, something is missing or"
-		    " maybe unbalanced (...) or {...}\n");
-		tl->err = 1;
-		return;
-	}
-}
-
-static void
-_Expect(struct tokenlist *tl, unsigned tok, int line)
-{
-	if (tl->t->tok == tok)
-		return;
-	sbuf_printf(tl->sb, "Expected %s got ", vcl_tnames[tok]);
-	ErrToken(tl, tl->t);
-	sbuf_printf(tl->sb, "\n(program line %u), at\n", line);
-	ErrWhere(tl, tl->t);
-}
-
-#define Expect(a, b) _Expect(a, b, __LINE__)
-#define ExpectErr(a, b) do { _Expect(a, b, __LINE__); ERRCHK(a);} while (0)
-
-#define L(tl, foo)	do {	\
-	tl->indent += INDENT;	\
-	foo;			\
-	tl->indent -= INDENT;	\
-} while (0)
-
-#define C(tl, sep)	do {				\
-	Fc(tl, 1, "VRT_count(sp, %u)%s\n", ++tl->cnt, sep);	\
-	tl->t->cnt = tl->cnt; 				\
-} while (0)
-	
-/*--------------------------------------------------------------------
- * Printf output to the two sbufs, possibly indented
- */
-
-static void
-Fh(struct tokenlist *tl, int indent, const char *fmt, ...)
-{
-	va_list ap;
-
-	if (indent)
-		sbuf_printf(tl->fh, "%*.*s", tl->indent, tl->indent, "");
-	va_start(ap, fmt);
-	sbuf_vprintf(tl->fh, fmt, ap);
-	va_end(ap);
-}
-
-static void
-Fc(struct tokenlist *tl, int indent, const char *fmt, ...)
-{
-	va_list ap;
-
-	if (indent)
-		sbuf_printf(tl->fc, "%*.*s", tl->indent, tl->indent, "");
-	va_start(ap, fmt);
-	sbuf_vprintf(tl->fc, fmt, ap);
-	va_end(ap);
-}
-
-/*--------------------------------------------------------------------
- * Compare token to token
- */
-
-static int
-Teq(struct token *t1, struct token *t2)
-{
-	if (t1->e - t1->b != t2->e - t2->b)
-		return (0);
-	return (!memcmp(t1->b, t2->b, t1->e - t1->b));
-}
-
-/*--------------------------------------------------------------------
- * Compare ID token to string, return true of match
- */
-
-static int
-IdIs(struct token *t, const char *p)
-{
-	const char *q;
-
-	assert(t->tok == ID);
-	for (q = t->b; q < t->e && *p != '\0'; p++, q++)
-		if (*q != *p)
-			return (0);
-	if (q != t->e || *p != '\0')
-		return (0);
-	return (1);
-}
-
-/*--------------------------------------------------------------------*/
-
-static char *
-EncString(struct token *t)
-{
-	char *p, *q;
-	const char *r;
-	unsigned u;
-
-	assert(t->tok == CSTR);
-	p = malloc(t->e - t->b);
-	assert(p != NULL);
-	q = p;
-	for (r = t->b + 1; r < t->e - 1; ) {
-		if (*r != '\\') {
-			*q++ = *r++;
-			continue;
-		}
-		switch (r[1]) {
-		case 'n':	*q++ = '\n';	r += 2; break;
-		case 'r':	*q++ = '\r';	r += 2; break;
-		case 'v':	*q++ = '\v';	r += 2; break;
-		case 'f':	*q++ = '\f';	r += 2; break;
-		case 't':	*q++ = '\t';	r += 2; break;
-		case 'b':	*q++ = '\b';	r += 2; break;
-		case '0': case '1': case '2': case '3':
-		case '4': case '5': case '6': case '7':
-			u = r[1] - '0';
-			r += 2;
-			if (isdigit(r[0]) && (r[0] - '0') < 8) {
-				u <<= 3;
-				u |= r[0] - '0';
-				r++;
-				if (isdigit(r[0]) && (r[0] - '0') < 8) {
-					u <<= 3;
-					u |= r[0] - '0';
-					r++;
-				}
-			}
-			*q++ = u;
-			break;
-		default:
-			*q++ = r[1];	
-			r += 2;
-			break;
-		}
-	}
-	*q = '\0';
-	return (p);
-}
-
-
-/*--------------------------------------------------------------------
- * Keep track of definitions and references
- */
-
-static struct ref *
-FindRef(struct tokenlist *tl, struct token *t, enum ref_type type)
-{
-	struct ref *r;
-
-	TAILQ_FOREACH(r, &tl->refs, list) {
-		if (r->type != type)
-			continue;
-		if (Teq(r->name, t))
-			return (r);
-	}
-	r = calloc(sizeof *r, 1);
-	assert(r != NULL);
-	r->name = t;
-	r->type = type;
-	TAILQ_INSERT_TAIL(&tl->refs, r, list);
-	return (r);
-}
-
-static int
-FindRefStr(struct tokenlist *tl, const char *s, enum ref_type type)
-{
-	struct ref *r;
-
-	TAILQ_FOREACH(r, &tl->refs, list) {
-		if (r->type != type)
-			continue;
-		if (IdIs(r->name, s))
-			return (1);
-	}
-	return (0);
-}
-
-static void
-AddRef(struct tokenlist *tl, struct token *t, enum ref_type type)
-{
-
-	FindRef(tl, t, type)->refcnt++;
-}
-
-static void
-AddRefStr(struct tokenlist *tl, const char *s, enum ref_type type)
-{
-	struct token *t;
-
-	t = calloc(sizeof *t, 1);
-	t->b = s;
-	t->e = strchr(s, '\0');
-	t->tok = METHOD;
-	AddRef(tl, t, type);
-}
-
-static void
-AddDef(struct tokenlist *tl, struct token *t, enum ref_type type)
-{
-	struct ref *r;
-
-	r = FindRef(tl, t, type);
-	r->defcnt++;
-	r->name = t;
-}
-
-/*--------------------------------------------------------------------
- * Recognize and convert units of time, return seconds.
- */
-
-static double
-TimeUnit(struct tokenlist *tl)
-{
-	double sc = 1.0;
-
-	assert(tl->t->tok == ID);
-	if (IdIs(tl->t, "ms"))
-		sc = 1e-3;
-	else if (IdIs(tl->t, "s"))
-		sc = 1.0;
-	else if (IdIs(tl->t, "m"))
-		sc = 60.0;
-	else if (IdIs(tl->t, "h"))
-		sc = 60.0 * 60.0;
-	else if (IdIs(tl->t, "d"))
-		sc = 60.0 * 60.0 * 24.0;
-	else {
-		sbuf_printf(tl->sb, "Unknown time unit ");
-		ErrToken(tl, tl->t);
-		sbuf_printf(tl->sb, ".  Legal are 's', 'm', 'h' and 'd'\n");
-		ErrWhere(tl, tl->t);
-		return (1.0);
-	}
-	NextToken(tl);
-	return (sc);
-}
-
-/*--------------------------------------------------------------------
- * Recognize and convert units of size, return bytes.
- */
-
-static double
-SizeUnit(struct tokenlist *tl)
-{
-	double sc = 1.0;
-
-	assert(tl->t->tok == ID);
-	if (IdIs(tl->t, "b"))
-		sc = 1.0;
-	else if (IdIs(tl->t, "kb"))
-		sc = 1024.0;
-	else if (IdIs(tl->t, "mb") || IdIs(tl->t, "Mb"))
-		sc = 1024.0 * 1024.0;
-	else if (IdIs(tl->t, "gb") || IdIs(tl->t, "Gb"))
-		sc = 1024.0 * 1024.0 * 1024.0;
-	else {
-		sbuf_printf(tl->sb, "Unknown size unit ");
-		ErrToken(tl, tl->t);
-		sbuf_printf(tl->sb, ".  Legal are 'kb', 'mb' and 'gb'\n");
-		ErrWhere(tl, tl->t);
-		return (1.0);
-	}
-	NextToken(tl);
-	return (sc);
-}
-
-/*--------------------------------------------------------------------
- * Recognize and convert units of rate as { space '/' time }
- */
-
-static double
-RateUnit(struct tokenlist *tl)
-{
-	double sc = 1.0;
-
-	assert(tl->t->tok == ID);
-	sc = SizeUnit(tl);
-	Expect(tl, '/');
-	NextToken(tl);
-	sc /= TimeUnit(tl);
-	return (sc);
-}
-
-/*--------------------------------------------------------------------
- * Recognize and convert { CNUM } to unsigned value
- */
-
-static unsigned
-UintVal(struct tokenlist *tl)
-{
-	unsigned d = 0;
-	const char *p;
-
-	Expect(tl, CNUM);
-	for (p = tl->t->b; p < tl->t->e; p++) {
-		d *= 10;
-		d += *p - '0';
-	}
-	NextToken(tl);
-	return (d);
-}
-
-/*--------------------------------------------------------------------
- * Recognize and convert { CNUM [ '.' [ CNUM ] ] } to double value
- */
-
-static double
-DoubleVal(struct tokenlist *tl)
-{
-	double d = 0.0, e = 0.1;
-	const char *p;
-
-	Expect(tl, CNUM);
-	for (p = tl->t->b; p < tl->t->e; p++) {
-		d *= 10;
-		d += *p - '0';
-	}
-	NextToken(tl);
-	if (tl->t->tok != '.') 
-		return (d);
-	NextToken(tl);
-	if (tl->t->tok != CNUM)
-		return (d);
-	for (p = tl->t->b; p < tl->t->e; p++) {
-		d += (*p - '0') * e;
-		e *= 0.1;
-	}
-	NextToken(tl);
-	return (d);
-}
-
-/*--------------------------------------------------------------------*/
-
-static unsigned
-IpVal(struct tokenlist *tl)
-{
-	unsigned u, v;
-	struct token *t;
-
-	t = tl->t;
-	u = UintVal(tl);
-	if (u < 256) {
-		v = u << 24;
-		Expect(tl, '.');
-		NextToken(tl);
-		t = tl->t;
-		u = UintVal(tl);
-		if (u < 256) {
-			v |= u << 16;
-			Expect(tl, '.');
-			NextToken(tl);
-			t = tl->t;
-			u = UintVal(tl);
-			if (u < 256) {
-				v |= u << 8;
-				Expect(tl, '.');
-				NextToken(tl);
-				t = tl->t;
-				u = UintVal(tl);
-				if (u < 256) {
-					v |= u;
-					return (v);
-				}
-			}
-		}
-	}
-	sbuf_printf(tl->sb, "Illegal octet in IP number\n");
-	ErrWhere(tl, t);
-	return (0);
-}
-
-/*--------------------------------------------------------------------*/
-
-static struct var *
-HeaderVar(struct tokenlist *tl __unused, struct token *t, struct var *vh)
-{
-	char *p;
-	struct var *v;
-	int i;
-
-	v = calloc(sizeof *v, 1);
-	assert(v != NULL);
-	i = t->e - t->b;
-	p = malloc(i + 1);
-	assert(p != NULL);
-	memcpy(p, t->b, i);
-	p[i] = '\0';
-	v->name = p;
-	v->fmt = STRING;
-	asprintf(&p, "VRT_GetHdr(sp, \"\\%03o%s:\")",
-	    strlen(v->name + vh->len) + 1, v->name + vh->len);
-	assert(p != NULL);
-	v->rname = p;
-	return (v);
-}
-
-/*--------------------------------------------------------------------*/
-
-static struct var *
-FindVar(struct tokenlist *tl, struct token *t, struct var *vl)
-{
-	struct var *v;
-
-	for (v = vl; v->name != NULL; v++) {
-		if (v->fmt == HEADER  && t->e - t->b <= v->len)
-			continue;
-		if (v->fmt != HEADER  && t->e - t->b != v->len)
-			continue;
-		if (memcmp(t->b, v->name, v->len))
-			continue;
-		if (v->fmt != HEADER)
-			return (v);
-		return (HeaderVar(tl, t, v));
-	}
-	sbuf_printf(tl->sb, "Unknown variable ");
-	ErrToken(tl, t);
-	sbuf_cat(tl->sb, "\nAt: ");
-	ErrWhere(tl, t);
-	return (NULL);
-}
-
-
-/*--------------------------------------------------------------------*/
-
-static void
-TimeVal(struct tokenlist *tl)
-{
-	double v, sc;
-
-	v = DoubleVal(tl);
-	ExpectErr(tl, ID);
-	sc = TimeUnit(tl);
-	Fc(tl, 0, "(%g * %g)", v, sc);
-}
-
-static void
-SizeVal(struct tokenlist *tl)
-{
-	double v, sc;
-
-	v = DoubleVal(tl);
-	ExpectErr(tl, ID);
-	sc = SizeUnit(tl);
-	Fc(tl, 0, "(%g * %g)", v, sc);
-}
-
-static void
-RateVal(struct tokenlist *tl)
-{
-	double v, sc;
-
-	v = DoubleVal(tl);
-	ExpectErr(tl, ID);
-	sc = RateUnit(tl);
-	Fc(tl, 0, "(%g * %g)", v, sc);
-}
-
-/*--------------------------------------------------------------------*/
-
-static void
-Cond_Ip(struct var *vp, struct tokenlist *tl)
-{
-	unsigned u;
-
-	switch (tl->t->tok) {
-	case '~':
-		NextToken(tl);
-		ExpectErr(tl, ID);
-		AddRef(tl, tl->t, R_ACL);
-		Fc(tl, 1, "ip_match(%s, acl_%T)\n", vp->rname, tl->t);
-		NextToken(tl);
-		break;
-	case T_EQ:
-	case T_NEQ:
-		Fc(tl, 1, "%s %T ", vp->rname, tl->t);
-		NextToken(tl);
-		u = IpVal(tl);
-		Fc(tl, 0, "%uU /* %u.%u.%u.%u */\n", u,
-		    (u >> 24) & 0xff, (u >> 16) & 0xff,
-		    (u >> 8) & 0xff, (u) & 0xff);
-		break;
-	default:
-		sbuf_printf(tl->sb, "Illegal condition ");
-		ErrToken(tl, tl->t);
-		sbuf_printf(tl->sb, " on IP number variable\n");
-		sbuf_printf(tl->sb, "  only '==', '!=' and '~' are legal\n");
-		ErrWhere(tl, tl->t);
-		break;
-	}
-}
-
-static void
-Cond_String(struct var *vp, struct tokenlist *tl)
-{
-
-	switch (tl->t->tok) {
-	case '~':
-		Fc(tl, 1, "string_match(%s, ", vp->rname);
-		NextToken(tl);
-		ExpectErr(tl, CSTR);
-		Fc(tl, 0, "%T)\n", tl->t);
-		NextToken(tl);
-		break;
-	case T_EQ:
-	case T_NEQ:
-		Fc(tl, 1, "%sstrcmp(%s, ",
-		    tl->t->tok == T_EQ ? "!" : "", vp->rname);
-		NextToken(tl);
-		ExpectErr(tl, CSTR);
-		Fc(tl, 0, "%T)\n", tl->t);
-		NextToken(tl);
-		break;
-	default:
-		Fc(tl, 1, "%s != (void*)0", vp->rname);
-		break;
-	}
-}
-
-static void
-Cond_Int(struct var *vp, struct tokenlist *tl)
-{
-
-	Fc(tl, 1, "%s ", vp->rname);
-	switch (tl->t->tok) {
-	case T_EQ:
-	case T_NEQ:
-	case T_LEQ:
-	case T_GEQ:
-	case '>':
-	case '<':
-		Fc(tl, 0, "%T ", tl->t);
-		NextToken(tl);
-		switch(vp->fmt) {
-		case TIME:
-			TimeVal(tl);
-			break;
-		case INT:
-			ExpectErr(tl, CNUM);
-			Fc(tl, 0, "%T ", tl->t);
-			NextToken(tl);
-			break;
-		case SIZE:
-			SizeVal(tl);
-			break;
-		default:
-			sbuf_printf(tl->sb,
-			    "No conditions available for variable '%s'\n",
-			    vp->name);
-			ErrWhere(tl, tl->t);
-			return;
-		}
-		Fc(tl, 0, "\n");
-		break;
-	default:
-		sbuf_printf(tl->sb, "Illegal condition ");
-		ErrToken(tl, tl->t);
-		sbuf_printf(tl->sb, " on integer variable\n");
-		sbuf_printf(tl->sb,
-		    "  only '==', '!=', '<', '>', '<=' and '>=' are legal\n");
-		ErrWhere(tl, tl->t);
-		break;
-	}
-}
-
-static void
-Cond_Bool(struct var *vp, struct tokenlist *tl)
-{
-
-	Fc(tl, 1, "%s\n", vp->rname);
-}
-
-static void
-Cond_2(struct tokenlist *tl)
-{
-	struct var *vp;
-
-	C(tl, ",");
-	if (tl->t->tok == '!') {
-		Fc(tl, 1, "!(\n");
-		NextToken(tl);
-	} else {
-		Fc(tl, 1, "(\n");
-	}
-	if (tl->t->tok == '(') {
-		NextToken(tl);
-		Cond_0(tl);
-		ExpectErr(tl, ')');
-		NextToken(tl);
-	} else if (tl->t->tok == VAR) {
-		vp = FindVar(tl, tl->t, vars);
-		ERRCHK(tl);
-		assert(vp != NULL);
-		NextToken(tl);
-		switch (vp->fmt) {
-		case INT:	L(tl, Cond_Int(vp, tl)); break;
-		case SIZE:	L(tl, Cond_Int(vp, tl)); break;
-		case BOOL:	L(tl, Cond_Bool(vp, tl)); break;
-		case IP:	L(tl, Cond_Ip(vp, tl)); break;
-		case STRING:	L(tl, Cond_String(vp, tl)); break;
-		case TIME:	L(tl, Cond_Int(vp, tl)); break;
-		/* XXX backend == */
-		default:	
-			sbuf_printf(tl->sb,
-			    "Variable '%s'"
-			    " has no conditions that can be checked\n",
-			    vp->name);
-			ErrWhere(tl, tl->t);
-			return;
-		}
-	} else {
-		sbuf_printf(tl->sb,
-		    "Syntax error in condition, expected '(', '!' or"
-		    " variable name, found ");
-		ErrToken(tl, tl->t);
-		sbuf_printf(tl->sb, "\n");
-		ErrWhere(tl, tl->t);
-		return;
-	}
-	Fc(tl, 1, ")\n");
-}
-
-static void
-Cond_1(struct tokenlist *tl)
-{
-
-	Fc(tl, 1, "(\n");
-	L(tl, Cond_2(tl));
-	while (tl->t->tok == T_CAND) {
-		NextToken(tl);
-		Fc(tl, 1, ") && (\n");
-		L(tl, Cond_2(tl));
-	}
-	Fc(tl, 1, ")\n");
-}
-
-static void
-Cond_0(struct tokenlist *tl)
-{
-
-	Fc(tl, 1, "(\n");
-	L(tl, Cond_1(tl));
-	while (tl->t->tok == T_COR) {
-		NextToken(tl);
-		Fc(tl, 1, ") || (\n");
-		L(tl, Cond_1(tl));
-	}
-	Fc(tl, 1, ")\n");
-}
-
-static void
-Conditional(struct tokenlist *tl)
-{
-
-	ExpectErr(tl, '(');
-	NextToken(tl);
-	Fc(tl, 1, "(\n");
-	L(tl, Cond_0(tl));
-	ERRCHK(tl);
-	Fc(tl, 1, ")\n");
-	ExpectErr(tl, ')');
-	NextToken(tl);
-}
-
-/*--------------------------------------------------------------------*/
-
-static void
-IfStmt(struct tokenlist *tl)
-{
-
-	ExpectErr(tl, T_IF);
-	Fc(tl, 1, "if \n");
-	NextToken(tl);
-	L(tl, Conditional(tl));
-	ERRCHK(tl);
-	L(tl, Compound(tl));
-	ERRCHK(tl);
-	while (1) {
-		switch (tl->t->tok) {
-		case T_ELSE:
-			NextToken(tl);
-			if (tl->t->tok != T_IF) {
-				Fc(tl, 1, "else \n");
-				L(tl, Compound(tl));
-				ERRCHK(tl);
-				return;
-			}
-			/* FALLTHROUGH */
-		case T_ELSEIF:
-		case T_ELSIF:
-			Fc(tl, 1, "else if \n");
-			NextToken(tl);
-			L(tl, Conditional(tl));
-			ERRCHK(tl);
-			L(tl, Compound(tl));
-			ERRCHK(tl);
-			break;
-		default:
-			C(tl, ";");
-			return;
-		}
-	}
-}
-
-/*--------------------------------------------------------------------*/
-
-static void
-Action(struct tokenlist *tl)
-{
-	unsigned a, u;
-	struct var *vp;
-	struct token *at;
-
-	at = tl->t;
-	NextToken(tl);
-	switch (at->tok) {
-	case T_NO_NEW_CACHE:
-		Fc(tl, 1, "VCL_no_new_cache(sp);\n");
-		return;
-	case T_NO_CACHE:
-		Fc(tl, 1, "VCL_no_cache(sp);\n");
-		return;
-#define VCL_RET_MAC(a,b,c) case T_##b: \
-		Fc(tl, 1, "VRT_done(sp, VCL_RET_%s);\n", #b); \
-		tl->curproc->returns |= VCL_RET_##b; \
-		tl->curproc->returnt[c] = at; \
-		return;
-#include "vcl_returns.h"
-#undef VCL_RET_MAC
-	case T_ERROR:
-		if (tl->t->tok == CNUM)
-			a = UintVal(tl);
-		else
-			a = 0;
-		Fc(tl, 1, "VRT_error(sp, %u, ", a);
-		if (tl->t->tok == CSTR) {
-			Fc(tl, 0, "%T);\n", tl->t);
-			NextToken(tl);
-		} else
-			Fc(tl, 0, "(const char *)0);\n");
-		Fc(tl, 1, "VRT_done(sp, VCL_RET_ERROR);\n");
-		return;
-	case T_SWITCH_CONFIG:
-		ExpectErr(tl, ID);
-		Fc(tl, 1, "VCL_switch_config(\"%T\");\n", tl->t);
-		NextToken(tl);
-		return;
-	case T_CALL:
-		ExpectErr(tl, ID);
-		AddCall(tl, tl->t);
-		AddRef(tl, tl->t, R_FUNC);
-		Fc(tl, 1, "if (VGC_function_%T(sp))\n", tl->t);
-		Fc(tl, 1, "\treturn (1);\n");
-		NextToken(tl);
-		return;
-	case T_REWRITE:
-		ExpectErr(tl, CSTR);
-		Fc(tl, 1, "VCL_rewrite(%T", tl->t);
-		NextToken(tl);
-		ExpectErr(tl, CSTR);
-		Fc(tl, 0, ", %T);\n", tl->t);
-		NextToken(tl);
-		return;
-	case T_SET:
-		ExpectErr(tl, VAR);
-		vp = FindVar(tl, tl->t, vars);
-		ERRCHK(tl);
-		assert(vp != NULL);
-		Fc(tl, 1, "%s ", vp->rname);
-		NextToken(tl);
-		switch (vp->fmt) {
-		case INT:
-		case SIZE:
-		case RATE:
-		case TIME:
-		case FLOAT:
-			Fc(tl, 0, "%T ", tl->t);
-			a = tl->t->tok;
-			NextToken(tl);
-			if (a == T_MUL || a == T_DIV)
-				Fc(tl, 0, "%g", DoubleVal(tl));
-			else if (vp->fmt == TIME)
-				TimeVal(tl);
-			else if (vp->fmt == SIZE)
-				SizeVal(tl);
-			else if (vp->fmt == RATE)
-				RateVal(tl);
-			else 
-				Fc(tl, 0, "%g", DoubleVal(tl));
-			Fc(tl, 0, ";\n");
-			break;
-		case IP:
-			if (tl->t->tok == '=') {
-				NextToken(tl);
-				u = IpVal(tl);
-				Fc(tl, 0, "= %uU; /* %u.%u.%u.%u */\n",
-				    u,
-				    (u >> 24) & 0xff,
-				    (u >> 16) & 0xff,
-				    (u >> 8) & 0xff,
-				    u & 0xff);
-				break;
-			}
-			sbuf_printf(tl->sb, "Illegal assignment operator ");
-			ErrToken(tl, tl->t);
-			sbuf_printf(tl->sb,
-			    " only '=' is legal for IP numbers\n");
-			ErrWhere(tl, tl->t);
-			return;
-		case BACKEND:
-			if (tl->t->tok == '=') {
-				NextToken(tl);
-				AddRef(tl, tl->t, R_BACKEND);
-				Fc(tl, 0, "= &VGC_backend_%T;\n", tl->t);
-				NextToken(tl);
-				break;
-			}
-			sbuf_printf(tl->sb, "Illegal assignment operator ");
-			ErrToken(tl, tl->t);
-			sbuf_printf(tl->sb,
-			    " only '=' is legal for backend\n");
-			ErrWhere(tl, tl->t);
-			return;
-		default:
-			sbuf_printf(tl->sb,
-			    "Assignments not possible for '%s'\n", vp->name);
-			ErrWhere(tl, tl->t);
-			return;
-		}
-		return;
-	default:
-		sbuf_printf(tl->sb, "Expected action, 'if' or '}'\n");
-		ErrWhere(tl, at);
-		return;
-	}
-}
-
-/*--------------------------------------------------------------------*/
-
-static void
-Acl(struct tokenlist *tl)
-{
-	unsigned u, m;
-
-	NextToken(tl);
-
-	ExpectErr(tl, ID);
-	AddDef(tl, tl->t, R_ACL);
-	Fh(tl, 0, "static struct vcl_acl acl_%T[];\n", tl->t);
-	Fc(tl, 1, "static struct vcl_acl acl_%T[] = {\n", tl->t);
-	NextToken(tl);
-
-	tl->indent += INDENT;
-
-	ExpectErr(tl, '{');
-	NextToken(tl);
-
-	while (tl->t->tok == CNUM) {
-		u = IpVal(tl);
-		if (tl->t->tok == '/') {
-			NextToken(tl);
-			ExpectErr(tl, CNUM);
-			m = UintVal(tl);
-		} else
-			m = 32;
-		ExpectErr(tl, ';');
-		NextToken(tl);
-		Fc(tl, 1, "{ %11uU, %3uU }, /* %u.%u.%u.%u/%u */\n",
-		    u, m,
-		    (u >> 24) & 0xff, (u >> 16) & 0xff,
-		    (u >> 8) & 0xff, (u) & 0xff, m);
-	}
-	ExpectErr(tl, '}');
-	Fc(tl, 1, "{ %11uU, %3uU }\n", 0, 0);
-
-	tl->indent -= INDENT;
-
-	Fc(tl, 1, "};\n\n");
-	NextToken(tl);
-}
-
-/*--------------------------------------------------------------------*/
-
-static void
-Compound(struct tokenlist *tl)
-{
-
-	ExpectErr(tl, '{');
-	Fc(tl, 1, "{\n");
-	tl->indent += INDENT;
-	C(tl, ";");
-	NextToken(tl);
-	while (1) {
-		ERRCHK(tl);
-		switch (tl->t->tok) {
-		case '{':
-			Compound(tl);
-			break;
-		case T_IF:
-			IfStmt(tl);
-			break;
-		case '}':
-			NextToken(tl);
-			tl->indent -= INDENT;
-			Fc(tl, 1, "}\n");
-			return;
-		case EOI:
-			sbuf_printf(tl->sb,
-			    "End of input while in compound statement\n");
-			tl->err = 1;
-			return;
-		default:
-			Action(tl);
-			ERRCHK(tl);
-			ExpectErr(tl, ';');
-			NextToken(tl);
-			break;
-		}
-	}
-}
-
-/*--------------------------------------------------------------------*/
-
-static const char *
-CheckHostPort(const char *host, const char *port)
-{
-	struct addrinfo *res, hint;
-	int error;
-
-	memset(&hint, 0, sizeof hint);
-	hint.ai_family = PF_UNSPEC;
-	hint.ai_socktype = SOCK_STREAM;
-	error = getaddrinfo(host, port, &hint, &res);
-	if (error) 
-		return (gai_strerror(error));
-	freeaddrinfo(res);
-	return (NULL);
-}
-
-static void
-Backend(struct tokenlist *tl)
-{
-	struct var *vp;
-	struct token *t_be = NULL;
-	struct token *t_host = NULL;
-	struct token *t_port = NULL;
-	char *host = NULL;
-	char *port = NULL;
-	const char *ep;
-
-	NextToken(tl);
-	ExpectErr(tl, ID);
-	t_be = tl->t;
-	AddDef(tl, tl->t, R_BACKEND);
-	if (tl->nbackend == 0)
-		AddRef(tl, tl->t, R_BACKEND);
-	Fh(tl, 1, "#define VGC_backend_%T (VCL_conf.backend[%d])\n",
-	    tl->t, tl->nbackend);
-	Fc(tl, 0, "static void\n");
-	Fc(tl, 1, "VGC_init_backend_%T (void)\n", tl->t);
-	Fc(tl, 1, "{\n");
-	Fc(tl, 1, "\tstruct backend *backend = VGC_backend_%T;\n", tl->t);
-	Fc(tl, 1, "\tconst char *p;\n");
-	Fc(tl, 1, "\n");
-	Fc(tl, 1, "\tVRT_set_backend_name(backend, \"%T\");\n", tl->t);
-	NextToken(tl);
-	ExpectErr(tl, '{');
-	NextToken(tl);
-	while (1) {
-		if (tl->t->tok == '}')
-			break;
-		ExpectErr(tl, T_SET);
-		NextToken(tl);
-		ExpectErr(tl, VAR);
-		vp = FindVar(tl, tl->t, be_vars);
-		ERRCHK(tl);
-		assert(vp != NULL);
-		NextToken(tl);
-		ExpectErr(tl, '=');
-		NextToken(tl);
-		switch (vp->fmt) {
-		case HOSTNAME:
-			ExpectErr(tl, CSTR);
-			t_host = tl->t;
-			Fc(tl, 1, "\tp = %T;\n", tl->t);
-			Fc(tl, 1, "\t");
-			Fc(tl, 0, vp->lname, "p");
-			Fc(tl, 0, ";\n");
-			NextToken(tl);
-			break;
-		case PORTNAME:
-			ExpectErr(tl, CSTR);
-			t_port = tl->t;
-			Fc(tl, 1, "\tp = %T;\n", tl->t);
-			Fc(tl, 1, "\t");
-			Fc(tl, 0, vp->lname, "p");
-			Fc(tl, 0, ";\n");
-			NextToken(tl);
-			break;
-		default:
-			sbuf_printf(tl->sb,
-			    "Assignments not possible for '%s'\n", vp->name);
-			ErrWhere(tl, tl->t);
-			return;
-		}
-		ExpectErr(tl, ';');
-		NextToken(tl);
-	}
-	ExpectErr(tl, '}');
-	if (t_host == NULL) {
-		sbuf_printf(tl->sb, "Backend '%T' has no hostname\n", t_be);
-		ErrWhere(tl, tl->t);
-		return;
-	}
-	host = EncString(t_host);
-	ep = CheckHostPort(host, "80");
-	if (ep != NULL) {
-		sbuf_printf(tl->sb, "Backend '%T': %s\n", t_be, ep);
-		ErrWhere(tl, t_host);
-		return;
-	}
-	if (t_port != NULL) {
-		port = EncString(t_port);
-		ep = CheckHostPort(host, port);
-		if (ep != NULL) {
-			sbuf_printf(tl->sb, "Backend '%T': %s\n", t_be, ep);
-			ErrWhere(tl, t_port);
-			return;
-		}
-	}
-	
-	NextToken(tl);
-	Fc(tl, 1, "}\n");
-	Fc(tl, 0, "\n");
-	tl->nbackend++;
-}
-
-/*--------------------------------------------------------------------*/
-
-static void
-Function(struct tokenlist *tl)
-{
-
-	NextToken(tl);
-	ExpectErr(tl, ID);
-	tl->curproc = AddProc(tl, tl->t, 1);
-	tl->curproc->exists++;
-	AddDef(tl, tl->t, R_FUNC);
-	Fh(tl, 0, "static int VGC_function_%T (struct sess *sp);\n", tl->t);
-	Fc(tl, 1, "static int\n");
-	Fc(tl, 1, "VGC_function_%T (struct sess *sp)\n", tl->t);
-	NextToken(tl);
-	L(tl, Compound(tl));
-	Fc(tl, 0, "\n");
-}
-
-/*--------------------------------------------------------------------
- * Top level of parser, recognize:
- *	Function definitions
- *	Backend definitions
- *	End of input
- */
-
-static void
-Parse(struct tokenlist *tl)
-{
-
-	while (tl->t->tok != EOI) {
-		ERRCHK(tl);
-		switch (tl->t->tok) {
-		case T_ACL:
-			Acl(tl);
-			break;
-		case T_SUB:
-			Function(tl);
-			break;
-		case T_BACKEND:
-			Backend(tl);
-			break;
-		case EOI:
-			break;
-		default:
-			sbuf_printf(tl->sb,
-			    "Expected 'acl', 'sub' or 'backend', found ");
-			ErrToken(tl, tl->t);
-			sbuf_printf(tl->sb, " at\n");
-			ErrWhere(tl, tl->t);
-			return;
-		}
-	}
-}
-
-/*--------------------------------------------------------------------
- * Add a token to the token list.
- */
-
-static void
-AddToken(struct tokenlist *tl, unsigned tok, const char *b, const char *e)
-{
-	struct token *t;
-
-	t = calloc(sizeof *t, 1);
-	assert(t != NULL);
-	t->tok = tok;
-	t->b = b;
-	t->e = e;
-	TAILQ_INSERT_TAIL(&tl->tokens, t, list);
-	tl->t = t;
-	if (0) {
-		fprintf(stderr, "[%s %*.*s] ",
-		    vcl_tnames[tok],
-		    e - b, e - b, b);
-		if (tok == EOI)
-			fprintf(stderr, "\n");
-	}
-}
-
-/*--------------------------------------------------------------------
- * Lexical analysis and token generation
- */
-
-static void
-Lexer(struct tokenlist *tl, const char *b, const char *e)
-{
-	const char *p, *q;
-	unsigned u;
-
-	for (p = b; p < e; ) {
-
-		/* Skip any whitespace */
-		if (isspace(*p)) {
-			p++;
-			continue;
-		}
-
-		/* Skip '#.*\n' comments */
-		if (*p == '#') {
-			while (p < e && *p != '\n')
-				p++;
-			continue;
-		}
-
-		/* Skip C-style comments */
-		if (*p == '/' && p[1] == '*') {
-			p += 2;
-			for (p += 2; p < e; p++) {
-				if (*p == '*' && p[1] == '/') {
-					p += 2;
-					break;
-				}
-			}
-			continue;
-		}
-
-		/* Match for the fixed tokens (see token.tcl) */
-		u = vcl_fixed_token(p, &q);
-		if (u != 0) {
-			AddToken(tl, u, p, q);
-			p = q;
-			continue;
-		}
-
-		/* Match strings, with \\ and \" escapes */
-		if (*p == '"') {
-			for (q = p + 1; q < e; q++) {
-				if (*q == '\\' && q[1] == '\\')
-					q++;
-				else if (*q == '\\' && q[1] == '"')
-					q++;
-				else if (*q == '"') {
-					q++;
-					break;
-				}
-			}
-			AddToken(tl, CSTR, p, q);
-			p = q;
-			continue;
-		}
-
-		/* Match Identifiers */
-		if (isident1(*p)) {
-			for (q = p; q < e; q++)
-				if (!isident(*q))
-					break;
-			if (isvar(*q)) {
-				for (; q < e; q++)
-					if (!isvar(*q))
-						break;
-				AddToken(tl, VAR, p, q);
-			} else {
-				AddToken(tl, ID, p, q);
-			}
-			p = q;
-			continue;
-		}
-
-		/* Match numbers { [0-9]+ } */
-		if (isdigit(*p)) {
-			for (q = p; q < e; q++)
-				if (!isdigit(*q))
-					break;
-			AddToken(tl, CNUM, p, q);
-			p = q;
-			continue;
-		}
-		AddToken(tl, EOI, p, p + 1);
-		sbuf_printf(tl->sb, "Syntax error at\n");
-		ErrWhere(tl, tl->t);
-		return;
-	}
-}
-
-/*--------------------------------------------------------------------
- * Consistency check
- */
-
-static struct proc *
-AddProc(struct tokenlist *tl, struct token *t, int def)
-{
-	struct proc *p;
-
-	TAILQ_FOREACH(p, &tl->procs, list) {
-		if (!Teq(p->name, t)) 
-			continue;
-		if (def)
-			p->name = t;
-		return (p);
-	}
-	p = calloc(sizeof *p, 1);
-	assert(p != NULL);
-	p->name = t;
-	TAILQ_INIT(&p->calls);
-	TAILQ_INSERT_TAIL(&tl->procs, p, list);
-	return (p);
-}
-
-static void
-AddCall(struct tokenlist *tl, struct token *t)
-{
-	struct proccall *pc;
-	struct proc *p;
-
-	p = AddProc(tl, t, 0);
-	TAILQ_FOREACH(pc, &tl->curproc->calls, list) {
-		if (pc->p == p)
-			return;
-	}
-	pc = calloc(sizeof *pc, 1);
-	assert(pc != NULL);
-	pc->p = p;
-	pc->t = t;
-	TAILQ_INSERT_TAIL(&tl->curproc->calls, pc, list);
-}
-
-static int
-Consist_Decend(struct tokenlist *tl, struct proc *p, unsigned returns)
-{
-	unsigned u;
-	struct proccall *pc;
-
-	if (!p->exists) {
-		sbuf_printf(tl->sb, "Function %T does not exist\n", p->name);
-		return (1);
-	}
-	if (p->active) {
-		sbuf_printf(tl->sb, "Function recurses on\n");
-		ErrWhere(tl, p->name);
-		return (1);
-	}
-	u = p->returns & ~returns;
-	if (u) {
-#define VCL_RET_MAC(a, b, c) \
-		if (u & VCL_RET_##b) { \
-			sbuf_printf(tl->sb, "Illegal return for method\n"); \
-			ErrWhere(tl, p->returnt[c]); \
-		} 
-#include "vcl_returns.h"
-#undef VCL_RET_MAC
-		sbuf_printf(tl->sb, "In function\n");
-		ErrWhere(tl, p->name);
-		return (1);
-	}
-	p->active = 1;
-	TAILQ_FOREACH(pc, &p->calls, list) {
-		if (Consist_Decend(tl, pc->p, returns)) {
-			sbuf_printf(tl->sb, "\nCalled from\n");
-			ErrWhere(tl, p->name);
-			sbuf_printf(tl->sb, "at\n");
-			ErrWhere(tl, pc->t);
-			return (1);
-		}
-	}
-	p->active = 0;
-	p->called++;
-	return (0);
-}
-
-static int
-Consistency(struct tokenlist *tl)
-{
-	struct proc *p;
-	struct method *m;
-
-	TAILQ_FOREACH(p, &tl->procs, list) {
-		for(m = method_tab; m->name != NULL; m++) {
-			if (IdIs(p->name, m->defname))
-				p->called = 1;
-			if (IdIs(p->name, m->name))
-				break;
-		}
-		if (m->name == NULL) 
-			continue;
-		if (Consist_Decend(tl, p, m->returns)) {
-			sbuf_printf(tl->sb,
-			    "\nwhich is a %s method\n", m->name);
-			return (1);
-		}
-	}
-	TAILQ_FOREACH(p, &tl->procs, list) {
-		if (p->called)
-			continue;
-		sbuf_printf(tl->sb, "Function unused\n");
-		ErrWhere(tl, p->name);
-		return (1);
-	}
-	return (0);
-}
-
-/*--------------------------------------------------------------------*/
-
-static int
-CheckRefs(struct tokenlist *tl)
-{
-	struct ref *r;
-	const char *type;
-	int nerr = 0;
-
-	TAILQ_FOREACH(r, &tl->refs, list) {
-		if (r->defcnt != 0 && r->refcnt != 0)
-			continue;
-		nerr++;
-
-		switch(r->type) {
-		case R_FUNC:
-			type = "function";
-			break;
-		case R_ACL:
-			type = "acl";
-			break;
-		case R_BACKEND:
-			type = "backend";
-			break;
-		default:
-			ErrInternal(tl);
-			sbuf_printf(tl->sb, "Ref ");
-			ErrToken(tl, r->name);
-			sbuf_printf(tl->sb, " has unknown type %d\n",
-			    r->type);
-			continue;
-		}
-		if (r->defcnt == 0 && r->name->tok == METHOD) {
-			sbuf_printf(tl->sb,
-			    "No definition for method %T\n", r->name);
-			continue;
-		}
-
-		if (r->defcnt == 0) {
-			sbuf_printf(tl->sb,
-			    "Undefined %s %T, first reference:\n",
-			    type, r->name);
-			ErrWhere(tl, r->name);
-			continue;
-		} 
-
-		sbuf_printf(tl->sb, "Unused %s %T, defined:\n", type, r->name);
-		ErrWhere(tl, r->name);
-	}
-	return (nerr);
-}
-
-/*--------------------------------------------------------------------*/
-
-static void
-LocTable(struct tokenlist *tl)
-{
-	struct token *t;
-	unsigned lin, pos;
-	const char *p;
-	
-	Fh(tl, 0, "#define VGC_NREFS %u\n", tl->cnt + 1);
-	Fh(tl, 0, "static struct vrt_ref VGC_ref[VGC_NREFS];\n");
-	Fc(tl, 0, "static struct vrt_ref VGC_ref[VGC_NREFS] = {\n");
-	lin = 1;
-	pos = 0;
-	p = tl->b;
-	TAILQ_FOREACH(t, &tl->tokens, list) {
-		if (t->cnt == 0)
-			continue;
-		for (;p < t->b; p++) {
-			if (*p == '\n') {
-				lin++;
-				pos = 0;
-			} else if (*p == '\t') {
-				pos &= ~7;
-				pos += 8;
-			} else
-				pos++;
-		
-		}
-		Fc(tl, 0, "  [%3u] = { %4u, %3u, 0, \"%T\" },\n",
-		    t->cnt, lin, pos + 1, t);
-	}
-	Fc(tl, 0, "};\n");
-}
-
-
-/*--------------------------------------------------------------------*/
-
-static void
-EmitInitFunc(struct tokenlist *tl)
-{
-	struct ref *r;
-
-	Fc(tl, 0, "\nstatic void\nVGC_Init(void)\n{\n\n");
-	Fc(tl, 0, "\tVRT_alloc_backends(&VCL_conf);\n");
-	
-	TAILQ_FOREACH(r, &tl->refs, list) {
-		switch(r->type) {
-		case R_FUNC:
-			break;
-		case R_ACL:
-			break;
-		case R_BACKEND:
-			Fc(tl, 0, "\tVGC_init_backend_%T();\n", r->name);
-			break;
-		}
-	}
-	Fc(tl, 0, "}\n");
-}
-
-/*--------------------------------------------------------------------*/
-
-static void
-EmitStruct(struct tokenlist *tl)
-{
-
-	Fc(tl, 0, "\nstruct VCL_conf VCL_conf = {\n");
-	Fc(tl, 0, "\t.magic = VCL_CONF_MAGIC,\n");
-	Fc(tl, 0, "\t.init_func = VGC_Init,\n");
-	Fc(tl, 0, "\t.nbackend = %d,\n", tl->nbackend);
-	Fc(tl, 0, "\t.ref = VGC_ref,\n");
-	Fc(tl, 0, "\t.nref = VGC_NREFS,\n");
-#define VCL_RET_MAC(l,u,b)
-#define VCL_MET_MAC(l,u,b) \
-	if (FindRefStr(tl, "vcl_" #l, R_FUNC)) { \
-		Fc(tl, 0, "\t." #l "_func = VGC_function_vcl_" #l ",\n"); \
-		AddRefStr(tl, "vcl_" #l, R_FUNC); \
-	} else { \
-		Fc(tl, 0, "\t." #l "_func = VGC_function_default_vcl_" #l ",\n"); \
-	} \
-	AddRefStr(tl, "default_vcl_" #l, R_FUNC);
-#include "vcl_returns.h"
-#undef VCL_MET_MAC
-#undef VCL_RET_MAC
-	Fc(tl, 0, "};\n");
-}
-
-/*--------------------------------------------------------------------*/
-
-char *
-VCC_Compile(struct sbuf *sb, const char *b, const char *e)
-{
-	struct tokenlist tokens;
-	struct ref *r;
-	struct token *t;
-	FILE *fo;
-	char *of = NULL;
-	char buf[BUFSIZ];
-
-	memset(&tokens, 0, sizeof tokens);
-	TAILQ_INIT(&tokens.tokens);
-	TAILQ_INIT(&tokens.refs);
-	TAILQ_INIT(&tokens.procs);
-	tokens.sb = sb;
-
-	tokens.fc = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND);
-	assert(tokens.fc != NULL);
-
-	tokens.fh = sbuf_new(NULL, NULL, 0, SBUF_AUTOEXTEND);
-	assert(tokens.fh != NULL);
-
-	Fh(&tokens, 0, "extern struct VCL_conf VCL_conf;\n");
-
-	tokens.b = b;
-	if (e == NULL)
-		e = strchr(b, '\0');
-	assert(e != NULL);
-	tokens.e = e;
-	Lexer(&tokens, b, e);
-	Lexer(&tokens, vcc_default_vcl_b, vcc_default_vcl_e);
-	AddToken(&tokens, EOI, e, e);
-	if (tokens.err)
-		goto done;
-	tokens.t = TAILQ_FIRST(&tokens.tokens);
-	Parse(&tokens);
-	if (tokens.err)
-		goto done;
-	Consistency(&tokens);
-	if (tokens.err)
-		goto done;
-	LocTable(&tokens);
-
-	EmitInitFunc(&tokens);
-
-	EmitStruct(&tokens);
-
-	if (CheckRefs(&tokens))
-		goto done;
-
-	of = strdup("/tmp/vcl.XXXXXXXX");
-	assert(of != NULL);
-	mktemp(of);
-
-	sprintf(buf, 
-	    "tee /tmp/_.c |"
-	    "cc -fpic -shared -Wl,-x -o %s -x c - ", of);
-
-	fo = popen(buf, "w");
-	assert(fo != NULL);
-
-	vcl_output_lang_h(fo);
-
-	sbuf_finish(tokens.fh);
-	fputs(sbuf_data(tokens.fh), fo);
-	sbuf_delete(tokens.fh);
-
-	sbuf_finish(tokens.fc);
-	fputs(sbuf_data(tokens.fc), fo);
-	sbuf_delete(tokens.fc);
-
-	pclose(fo);
-done:
-
-	/* Free References */
-	while (!TAILQ_EMPTY(&tokens.refs)) {
-		r = TAILQ_FIRST(&tokens.refs);
-		TAILQ_REMOVE(&tokens.refs, r, list);
-		free(r);
-	}
-
-	/* Free Tokens */
-	while (!TAILQ_EMPTY(&tokens.tokens)) {
-		t = TAILQ_FIRST(&tokens.tokens);
-		TAILQ_REMOVE(&tokens.tokens, t, list);
-		free(t);
-	}
-	return (of);
-}
-
-/*--------------------------------------------------------------------*/
-
-char *
-VCC_CompileFile(struct sbuf *sb, const char *fn)
-{
-	char *f, *r;
-	int fd, i;
-	struct stat st;
-
-	fd = open(fn, O_RDONLY);
-	if (fd < 0) {
-		sbuf_printf(sb, "Cannot open file '%s': %s",
-		    fn, strerror(errno));
-		return (NULL);
-	}
-	assert(0 == fstat(fd, &st));
-	f = malloc(st.st_size + 1);
-	assert(f != NULL);
-	i = read(fd, f, st.st_size); 
-	assert(i == st.st_size);
-	f[i] = '\0';
-	r = VCC_Compile(sb, f, NULL);
-	free(f);
-	return (r);
-}
-
-/*--------------------------------------------------------------------*/
-
-static int
-VCC_T_render(FILE *f, const struct printf_info *info __unused, const void *const *args)
-{
-	const struct token *t;
-
-	t = *((const struct token * const*) (args[0]));
-	return (fprintf(f, "%*.*s",
-	    t->e - t->b, t->e - t->b, t->b));
-}
-     
-static int
-VCC_T_arginfo(const struct printf_info *info __unused, size_t n, int *argtypes)
-{
-
-	if (n > 0)
-		argtypes[0] = PA_POINTER;
-	return 1;
-}
-     
-/*--------------------------------------------------------------------*/
-
-void
-VCC_InitCompile(const char *default_vcl)
-{
-	struct var *v;
-
-	vcc_default_vcl_b = default_vcl;
-	vcc_default_vcl_e = strchr(default_vcl, '\0');
-	assert(vcc_default_vcl_e != NULL);
-	
-	register_printf_function ('T', VCC_T_render, VCC_T_arginfo);
-	vcl_init_tnames();
-	for (v = vars; v->name != NULL; v++)
-		v->len = strlen(v->name);
-	for (v = be_vars; v->name != NULL; v++)
-		v->len = strlen(v->name);
-}
-
-#endif
+const char *vrt_obj_h = 
+	"/*\n"
+	" * $Id$\n"
+	" *\n"
+	" * NB:  This file is machine generated, DO NOT EDIT!\n"
+	" *\n"
+	" * Edit vcc_gen_obj.tcl instead\n"
+	" */\n"
+	"\n"
+	"char * VRT_r_backend_host(struct backend *);\n"
+	"void VRT_l_backend_host(struct backend *, char *);\n"
+	"char * VRT_r_backend_port(struct backend *);\n"
+	"void VRT_l_backend_port(struct backend *, char *);\n"
+	"char * VRT_r_req_request(struct sess *);\n"
+	"void VRT_l_req_request(struct sess *, char *);\n"
+	"char * VRT_r_req_url(struct sess *);\n"
+	"void VRT_l_req_url(struct sess *, char *);\n"
+	"double VRT_r_obj_valid(struct sess *);\n"
+	"void VRT_l_obj_valid(struct sess *, double);\n"
+	"double VRT_r_obj_cacheable(struct sess *);\n"
+	"void VRT_l_obj_cacheable(struct sess *, double);\n"
+	"struct backend * VRT_r_obj_backend(struct sess *);\n"
+	"void VRT_l_obj_backend(struct sess *, struct backend *);\n"
+	"double VRT_r_obj_ttl(struct sess *);\n"
+	"void VRT_l_obj_ttl(struct sess *, double);\n"
+	"char * VRT_r_req_http_(struct sess *);\n"
+	"void VRT_l_req_http_(struct sess *, char *);\n"
+;


Property changes on: trunk/varnish-cache/lib/libvcl/vcc_obj.c
___________________________________________________________________
Name: svn:keywords
   + Id


Property changes on: trunk/varnish-cache/lib/libvcl/vcc_token.c
___________________________________________________________________
Name: svn:keywords
   + Id




More information about the varnish-commit mailing list