r1281 - in trunk/varnish-cache: include lib/libvcl

phk at projects.linpro.no phk at projects.linpro.no
Fri Mar 9 11:31:29 CET 2007


Author: phk
Date: 2007-03-09 11:31:29 +0100 (Fri, 09 Mar 2007)
New Revision: 1281

Modified:
   trunk/varnish-cache/include/vcl.h
   trunk/varnish-cache/include/vrt.h
   trunk/varnish-cache/lib/libvcl/vcc_acl.c
   trunk/varnish-cache/lib/libvcl/vcc_compile.c
   trunk/varnish-cache/lib/libvcl/vcc_compile.h
   trunk/varnish-cache/lib/libvcl/vcc_fixed_token.c
   trunk/varnish-cache/lib/libvcl/vcc_gen_fixed_token.tcl
   trunk/varnish-cache/lib/libvcl/vcc_token.c
   trunk/varnish-cache/lib/libvcl/vcc_token_defs.h
Log:
Implement a facility for source file modularization in the VCL
compiler.  The syntax is:

	include "filename" ;

Unlike the C preprocessors #include directive, a VCL include can
appear anywhere in the sourcefile:

	if {req.Cookie == include "cookie.vcl" ; || !req.Host } {
	}

and have cookie.vcl contain just:

	"8435398475983275293759843"


Technically this results in a change to how we account for source
code references in the counter/profile table as well, and as a result
the entire source code of the VCL program is now compiled into the
shared library for easy reference.



Modified: trunk/varnish-cache/include/vcl.h
===================================================================
--- trunk/varnish-cache/include/vcl.h	2007-03-08 10:09:18 UTC (rev 1280)
+++ trunk/varnish-cache/include/vcl.h	2007-03-09 10:31:29 UTC (rev 1281)
@@ -22,6 +22,10 @@
         unsigned        nref;
         unsigned        busy;
 
+	unsigned	nsrc;
+	const char	**srcname;
+	const char	**srcbody;
+
         void            *priv;
 
         vcl_init_f      *init_func;

Modified: trunk/varnish-cache/include/vrt.h
===================================================================
--- trunk/varnish-cache/include/vrt.h	2007-03-08 10:09:18 UTC (rev 1280)
+++ trunk/varnish-cache/include/vrt.h	2007-03-09 10:31:29 UTC (rev 1281)
@@ -40,7 +40,8 @@
 struct VCL_conf;
 
 struct vrt_ref {
-	unsigned	file;
+	unsigned	source;
+	unsigned	offset;
 	unsigned	line;
 	unsigned	pos;
 	unsigned	count;

Modified: trunk/varnish-cache/lib/libvcl/vcc_acl.c
===================================================================
--- trunk/varnish-cache/lib/libvcl/vcc_acl.c	2007-03-08 10:09:18 UTC (rev 1280)
+++ trunk/varnish-cache/lib/libvcl/vcc_acl.c	2007-03-09 10:31:29 UTC (rev 1281)
@@ -120,14 +120,14 @@
 			mask = UintVal(tl);
 		}
 		Fc(tl, 1, "{ %u, %u, %u, ", not, mask, para);
-		EncString(tl->fc, t);
+		EncToken(tl->fc, t);
 		Fc(tl, 0, ", \"");
 		if (para)
 			Fc(tl, 0, "(");
 		if (not)
 			Fc(tl, 0, "!");
 		Fc(tl, 0, "\\\"\" ");
-		EncString(tl->fc, t);
+		EncToken(tl->fc, t);
 		Fc(tl, 0, " \"\\\"");
 		if (mask)
 			Fc(tl, 0, "/%u", mask);

Modified: trunk/varnish-cache/lib/libvcl/vcc_compile.c
===================================================================
--- trunk/varnish-cache/lib/libvcl/vcc_compile.c	2007-03-08 10:09:18 UTC (rev 1280)
+++ trunk/varnish-cache/lib/libvcl/vcc_compile.c	2007-03-09 10:31:29 UTC (rev 1281)
@@ -86,8 +86,8 @@
 #include "libvcl.h"
 
 static struct method method_tab[] = {
-#define VCL_RET_MAC(a,b,c,d)
-#define VCL_MET_MAC(a,b,c)	{ "vcl_"#a, "default_vcl_"#a, c },
+#define VCL_RET_MAC(l,U,b,n)
+#define VCL_MET_MAC(l,U,m)	{ "vcl_"#l, "default_vcl_"#l, m },
 #include "vcl_returns.h"
 #undef VCL_MET_MAC
 #undef VCL_RET_MAC
@@ -170,23 +170,42 @@
 /*--------------------------------------------------------------------*/
 
 void
-EncString(struct vsb *sb, struct token *t)
+EncString(struct vsb *sb, const char *b, const char *e)
 {
-	const char *p;
 
-	assert(t->tok == CSTR);
+	if (e == NULL)
+		e = strchr(b, '\0');
+
 	vsb_cat(sb, "\"");
-	for (p = t->dec; *p != '\0'; p++) {
-		if (*p == '\\' || *p == '"')
-			vsb_printf(sb, "\\%c", *p);
-		else if (isgraph(*p))
-			vsb_printf(sb, "%c", *p);
-		else
-			vsb_printf(sb, "\\%03o", *p);
+	for (; b < e; b++) {
+		switch (*b) {
+		case '\\':
+		case '"':
+			vsb_printf(sb, "\\%c", *b);
+			break;
+		case '\n': vsb_printf(sb, "\\n"); break;
+		case '\t': vsb_printf(sb, "\\t"); break;
+		case '\r': vsb_printf(sb, "\\r"); break;
+		case ' ': vsb_printf(sb, " "); break;
+		default:
+			if (isgraph(*b))
+				vsb_printf(sb, "%c", *b);
+			else
+				vsb_printf(sb, "\\%03o", *b);
+			break;
+		}
 	}
 	vsb_cat(sb, "\"");
 }
 
+void
+EncToken(struct vsb *sb, struct token *t)
+{
+
+	assert(t->tok == CSTR);
+	EncString(sb, t->dec, NULL);
+}
+
 /*--------------------------------------------------------------------*/
 
 static int
@@ -505,7 +524,7 @@
 	Fc(tl, 1, "VRT_re_match(%s, %s)\n", str, buf);
 	Fh(tl, 0, "void *%s;\n", buf);
 	Fi(tl, 0, "\tVRT_re_init(&%s, ",buf);
-	EncString(tl->fi, re);
+	EncToken(tl->fi, re);
 	Fi(tl, 0, ");\n");
 	Ff(tl, 0, "\tVRT_re_fini(%s);\n", buf);
 }
@@ -530,7 +549,7 @@
 		    tl->t->tok == T_EQ ? "!" : "", vp->rname);
 		vcc_NextToken(tl);
 		ExpectErr(tl, CSTR);
-		EncString(tl->fc, tl->t);
+		EncToken(tl->fc, tl->t);
 		Fc(tl, 0, ")\n");
 		vcc_NextToken(tl);
 		break;
@@ -974,7 +993,7 @@
 			ExpectErr(tl, CSTR);
 			t_host = tl->t;
 			Fc(tl, 1, "\t%s ", vp->lname);
-			EncString(tl->fc, t_host);
+			EncToken(tl->fc, t_host);
 			Fc(tl, 0, ");\n");
 			vcc_NextToken(tl);
 			break;
@@ -982,7 +1001,7 @@
 			ExpectErr(tl, CSTR);
 			t_port = tl->t;
 			Fc(tl, 1, "\t%s ", vp->lname);
-			EncString(tl->fc, t_port);
+			EncToken(tl->fc, t_port);
 			Fc(tl, 0, ");\n");
 			vcc_NextToken(tl);
 			break;
@@ -1282,32 +1301,39 @@
 	return (nerr);
 }
 
-/*--------------------------------------------------------------------*/
+/*--------------------------------------------------------------------
+ * Output the location/profiling table.  For each counted token, we
+ * record source+line+charpos for the first character in the token.
+ */
 
 static void
 LocTable(struct tokenlist *tl)
 {
 	struct token *t;
-	unsigned fil, lin, pos;
+	unsigned lin, pos;
+	struct source *sp;
 	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");
-	fil = 0;
 	lin = 1;
 	pos = 0;
-	p = vcc_default_vcl_b;
+	sp = 0;
+	p = NULL;
 	TAILQ_FOREACH(t, &tl->tokens, list) {
 		if (t->cnt == 0)
 			continue;
+		assert(t->src != NULL);
+		if (t->src != sp) {
+			lin = 1;
+			pos = 0;
+			sp = t->src;
+			p = sp->b;
+		}
+		assert(sp != NULL);
+		assert(p != NULL);
 		for (;p < t->b; p++) {
-			if (p == vcc_default_vcl_e) {
-				p = tl->b;
-				fil = 1;
-				lin = 1;
-				pos = 0;
-			}
 			if (*p == '\n') {
 				lin++;
 				pos = 0;
@@ -1318,13 +1344,12 @@
 				pos++;
 
 		}
-		Fc(tl, 0, "  [%3u] = { %d, %4u, %3u, 0, \"%.*s\" },\n",
-		    t->cnt, fil, lin, pos + 1, PF(t));
+		Fc(tl, 0, "  [%3u] = { %d, %8u, %4u, %3u, 0, \"%.*s\" },\n",
+		    t->cnt, sp->idx, t->b - sp->b, lin, pos + 1, PF(t));
 	}
 	Fc(tl, 0, "};\n");
 }
 
-
 /*--------------------------------------------------------------------*/
 
 static void
@@ -1352,7 +1377,24 @@
 static void
 EmitStruct(struct tokenlist *tl)
 {
+	struct source *sp;
 
+	Fc(tl, 0, "\nconst char *srcname[%u] = {\n", tl->nsources);
+	TAILQ_FOREACH(sp, &tl->sources, list) {
+		Fc(tl, 0, "\t");
+		EncString(tl->fc, sp->name, NULL);
+		Fc(tl, 0, ",\n");
+	}
+	Fc(tl, 0, "};\n");
+	
+	Fc(tl, 0, "\nconst char *srcbody[%u] = {\n", tl->nsources);
+	TAILQ_FOREACH(sp, &tl->sources, list) {
+		Fc(tl, 0, "\t");
+		EncString(tl->fc, sp->b, sp->e);
+		Fc(tl, 0, ",\n");
+	}
+	Fc(tl, 0, "};\n");
+
 	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");
@@ -1360,6 +1402,9 @@
 	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");
+	Fc(tl, 0, "\t.nsrc = %u,\n", tl->nsources);
+	Fc(tl, 0, "\t.srcname = srcname,\n");
+	Fc(tl, 0, "\t.srcbody = srcbody,\n");
 #define VCL_RET_MAC(l,u,b,n)
 #define VCL_MET_MAC(l,u,b) \
 	if (FindRefStr(tl, "vcl_" #l, R_FUNC)) { \
@@ -1377,10 +1422,112 @@
 
 /*--------------------------------------------------------------------*/
 
-char *
-VCC_Compile(struct vsb *sb, const char *b, const char *e)
+static struct source *
+vcc_new_source(const char *b, const char *e, const char *name)
 {
-	struct tokenlist tokens;
+	struct source *sp;
+
+	if (e == NULL)
+		e = strchr(b, '\0');
+	sp = calloc(sizeof *sp, 1);
+	assert(sp != NULL);
+	sp->name = strdup(name);
+	sp->b = b;
+	sp->e = e;
+	return (sp);
+}
+
+static void
+vcc_destroy_source(struct source *sp)
+{
+
+	free(sp->name);	
+	free(sp);
+}
+
+/*--------------------------------------------------------------------*/
+
+static struct source *
+vcc_file_source(struct vsb *sb, const char *fn)
+{
+	char *f;
+	int fd, i;
+	struct stat st;
+
+	fd = open(fn, O_RDONLY);
+	if (fd < 0) {
+		vsb_printf(sb, "Cannot open file '%s': %s\n",
+		    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);
+	close(fd);
+	f[i] = '\0';
+	return (vcc_new_source(f, f + i, fn));
+}
+
+/*--------------------------------------------------------------------*/
+
+static void
+vcc_resolve_includes(struct tokenlist *tl)
+{
+	struct token *t, *t1, *t2;
+	struct source *sp;
+
+	TAILQ_FOREACH(t, &tl->tokens, list) {
+		if (t->tok != T_INCLUDE)
+			continue;
+
+		t1 = TAILQ_NEXT(t, list);
+		assert(t1 != NULL);	/* There's always an EOI */
+		if (t1->tok != CSTR) {
+			vsb_printf(tl->sb,
+			    "include not followed by string constant.\n");
+			vcc_ErrWhere(tl, t1);
+			return;
+		}
+		t2 = TAILQ_NEXT(t1, list);
+		assert(t2 != NULL);	/* There's always an EOI */
+		if (t2->tok != ';') {
+			vsb_printf(tl->sb,
+			    "include <string> not followed by semicolon.\n");
+			vcc_ErrWhere(tl, t1);
+			return;
+		}
+		assert(t2 != NULL);
+
+		sp = vcc_file_source(tl->sb, t1->dec);
+		if (sp == NULL) {
+			vcc_ErrWhere(tl, t1);
+			return;
+		}
+		TAILQ_INSERT_TAIL(&tl->sources, sp, list);
+		sp->idx = tl->nsources++;
+		tl->t = t2;
+		vcc_Lexer(tl, sp);
+
+		TAILQ_REMOVE(&tl->tokens, t, list);
+		TAILQ_REMOVE(&tl->tokens, t1, list);
+		TAILQ_REMOVE(&tl->tokens, t2, list);
+		vcc_FreeToken(t);
+		vcc_FreeToken(t1);
+		vcc_FreeToken(t2);
+		if (!tl->err)
+			vcc_resolve_includes(tl);
+		return;
+	}
+}
+
+/*--------------------------------------------------------------------*/
+
+static char *
+vcc_CompileSource(struct vsb *sb, struct source *sp)
+{
+	struct tokenlist tokens, *tl;
 	struct ref *r;
 	struct token *t;
 	FILE *fo;
@@ -1389,11 +1536,15 @@
 	int i;
 
 	memset(&tokens, 0, sizeof tokens);
-	TAILQ_INIT(&tokens.tokens);
-	TAILQ_INIT(&tokens.refs);
-	TAILQ_INIT(&tokens.procs);
+	tl = &tokens;
+	TAILQ_INIT(&tl->tokens);
+	TAILQ_INIT(&tl->refs);
+	TAILQ_INIT(&tl->procs);
+	TAILQ_INIT(&tl->sources);
 	tokens.sb = sb;
 
+	tl->nsources = 0;
+
 	tokens.fc = vsb_new(NULL, NULL, 0, VSB_AUTOEXTEND);
 	assert(tokens.fc != NULL);
 
@@ -1406,38 +1557,52 @@
 	tokens.ff = vsb_new(NULL, NULL, 0, VSB_AUTOEXTEND);
 	assert(tokens.ff != NULL);
 
-	Fh(&tokens, 0, "extern struct VCL_conf VCL_conf;\n");
+#define VCL_MET_MAC(l,U,m) \
+		tokens.fm_##l = vsb_new(NULL, NULL, 0, VSB_AUTOEXTEND); \
+		assert(tokens.fm_##l != NULL);
+#include "vcl_returns.h"
+#undef VCL_MET_MAC
 
-	Fi(&tokens, 0, "\tVRT_alloc_backends(&VCL_conf);\n");
+	Fh(tl, 0, "extern struct VCL_conf VCL_conf;\n");
 
-	tokens.b = b;
-	if (e == NULL)
-		e = strchr(b, '\0');
-	assert(e != NULL);
-	tokens.e = e;
-	vcc_Lexer(&tokens, vcc_default_vcl_b, vcc_default_vcl_e);
-	vcc_Lexer(&tokens, b, e);
-	vcc_AddToken(&tokens, EOI, e, e);
+	Fi(tl, 0, "\tVRT_alloc_backends(&VCL_conf);\n");
+
+	TAILQ_INSERT_TAIL(&tl->sources, sp, list);
+	sp->idx = tl->nsources++;
+	vcc_Lexer(tl, sp);
 	if (tokens.err)
 		goto done;
-	tokens.t = TAILQ_FIRST(&tokens.tokens);
-	Parse(&tokens);
+
+	sp = vcc_new_source(vcc_default_vcl_b, vcc_default_vcl_e, "Default");
+	TAILQ_INSERT_TAIL(&tl->sources, sp, list);
+	sp->idx = tl->nsources++;
+	vcc_Lexer(tl, sp);
+	vcc_AddToken(tl, EOI, sp->e, sp->e);
 	if (tokens.err)
 		goto done;
-	Consistency(&tokens);
+
+	vcc_resolve_includes(tl);
 	if (tokens.err)
 		goto done;
-	LocTable(&tokens);
 
-	Ff(&tokens, 0, "\tVRT_free_backends(&VCL_conf);\n");
+	tokens.t = TAILQ_FIRST(&tl->tokens);
+	Parse(tl);
+	if (tokens.err)
+		goto done;
+	Consistency(tl);
+	if (tokens.err)
+		goto done;
+	LocTable(tl);
 
-	EmitInitFunc(&tokens);
+	Ff(tl, 0, "\tVRT_free_backends(&VCL_conf);\n");
 
-	EmitFiniFunc(&tokens);
+	EmitInitFunc(tl);
 
-	EmitStruct(&tokens);
+	EmitFiniFunc(tl);
 
-	if (CheckRefs(&tokens))
+	EmitStruct(tl);
+
+	if (CheckRefs(tl))
 		goto done;
 
 	of = strdup("/tmp/vcl.XXXXXXXX");
@@ -1472,18 +1637,22 @@
 	}
 done:
 
+#define VCL_MET_MAC(l,U,m) vsb_delete(tokens.fm_##l);
+#include "vcl_returns.h"
+#undef VCL_MET_MAC
+
 	/* Free References */
-	while (!TAILQ_EMPTY(&tokens.refs)) {
-		r = TAILQ_FIRST(&tokens.refs);
-		TAILQ_REMOVE(&tokens.refs, r, list);
+	while (!TAILQ_EMPTY(&tl->refs)) {
+		r = TAILQ_FIRST(&tl->refs);
+		TAILQ_REMOVE(&tl->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);
+	while (!TAILQ_EMPTY(&tl->tokens)) {
+		t = TAILQ_FIRST(&tl->tokens);
+		TAILQ_REMOVE(&tl->tokens, t, list);
+		vcc_FreeToken(t);
 	}
 	return (of);
 }
@@ -1491,26 +1660,32 @@
 /*--------------------------------------------------------------------*/
 
 char *
+VCC_Compile(struct vsb *sb, const char *b, const char *e)
+{
+	struct source *sp;
+	char *r;
+
+	sp = vcc_new_source(b, e, "input");
+	if (sp == NULL)
+		return (NULL);
+	r = vcc_CompileSource(sb, sp);
+	vcc_destroy_source(sp);
+	return (r);
+}
+
+/*--------------------------------------------------------------------*/
+
+char *
 VCC_CompileFile(struct vsb *sb, const char *fn)
 {
-	char *f, *r;
-	int fd, i;
-	struct stat st;
+	struct source *sp;
+	char *r;
 
-	fd = open(fn, O_RDONLY);
-	if (fd < 0) {
-		vsb_printf(sb, "Cannot open file '%s': %s",
-		    fn, strerror(errno));
+	sp = vcc_file_source(sb, fn);
+	if (sp == NULL)
 		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);
+	r = vcc_CompileSource(sb, sp);
+	vcc_destroy_source(sp);
 	return (r);
 }
 

Modified: trunk/varnish-cache/lib/libvcl/vcc_compile.h
===================================================================
--- trunk/varnish-cache/lib/libvcl/vcc_compile.h	2007-03-08 10:09:18 UTC (rev 1280)
+++ trunk/varnish-cache/lib/libvcl/vcc_compile.h	2007-03-09 10:31:29 UTC (rev 1281)
@@ -34,23 +34,38 @@
 
 #define INDENT		2
 
+struct source {
+	TAILQ_ENTRY(source)	list;
+	char			*name;
+	const char		*b;
+	const char		*e;
+	unsigned		idx;
+};
+
 struct token {
 	unsigned		tok;
 	const char		*b;
 	const char		*e;
+	struct source		*src;
 	TAILQ_ENTRY(token)	list;
 	unsigned		cnt;
 	char			*dec;
 };
 
+TAILQ_HEAD(tokenhead, token);
+
 struct tokenlist {
-	TAILQ_HEAD(, token)	tokens;
-	const char		*b;
-	const char		*e;
+	struct tokenhead	tokens;
+	TAILQ_HEAD(, source)	sources;
+	unsigned		nsources;
+	struct source		*src;
 	struct token		*t;
 	int			indent;
 	unsigned		cnt;
 	struct vsb		*fc, *fh, *fi, *ff;
+#define VCL_MET_MAC(l,U,m) struct vsb *fm_##l;
+#include "vcl_returns.h"
+#undef VCL_MET_MAC
 	TAILQ_HEAD(, ref)	refs;
 	struct vsb		*sb;
 	int			err;
@@ -138,7 +153,8 @@
 unsigned UintVal(struct tokenlist *tl);
 void AddDef(struct tokenlist *tl, struct token *t, enum ref_type type);
 void AddRef(struct tokenlist *tl, struct token *t, enum ref_type type);
-void EncString(struct vsb *sb, struct token *t);
+void EncToken(struct vsb *sb, struct token *t);
+void EncString(struct vsb *sb, const char *b, const char *e);
 
 
 /* vcc_obj.c */
@@ -153,10 +169,11 @@
 void vcc__Expect(struct tokenlist *tl, unsigned tok, int line);
 int vcc_Teq(struct token *t1, struct token *t2);
 int vcc_IdIs(struct token *t, const char *p);
-void vcc_Lexer(struct tokenlist *tl, const char *b, const char *e);
+void vcc_Lexer(struct tokenlist *tl, struct source *sp);
 void vcc_NextToken(struct tokenlist *tl);
 void vcc__ErrInternal(struct tokenlist *tl, const char *func, unsigned line);
 void vcc_AddToken(struct tokenlist *tl, unsigned tok, const char *b, const char *e);
+void vcc_FreeToken(struct token *t);
 
 #define ERRCHK(tl)      do { if ((tl)->err) return; } while (0)
 #define ErrInternal(tl) vcc__ErrInternal(tl, __func__, __LINE__)

Modified: trunk/varnish-cache/lib/libvcl/vcc_fixed_token.c
===================================================================
--- trunk/varnish-cache/lib/libvcl/vcc_fixed_token.c	2007-03-08 10:09:18 UTC (rev 1280)
+++ trunk/varnish-cache/lib/libvcl/vcc_fixed_token.c	2007-03-09 10:31:29 UTC (rev 1281)
@@ -242,6 +242,12 @@
 			*q = p + 6;
 			return (T_INSERT);
 		}
+		if (p[0] == 'i' && p[1] == 'n' && p[2] == 'c' && 
+		    p[3] == 'l' && p[4] == 'u' && p[5] == 'd' && 
+		    p[6] == 'e' && !isvar(p[7])) {
+			*q = p + 7;
+			return (T_INCLUDE);
+		}
 		if (p[0] == 'i' && p[1] == 'f' && !isvar(p[2])) {
 			*q = p + 2;
 			return (T_IF);
@@ -399,6 +405,7 @@
 	vcl_tnames[T_HASH] = "hash";
 	vcl_tnames[T_IF] = "if";
 	vcl_tnames[T_INC] = "++";
+	vcl_tnames[T_INCLUDE] = "include";
 	vcl_tnames[T_INCR] = "+=";
 	vcl_tnames[T_INSERT] = "insert";
 	vcl_tnames[T_LEQ] = "<=";
@@ -455,6 +462,10 @@
 	fputs("        unsigned        nref;\n", f);
 	fputs("        unsigned        busy;\n", f);
 	fputs("\n", f);
+	fputs("	unsigned	nsrc;\n", f);
+	fputs("	const char	**srcname;\n", f);
+	fputs("	const char	**srcbody;\n", f);
+	fputs("\n", f);
 	fputs("        void            *priv;\n", f);
 	fputs("\n", f);
 	fputs("        vcl_init_f      *init_func;\n", f);
@@ -511,7 +522,8 @@
 	fputs("struct VCL_conf;\n", f);
 	fputs("\n", f);
 	fputs("struct vrt_ref {\n", f);
-	fputs("	unsigned	file;\n", f);
+	fputs("	unsigned	source;\n", f);
+	fputs("	unsigned	offset;\n", f);
 	fputs("	unsigned	line;\n", f);
 	fputs("	unsigned	pos;\n", f);
 	fputs("	unsigned	count;\n", f);

Modified: trunk/varnish-cache/lib/libvcl/vcc_gen_fixed_token.tcl
===================================================================
--- trunk/varnish-cache/lib/libvcl/vcc_gen_fixed_token.tcl	2007-03-08 10:09:18 UTC (rev 1280)
+++ trunk/varnish-cache/lib/libvcl/vcc_gen_fixed_token.tcl	2007-03-09 10:31:29 UTC (rev 1281)
@@ -61,6 +61,8 @@
 # Language keywords
 #
 set keywords {
+	include 
+
 	if else elseif elsif
 
 	func proc sub
@@ -140,6 +142,10 @@
         unsigned        nref;
         unsigned        busy;
 
+	unsigned	nsrc;
+	const char	**srcname;
+	const char	**srcbody;
+
         void            *priv;
 
         vcl_init_f      *init_func;

Modified: trunk/varnish-cache/lib/libvcl/vcc_token.c
===================================================================
--- trunk/varnish-cache/lib/libvcl/vcc_token.c	2007-03-08 10:09:18 UTC (rev 1280)
+++ trunk/varnish-cache/lib/libvcl/vcc_token.c	2007-03-09 10:31:29 UTC (rev 1281)
@@ -70,20 +70,16 @@
 {
 	unsigned lin, pos, x, y;
 	const char *p, *l, *f, *b, *e;
+	struct source *sp;
 
 	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;
-	}
+	sp = t->src;
+	f = sp->name;
+	b = sp->b;
+	e = sp->e;
 	for (l = p = b; p < t->b; p++) {
 		if (*p == '\n') {
 			lin++;
@@ -266,27 +262,44 @@
 	t->tok = tok;
 	t->b = b;
 	t->e = e;
-	TAILQ_INSERT_TAIL(&tl->tokens, t, list);
+	t->src = tl->src;
+	if (tl->t != NULL)
+		TAILQ_INSERT_AFTER(&tl->tokens, tl->t, t, list);
+	else
+		TAILQ_INSERT_TAIL(&tl->tokens, t, list);
 	tl->t = t;
 	if (0) {
 		fprintf(stderr, "[%s %.*s] ",
-		    vcl_tnames[tok],(int)(e - b), b);
+		    vcl_tnames[tok], PF(t));
 		if (tok == EOI)
 			fprintf(stderr, "\n");
 	}
 }
 
 /*--------------------------------------------------------------------
+ * Free a token
+ */
+
+void
+vcc_FreeToken(struct token *t)
+{
+
+	/* XXX: more */
+	free(t);
+}
+
+/*--------------------------------------------------------------------
  * Lexical analysis and token generation
  */
 
 void
-vcc_Lexer(struct tokenlist *tl, const char *b, const char *e)
+vcc_Lexer(struct tokenlist *tl, struct source *sp)
 {
 	const char *p, *q;
 	unsigned u;
 
-	for (p = b; p < e; ) {
+	tl->src = sp;
+	for (p = sp->b; p < sp->e; ) {
 
 		/* Skip any whitespace */
 		if (isspace(*p)) {
@@ -296,7 +309,7 @@
 
 		/* Skip '#.*\n' comments */
 		if (*p == '#') {
-			while (p < e && *p != '\n')
+			while (p < sp->e && *p != '\n')
 				p++;
 			continue;
 		}
@@ -304,7 +317,7 @@
 		/* Skip C-style comments */
 		if (*p == '/' && p[1] == '*') {
 			p += 2;
-			for (p += 2; p < e; p++) {
+			for (p += 2; p < sp->e; p++) {
 				if (*p == '*' && p[1] == '/') {
 					p += 2;
 					break;
@@ -315,7 +328,7 @@
 
 		/* Skip C++-style comments */
 		if (*p == '/' && p[1] == '/') {
-			while (p < e && *p != '\n')
+			while (p < sp->e && *p != '\n')
 				p++;
 			continue;
 		}
@@ -330,7 +343,7 @@
 
 		/* Match strings, with \\ and \" escapes */
 		if (*p == '"') {
-			for (q = p + 1; q < e; q++) {
+			for (q = p + 1; q < sp->e; q++) {
 				if (*q == '"') {
 					q++;
 					break;
@@ -352,11 +365,11 @@
 
 		/* Match Identifiers */
 		if (isident1(*p)) {
-			for (q = p; q < e; q++)
+			for (q = p; q < sp->e; q++)
 				if (!isident(*q))
 					break;
 			if (isvar(*q)) {
-				for (; q < e; q++)
+				for (; q < sp->e; q++)
 					if (!isvar(*q))
 						break;
 				vcc_AddToken(tl, VAR, p, q);
@@ -369,7 +382,7 @@
 
 		/* Match numbers { [0-9]+ } */
 		if (isdigit(*p)) {
-			for (q = p; q < e; q++)
+			for (q = p; q < sp->e; q++)
 				if (!isdigit(*q))
 					break;
 			vcc_AddToken(tl, CNUM, p, q);

Modified: trunk/varnish-cache/lib/libvcl/vcc_token_defs.h
===================================================================
--- trunk/varnish-cache/lib/libvcl/vcc_token_defs.h	2007-03-08 10:09:18 UTC (rev 1280)
+++ trunk/varnish-cache/lib/libvcl/vcc_token_defs.h	2007-03-09 10:31:29 UTC (rev 1281)
@@ -7,47 +7,48 @@
  */
 
 #define LOW_TOKEN 128
-#define T_IF 128
-#define T_ELSE 129
-#define T_ELSEIF 130
-#define T_ELSIF 131
-#define T_FUNC 132
-#define T_PROC 133
-#define T_SUB 134
-#define T_ACL 135
-#define T_BACKEND 136
-#define T_CALL 137
-#define T_NO_CACHE 138
-#define T_NO_NEW_CACHE 139
-#define T_SET 140
-#define T_REWRITE 141
-#define T_SWITCH_CONFIG 142
-#define T_ERROR 143
-#define T_LOOKUP 144
-#define T_HASH 145
-#define T_PIPE 146
-#define T_PASS 147
-#define T_FETCH 148
-#define T_INSERT 149
-#define T_DELIVER 150
-#define T_DISCARD 151
-#define T_INC 152
-#define T_DEC 153
-#define T_CAND 154
-#define T_COR 155
-#define T_LEQ 156
-#define T_EQ 157
-#define T_NEQ 158
-#define T_GEQ 159
-#define T_SHR 160
-#define T_SHL 161
-#define T_INCR 162
-#define T_DECR 163
-#define T_MUL 164
-#define T_DIV 165
-#define ID 166
-#define VAR 167
-#define CNUM 168
-#define CSTR 169
-#define EOI 170
-#define METHOD 171
+#define T_INCLUDE 128
+#define T_IF 129
+#define T_ELSE 130
+#define T_ELSEIF 131
+#define T_ELSIF 132
+#define T_FUNC 133
+#define T_PROC 134
+#define T_SUB 135
+#define T_ACL 136
+#define T_BACKEND 137
+#define T_CALL 138
+#define T_NO_CACHE 139
+#define T_NO_NEW_CACHE 140
+#define T_SET 141
+#define T_REWRITE 142
+#define T_SWITCH_CONFIG 143
+#define T_ERROR 144
+#define T_LOOKUP 145
+#define T_HASH 146
+#define T_PIPE 147
+#define T_PASS 148
+#define T_FETCH 149
+#define T_INSERT 150
+#define T_DELIVER 151
+#define T_DISCARD 152
+#define T_INC 153
+#define T_DEC 154
+#define T_CAND 155
+#define T_COR 156
+#define T_LEQ 157
+#define T_EQ 158
+#define T_NEQ 159
+#define T_GEQ 160
+#define T_SHR 161
+#define T_SHL 162
+#define T_INCR 163
+#define T_DECR 164
+#define T_MUL 165
+#define T_DIV 166
+#define ID 167
+#define VAR 168
+#define CNUM 169
+#define CSTR 170
+#define EOI 171
+#define METHOD 172




More information about the varnish-commit mailing list