[master] c4a12be Long overdue rename of libvcl to libvcc.

Poul-Henning Kamp phk at varnish-cache.org
Tue Sep 17 13:14:43 CEST 2013


commit c4a12be0d42232e32be44cdf85a0545d85d2df59
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Tue Sep 17 11:14:04 2013 +0000

    Long overdue rename of libvcl to libvcc.

diff --git a/bin/varnishd/Makefile.am b/bin/varnishd/Makefile.am
index da3480f..680deb1 100644
--- a/bin/varnishd/Makefile.am
+++ b/bin/varnishd/Makefile.am
@@ -118,7 +118,7 @@ varnishd_LDFLAGS = -export-dynamic
 varnishd_LDADD = \
 	$(top_builddir)/lib/libvarnish/libvarnish.la \
 	$(top_builddir)/lib/libvarnishcompat/libvarnishcompat.la \
-	$(top_builddir)/lib/libvcl/libvcl.la \
+	$(top_builddir)/lib/libvcc/libvcc.la \
 	$(top_builddir)/lib/libvgz/libvgz.la \
 	@JEMALLOC_LDADD@ \
 	@PCRE_LIBS@ \
diff --git a/bin/varnishd/cache/cache_backend_cfg.c b/bin/varnishd/cache/cache_backend_cfg.c
index c217845..1fdf795 100644
--- a/bin/varnishd/cache/cache_backend_cfg.c
+++ b/bin/varnishd/cache/cache_backend_cfg.c
@@ -147,7 +147,7 @@ VBE_DropRefConn(struct backend *b)
 }
 
 /*--------------------------------------------------------------------
- * See lib/libvcl/vcc_backend.c::emit_sockaddr()
+ * See lib/libvcc/vcc_backend.c::emit_sockaddr()
  */
 
 static void
diff --git a/bin/varnishd/flint.sh b/bin/varnishd/flint.sh
index 0694b78..b616a29 100755
--- a/bin/varnishd/flint.sh
+++ b/bin/varnishd/flint.sh
@@ -23,7 +23,7 @@ flexelint \
 	mgt/*.c \
 	../../lib/libvarnish/*.c \
 	../../lib/libvarnishcompat/execinfo.c \
-	../../lib/libvcl/*.c \
+	../../lib/libvcc/*.c \
 	../../lib/libvmod_std/*.c \
 	../../lib/libvmod_debug/*.c \
 	../../lib/libvmod_directors/*.c \
diff --git a/bin/varnishd/mgt/mgt_vcc.c b/bin/varnishd/mgt/mgt_vcc.c
index 28ac476..6701436 100644
--- a/bin/varnishd/mgt/mgt_vcc.c
+++ b/bin/varnishd/mgt/mgt_vcc.c
@@ -42,7 +42,7 @@
 #include "common/params.h"
 #include "mgt/mgt.h"
 
-#include "libvcl.h"
+#include "libvcc.h"
 #include "vcl.h"
 #include "vcli.h"
 #include "vcli_priv.h"
diff --git a/configure.ac b/configure.ac
index 0bd07b6..0e73cf3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -580,7 +580,7 @@ AC_CONFIG_FILES([
     lib/libvarnishapi/Makefile
     lib/libvarnishtools/Makefile
     lib/libvarnishcompat/Makefile
-    lib/libvcl/Makefile
+    lib/libvcc/Makefile
     lib/libvgz/Makefile
     lib/libvmod_debug/Makefile
     lib/libvmod_std/Makefile
diff --git a/include/Makefile.am b/include/Makefile.am
index 605a71e..5b75aca 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -42,7 +42,7 @@ nobase_noinst_HEADERS = \
 	compat/execinfo.h \
 	compat/srandomdev.h \
 	flopen.h \
-	libvcl.h \
+	libvcc.h \
 	persistent.h \
 	vcli_common.h \
 	vcli_priv.h \
@@ -84,9 +84,9 @@ nobase_pkgdatainclude_HEADERS = \
 	vsb.h \
 	vsha256.h
 
-tbl/vrt_stv_var.h tbl/vcl_returns.h tbl/vcc_types.h vcl.h vrt_obj.h: $(top_srcdir)/lib/libvcl/generate.py $(top_srcdir)/include/vrt.h
+tbl/vrt_stv_var.h tbl/vcl_returns.h tbl/vcc_types.h vcl.h vrt_obj.h: $(top_srcdir)/lib/libvcc/generate.py $(top_srcdir)/include/vrt.h
 	mkdir -p tbl
-	@PYTHON@ $(top_srcdir)/lib/libvcl/generate.py $(top_srcdir) $(top_builddir)
+	@PYTHON@ $(top_srcdir)/lib/libvcc/generate.py $(top_srcdir) $(top_builddir)
 
 BUILT_SOURCES = vcs_version.h vmod_abi.h
 MAINTAINERCLEANFILES = vcs_version.h 
diff --git a/include/libvcc.h b/include/libvcc.h
new file mode 100644
index 0000000..5c50c34
--- /dev/null
+++ b/include/libvcc.h
@@ -0,0 +1,41 @@
+/*-
+ * Copyright (c) 2006 Verdens Gang AS
+ * Copyright (c) 2006-2009 Varnish Software AS
+ * All rights reserved.
+ *
+ * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+struct vcc;
+
+struct vcc *VCC_New(void);
+void VCC_Default_VCL(struct vcc *, const char *str);
+void VCC_VCL_dir(struct vcc *, const char *str);
+void VCC_VMOD_dir(struct vcc *, const char *str);
+void VCC_Err_Unref(struct vcc *tl, unsigned u);
+void VCC_Allow_InlineC(struct vcc *tl, unsigned u);
+void VCC_Unsafe_Path(struct vcc *tl, unsigned u);
+
+char *VCC_Compile(const struct vcc *, struct vsb *sb, const char *b);
diff --git a/include/libvcl.h b/include/libvcl.h
deleted file mode 100644
index 5c50c34..0000000
--- a/include/libvcl.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*-
- * Copyright (c) 2006 Verdens Gang AS
- * Copyright (c) 2006-2009 Varnish Software AS
- * All rights reserved.
- *
- * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- */
-
-struct vcc;
-
-struct vcc *VCC_New(void);
-void VCC_Default_VCL(struct vcc *, const char *str);
-void VCC_VCL_dir(struct vcc *, const char *str);
-void VCC_VMOD_dir(struct vcc *, const char *str);
-void VCC_Err_Unref(struct vcc *tl, unsigned u);
-void VCC_Allow_InlineC(struct vcc *tl, unsigned u);
-void VCC_Unsafe_Path(struct vcc *tl, unsigned u);
-
-char *VCC_Compile(const struct vcc *, struct vsb *sb, const char *b);
diff --git a/include/vrt.h b/include/vrt.h
index 203bba1..e203168 100644
--- a/include/vrt.h
+++ b/include/vrt.h
@@ -28,7 +28,7 @@
  *
  * Runtime support for compiled VCL programs.
  *
- * XXX: When this file is changed, lib/libvcl/generate.py *MUST* be rerun.
+ * XXX: When this file is changed, lib/libvcc/generate.py *MUST* be rerun.
  */
 
 struct req;
diff --git a/lib/Makefile.am b/lib/Makefile.am
index eb67436..c0c0e60 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -5,7 +5,7 @@ SUBDIRS = \
 	libvarnish \
 	libvarnishapi \
 	libvarnishtools \
-	libvcl \
+	libvcc \
 	libvgz \
 	libvmod_debug \
 	libvmod_std \
@@ -16,7 +16,7 @@ DIST_SUBDIRS = 	\
 	libvarnish \
 	libvarnishapi \
 	libvarnishtools \
-	libvcl \
+	libvcc \
 	libvgz \
 	libvmod_debug \
 	libvmod_std \
diff --git a/lib/libvcc/Makefile.am b/lib/libvcc/Makefile.am
new file mode 100644
index 0000000..b030dc4
--- /dev/null
+++ b/lib/libvcc/Makefile.am
@@ -0,0 +1,44 @@
+#
+
+AM_LDFLAGS  = $(AM_LT_LDFLAGS)
+
+AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include
+
+pkglib_LTLIBRARIES = libvcc.la
+
+libvcc_la_LDFLAGS = $(AM_LDFLAGS) -avoid-version
+
+libvcc_la_SOURCES = \
+	vcc_compile.h \
+	vcc_token_defs.h \
+	\
+	vcc_acl.c \
+	vcc_action.c \
+	vcc_backend.c \
+	vcc_backend_util.c \
+	vcc_compile.c \
+	vcc_expr.c \
+	vcc_parse.c \
+	vcc_fixed_token.c \
+	vcc_obj.c \
+	vcc_storage.c \
+	vcc_utils.c \
+	vcc_symb.c \
+	vcc_token.c \
+	vcc_var.c \
+	vcc_vmod.c \
+	vcc_xref.c
+
+EXTRA_DIST = \
+	generate.py
+
+dist_pkgdata_SCRIPTS = \
+	vmodtool.py
+
+vcc_obj.c vcc_fixed_token.c vcc_token_defs.h: \
+	$(srcdir)/generate.py $(top_srcdir)/include/vrt.h
+	@PYTHON@ $(srcdir)/generate.py $(srcdir) $(top_builddir)
+
+CLEANFILES = $(builddir)/vcc_token_defs.h \
+	$(builddir)/vcc_fixed_token.c \
+	$(builddir)/vcc_obj.c
diff --git a/lib/libvcc/flint.lnt b/lib/libvcc/flint.lnt
new file mode 100644
index 0000000..60b3850
--- /dev/null
+++ b/lib/libvcc/flint.lnt
@@ -0,0 +1,46 @@
+-passes=3
+
+// Review all below this line
+
+-printf_code( H, void *, unsigned)
+-printf_code( ju, long long unsigned)
+-printf_code( jx, long long unsigned)
+
++libh ../../config.h
+-header(../../config.h)
+-sem(lbv_assert, r_no)
+-sem(strchr, 1p, type(1), 2n == 0 ? (@p < 1p) : (@p < 1p || @p == 0 ))
+-sem(vcc_new_source, custodial(1))
+
+-emacro((???),va_arg)	// the va_arg() macro can yield 415, 416, 661, 662
+			// 796 and 797 (out-of-bounds errors).
+
+
+-emacro(413, offsetof)	// likely null pointer
+
+// -ffc    // No automatic custody
+
+-esym(534, vsb_printf)	// Ignoring return value of function
+-esym(534, vsb_cat)	// Ignoring return value of function
+-esym(534, vsb_bcat)	// Ignoring return value of function
+-esym(534, vsb_vprintf)	// Ignoring return value of function
+-esym(534, memset)	// Ignoring return value of function
+-e788			// enum constant 'HND_Unclass' not used within defaulted switch
+-e716			// while(1) ... 
+-e786			// String concatenation within initializer
+-e732			// Loss of sign (arg. no. 2) (int to unsigned int)
+
+
+-e763	// Redundant declaration for symbol '...' previously declared
+
+
+-e737	// Loss of sign in promotion from int to unsigned int
+-e534	// Ignoring return value of function
+-e506	// Constant value boolean
+-e774	// Boolean within 'if' always evaluates to False
+-e713	// Loss of precision (assignment) (unsigned long long to long long)
+-e574	// Signed-unsigned mix with relational
+-e539	// Did not expect positive indentation
+-e734	// Loss of precision (assignment) (31 bits to 8 bits)
+-e747	// Significant prototype coercion (arg. no. 2) long
+-e712	// Loss of precision (assignment) (long long to
diff --git a/lib/libvcc/flint.sh b/lib/libvcc/flint.sh
new file mode 100755
index 0000000..3bb465a
--- /dev/null
+++ b/lib/libvcc/flint.sh
@@ -0,0 +1,10 @@
+#!/bin/sh
+
+flexelint \
+	-I/usr/include \
+	-I. \
+	-I../.. \
+	-I../../include \
+	-I../../contrib/libevent \
+	flint.lnt \
+	*.c
diff --git a/lib/libvcc/generate.py b/lib/libvcc/generate.py
new file mode 100755
index 0000000..3f20b08
--- /dev/null
+++ b/lib/libvcc/generate.py
@@ -0,0 +1,952 @@
+#!/usr/local/bin/python3.1
+#-
+# Copyright (c) 2006 Verdens Gang AS
+# Copyright (c) 2006-2013 Varnish Software AS
+# All rights reserved.
+#
+# Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# Generate various .c and .h files for the VCL compiler and the interfaces
+# for it.
+
+#######################################################################
+# These are our tokens
+
+# We could drop all words such as "include", "if" etc, and use the
+# ID type instead, but declaring them tokens makes them reserved words
+# which hopefully makes for better error messages.
+# XXX: does it actually do that ?
+
+import sys
+
+srcroot = "../.."
+buildroot = "../.."
+if len(sys.argv) == 3:
+	srcroot = sys.argv[1]
+	buildroot = sys.argv[2]
+
+tokens = {
+	"T_INC":	"++",
+	"T_DEC":	"--",
+	"T_CAND":	"&&",
+	"T_COR":	"||",
+	"T_LEQ":	"<=",
+	"T_EQ":		"==",
+	"T_NEQ":	"!=",
+	"T_GEQ":	">=",
+	"T_SHR":	">>",
+	"T_SHL":	"<<",
+	"T_INCR":	"+=",
+	"T_DECR":	"-=",
+	"T_MUL":	"*=",
+	"T_DIV":	"/=",
+	"T_NOMATCH":	"!~",
+
+	# Single char tokens, for convenience on one line
+	None:		"{}()*+-/%><=;!&.|~,",
+
+	# These have handwritten recognizers
+	"ID":		None,
+	"CNUM":		None,
+	"CSTR":		None,
+	"EOI":		None,
+	"CSRC":		None,
+}
+
+#######################################################################
+# Our methods and actions
+
+returns =(
+	('recv',		"C", ('error', 'pass', 'pipe', 'hash', 'purge',)),
+	('pipe',		"C", ('error', 'pipe',)),
+	('pass',		"C", ('error', 'restart', 'fetch',)),
+	('hash',		"C", ('lookup',)),
+	('purge',		"C", ('error', 'fetch',)),
+	('miss',		"C", ('error', 'restart', 'pass', 'fetch',)),
+	('hit',			"C", ('error', 'restart', 'pass', 'fetch', 'deliver',)),
+	('backend_fetch',	"B", ('fetch', 'abandon')),
+	('backend_response',	"B", ('deliver', 'retry', 'abandon')),
+	('deliver',		"C", ('restart', 'deliver',)),
+	('error',		"C", ('restart', 'deliver',)),
+	('init',		"", ('ok',)),
+	('fini',		"", ('ok',)),
+)
+
+#######################################################################
+# Variables available in sessions
+#
+# 'all' means all methods
+# 'client' means all methods tagged "C"
+# 'backend' means all methods tagged "B"
+# 'both' means all methods tagged "B" or "C"
+
+sp_variables = [
+	('client.ip',
+		'IP',
+		( 'both',),
+		( ),
+	),
+	('client.identity',
+		'STRING',
+		( 'both',),
+		( 'both',),
+	),
+	('server.ip',
+		'IP',
+		( 'client',),
+		( ),
+	),
+	('server.hostname',
+		'STRING',
+		( 'client',),
+		( ),
+	),
+	('server.identity',
+		'STRING',
+		( 'client',),
+		( ),
+	),
+	('server.port',
+		'INT',
+		( 'client',),
+		( ),
+	),
+	('req.method',
+		'STRING',
+		( 'client',),
+		( 'client',),
+	),
+	('req.request',
+		'STRING',
+		( 'client',),
+		( 'client',),
+	),
+	('req.url',
+		'STRING',
+		( 'client',),
+		( 'client',),
+	),
+	('req.proto',
+		'STRING',
+		( 'client',),
+		( 'client',),
+	),
+	('req.http.',
+		'HEADER',
+		( 'client',),
+		( 'client',),
+	),
+	('req.restarts',
+		'INT',
+		( 'client',),
+		( ),
+	),
+	('req.esi_level',
+		'INT',
+		( 'client',),
+		( ),
+	),
+	('req.ttl',
+		'DURATION',
+		( 'client',),
+		( 'client',),
+	),
+	('req.grace',
+		'DURATION',
+		( 'client',),
+		( 'client',),
+	),
+	('req.keep',
+		'DURATION',
+		( 'client',),
+		( 'client',),
+	),
+	('req.xid',
+		'STRING',
+		( 'client',),
+		( ),
+	),
+	('req.esi',
+		'BOOL',
+		( 'recv', 'backend_response', 'deliver', 'error',),
+		( 'recv', 'backend_response', 'deliver', 'error',),
+	),
+	('req.can_gzip',
+		'BOOL',
+		( 'client',),
+		( ),
+	),
+	('req.backend',
+		'BACKEND',
+		( 'client',),
+		( 'client',),
+	),
+	('req.backend.healthy',
+		'BOOL',
+		( 'client',),
+		( ),
+	),
+	('req.hash_ignore_busy',
+		'BOOL',
+		( 'recv',),
+		( 'recv',),
+	),
+	('req.hash_always_miss',
+		'BOOL',
+		( 'recv',),
+		( 'recv',),
+	),
+	('bereq.retries',
+		'INT',
+		( 'backend',),
+		( ),
+	),
+	('bereq.backend',
+		'BACKEND',
+		( 'pipe', 'backend', ),
+		( 'pipe', 'backend', ),
+	),
+	('bereq.backend.healthy',
+		'BOOL',
+		( 'pipe', 'backend', ),
+		( ),
+	),
+	('bereq.method',
+		'STRING',
+		( 'pipe', 'backend', ),
+		( 'pipe', 'backend', ),
+	),
+	('bereq.request',
+		'STRING',
+		( 'pipe', 'backend', ),
+		( 'pipe', 'backend', ),
+	),
+	('bereq.url',
+		'STRING',
+		( 'pipe', 'backend', ),
+		( 'pipe', 'backend', ),
+	),
+	('bereq.proto',
+		'STRING',
+		( 'pipe', 'backend', ),
+		( 'pipe', 'backend', ),
+	),
+	('bereq.http.',
+		'HEADER',
+		( 'pipe', 'backend', ),
+		( 'pipe', 'backend', ),
+	),
+	('bereq.uncacheable',
+		'BOOL',
+		( 'backend', ),
+		( 'backend', ),
+	),
+	('bereq.connect_timeout',
+		'DURATION',
+		( 'pipe', 'backend', ),
+		( 'pipe', 'backend', ),
+	),
+	('bereq.first_byte_timeout',
+		'DURATION',
+		( 'pipe', 'backend', ),
+		( 'pipe', 'backend', ),
+	),
+	('bereq.between_bytes_timeout',
+		'DURATION',
+		( 'pipe', 'backend', ),
+		( 'pipe', 'backend', ),
+	),
+	('beresp.proto',
+		'STRING',
+		( 'backend_response',),
+		( 'backend_response',),
+	),
+	('beresp.status',
+		'INT',
+		( 'backend_response',),
+		( 'backend_response',),
+	),
+	('beresp.response',
+		'STRING',
+		( 'backend_response',),
+		( 'backend_response',),
+	),
+	('beresp.http.',
+		'HEADER',
+		( 'backend_response',),
+		( 'backend_response',),
+	),
+	('beresp.do_esi',
+		'BOOL',
+		( 'backend_response',),
+		( 'backend_response',),
+	),
+	('beresp.do_stream',
+		'BOOL',
+		( 'backend_response',),
+		( 'backend_response',),
+	),
+	('beresp.do_gzip',
+		'BOOL',
+		( 'backend_response',),
+		( 'backend_response',),
+	),
+	('beresp.do_gunzip',
+		'BOOL',
+		( 'backend_response',),
+		( 'backend_response',),
+	),
+	('beresp.uncacheable',
+		'BOOL',
+		( 'backend_response',),
+		( 'backend_response',),
+	),
+	('beresp.ttl',
+		'DURATION',
+		( 'backend_response',),
+		( 'backend_response',),
+	),
+	('beresp.grace',
+		'DURATION',
+		( 'backend_response',),
+		( 'backend_response',),
+	),
+	('beresp.keep',
+		'DURATION',
+		( 'backend_response',),
+		( 'backend_response',),
+	),
+	('beresp.backend.name',
+		'STRING',
+		( 'backend_response',),
+		( ),
+	),
+	('beresp.backend.ip',
+		'IP',
+		( 'backend_response',),
+		( ),
+	),
+	('beresp.backend.port',
+		'INT',
+		( 'backend_response',),
+		( ),
+	),
+	('beresp.storage',
+		'STRING',
+		( 'backend_response',),
+		( 'backend_response',),
+	),
+	('obj.proto',
+		'STRING',
+		( 'hit', 'error',),
+		( 'hit', 'error',),
+	),
+	('obj.status',
+		'INT',
+		( 'error',),
+		( 'error',),
+	),
+	('obj.response',
+		'STRING',
+		( 'error',),
+		( 'error',),
+	),
+	('obj.hits',
+		'INT',
+		( 'hit', 'deliver',),
+		( 'hit', 'deliver',),
+	),
+	('obj.http.',
+		'HEADER',
+		( 'hit', 'error',),
+		( 'error',),		# XXX ?
+	),
+	('obj.ttl',
+		'DURATION',
+		( 'hit', 'error',),
+		( 'hit', 'error',),
+	),
+	('obj.grace',
+		'DURATION',
+		( 'hit', 'error',),
+		( 'hit', 'error',),
+	),
+	('obj.keep',
+		'DURATION',
+		( 'hit', 'error',),
+		( 'hit', 'error',),
+	),
+	('obj.last_use',
+		'TIME',
+		( 'hit', 'deliver',),
+		( 'hit', 'deliver',),
+	),
+	('obj.uncacheable',
+		'BOOL',
+		( 'hit', 'deliver', 'error',),
+		( ),
+	),
+	('resp.proto',
+		'STRING',
+		( 'deliver',),
+		( 'deliver',),
+	),
+	('resp.status',
+		'INT',
+		( 'deliver',),
+		( 'deliver',),
+	),
+	('resp.response',
+		'STRING',
+		( 'deliver',),
+		( 'deliver',),
+	),
+	('resp.http.',
+		'HEADER',
+		( 'deliver',),
+		( 'deliver',),
+	),
+	('now',
+		'TIME',
+		( 'all',),
+		( ),
+	),
+]
+
+stv_variables = (
+	('free_space',	'BYTES',	"0."),
+	('used_space',	'BYTES',	"0."),
+	('happy',	'BOOL',		"0"),
+)
+
+#######################################################################
+# VCL to C type conversion
+
+vcltypes = {
+	'STRING_LIST':	"void*",
+}
+
+fi = open(srcroot + "/include/vrt.h")
+
+for i in fi:
+	j = i.split();
+	if len(j) < 3:
+		continue
+	if j[0] != "typedef":
+		continue
+	if j[-1][-1] != ";":
+		continue
+	if j[-1][:4] != "VCL_":
+		continue
+	d = " ".join(j[1:-1])
+	vcltypes[j[-1][4:-1]] = d
+fi.close()
+
+#######################################################################
+# Nothing is easily configurable below this line.
+#######################################################################
+
+import sys
+import copy
+
+#######################################################################
+# Emit a function to recognize tokens in a string
+
+def emit_vcl_fixed_token(fo, tokens):
+
+	recog = list()
+	emit = dict()
+	for i in tokens:
+		j = tokens[i]
+		if (j != None):
+			recog.append(j)
+			emit[j] = i
+
+	recog.sort()
+	rrecog = copy.copy(recog)
+	rrecog.sort(key = lambda x: -len(x))
+
+	fo.write("""
+#define M1()\tdo {*q = p + 1; return (p[0]); } while (0)
+#define M2(c,t)\tdo {if (p[1] == (c)) { *q = p + 2; return (t); }} while (0)
+
+unsigned
+vcl_fixed_token(const char *p, const char **q)
+{
+
+\tswitch (p[0]) {
+""")
+	last_initial = None
+	for i in recog:
+		if (i[0] == last_initial):
+			continue
+		last_initial = i[0]
+		fo.write("\tcase '%s':\n" % last_initial)
+		need_ret = True
+		for j in rrecog:
+			if (j[0] != last_initial):
+				continue
+			if len(j) == 2:
+				fo.write("\t\tM2('%s', %s);\n" %
+				    (j[1], emit[j]))
+			elif len(j) == 1:
+				fo.write("\t\tM1();\n")
+				need_ret = False
+			else:
+				fo.write("\t\tif (")
+				k = 1
+				l = len(j)
+				while (k < l):
+					fo.write("p[%d] == '%s'" % (k, j[k]))
+					fo.write(" &&")
+					if (k % 3) == 0:
+						fo.write("\n\t\t    ")
+					else:
+						fo.write(" ")
+					k += 1
+				fo.write("!isvar(p[%d])) {\n" % l)
+				fo.write("\t\t\t*q = p + %d;\n" % l)
+				fo.write("\t\t\treturn (%s);\n" % emit[j])
+				fo.write("\t\t}\n")
+		if need_ret:
+			fo.write("\t\treturn (0);\n")
+	fo.write("\tdefault:\n\t\treturn (0);\n\t}\n}\n")
+
+#######################################################################
+# Emit the vcl_tnames (token->string) conversion array
+
+def emit_vcl_tnames(fo, tokens):
+	fo.write("\nconst char * const vcl_tnames[256] = {\n")
+	l = list(tokens.keys())
+	l.sort()
+	for i in l:
+		j = tokens[i]
+		if j == None:
+			j = i
+		if i[0] == "'":
+			j = i
+		fo.write("\t[%s] = \"%s\",\n" % (i, j))
+	fo.write("};\n")
+
+#######################################################################
+# Read a C-source file and spit out code that outputs it with VSB_cat()
+
+def emit_file(fo, fn):
+	fi = open(fn)
+	fc = fi.read()
+	fi.close()
+
+	w = 66		# Width of lines, after white space prefix
+	maxlen = 10240	# Max length of string literal
+
+	x = 0
+	l = 0
+	fo.write("\n\t/* %s */\n\n" % fn)
+	for c in fc:
+		if l == 0:
+			fo.write("\tVSB_cat(sb, \"")
+			l += 12
+			x += 12
+		if x == 0:
+			fo.write("\t    \"")
+		d = c
+		if c == '\n':
+			d = "\\n"
+		elif c == '\t':
+			d = "\\t"
+		elif c == '"':
+			d = "\\\""
+		elif c == '\\':
+			d = "\\\\"
+
+		if c == '\n' and x > w - 20:
+			fo.write(d + "\"\n")
+			x = 0
+			continue
+		if c.isspace() and x > w - 10:
+			fo.write(d + "\"\n")
+			x = 0
+			continue
+
+		fo.write(d)
+		x += len(d)
+		l += len(d)
+		if l > maxlen:
+			fo.write("\");\n")
+			l = 0;
+			x = 0
+		if x > w - 3:
+			fo.write("\"\n")
+			x = 0
+	if x != 0:
+		fo.write("\"")
+	if l != 0:
+		fo.write("\t);\n")
+
+#######################################################################
+
+def polish_tokens(tokens):
+	# Expand single char tokens
+	st = tokens[None]
+	del tokens[None]
+
+	for i in st:
+		tokens["'" + i + "'"] = i
+#######################################################################
+
+def file_header(fo):
+	fo.write("""/*
+ * NB:  This file is machine generated, DO NOT EDIT!
+ *
+ * Edit and run generate.py instead
+ */
+""")
+
+#######################################################################
+
+polish_tokens(tokens)
+
+fo = open(buildroot + "/lib/libvcc/vcc_token_defs.h", "w")
+
+file_header(fo)
+
+j = 128
+l = list(tokens.keys())
+l.sort()
+for i in l:
+	if i[0] == "'":
+		continue
+	fo.write("#define\t%s %d\n" % (i, j))
+	j += 1
+	assert j < 256
+
+fo.close()
+
+#######################################################################
+
+rets = dict()
+vcls = list()
+vcls_client = list()
+vcls_backend = list()
+for i in returns:
+	vcls.append(i[0])
+	for j in i[1]:
+		if j == "B":
+			vcls_backend.append(i[0])
+		elif j == "C":
+			vcls_client.append(i[0])
+	for j in i[2]:
+		rets[j] = True
+
+#######################################################################
+
+fo = open(buildroot + "/include/tbl/vcl_returns.h", "w")
+
+file_header(fo)
+
+fo.write("\n/*lint -save -e525 -e539 */\n")
+
+fo.write("\n#ifdef VCL_RET_MAC\n")
+l = list(rets.keys())
+l.sort()
+for i in l:
+	fo.write("VCL_RET_MAC(%s, %s" % (i.lower(), i.upper()))
+	s=", "
+	for j in returns:
+		if i in j[2]:
+			fo.write("%sVCL_MET_%s" % (s, j[0].upper()))
+			s = " | "
+	fo.write(")\n")
+fo.write("#endif\n")
+
+fo.write("\n#ifdef VCL_MET_MAC\n")
+for i in returns:
+	fo.write("VCL_MET_MAC(%s,%s,\n" % (i[0].lower(), i[0].upper()))
+	p = " ("
+	for j in i[2]:
+		fo.write("    %s(1U << VCL_RET_%s)\n" % (p, j.upper()))
+		p = "| "
+	fo.write("))\n")
+fo.write("#endif\n")
+fo.write("\n/*lint -restore */\n")
+fo.close()
+
+#######################################################################
+
+fo = open(buildroot + "/include/vcl.h", "w")
+
+file_header(fo)
+
+fo.write("""
+struct vrt_ctx;
+struct req;
+struct busyobj;
+struct ws;
+struct cli;
+struct worker;
+
+typedef int vcl_init_f(struct cli *);
+typedef void vcl_fini_f(struct cli *);
+typedef int vcl_func_f(const struct vrt_ctx *ctx);
+""")
+
+
+fo.write("\n/* VCL Methods */\n")
+n = 0
+for i in returns:
+	fo.write("#define VCL_MET_%s\t\t(1U << %d)\n" % (i[0].upper(), n))
+	n += 1
+
+fo.write("\n#define VCL_MET_MAX\t\t%d\n" % n)
+fo.write("\n#define VCL_MET_MASK\t\t0x%x\n" % ((1 << n) - 1))
+
+
+fo.write("\n/* VCL Returns */\n")
+n = 0
+l = list(rets.keys())
+l.sort()
+for i in l:
+	fo.write("#define VCL_RET_%s\t\t%d\n" % (i.upper(), n))
+	n += 1
+
+fo.write("\n#define VCL_RET_MAX\t\t%d\n" % n)
+
+
+fo.write("""
+struct VCL_conf {
+	unsigned	magic;
+#define VCL_CONF_MAGIC	0x7406c509	/* from /dev/random */
+
+	struct director	**director;
+	unsigned	ndirector;
+	struct vrt_ref	*ref;
+	unsigned	nref;
+	unsigned	busy;
+	unsigned	discard;
+
+	unsigned	nsrc;
+	const char	**srcname;
+	const char	**srcbody;
+
+	vcl_init_f	*init_vcl;
+	vcl_fini_f	*fini_vcl;
+""")
+
+for i in returns:
+	fo.write("\tvcl_func_f\t*" + i[0] + "_func;\n")
+
+fo.write("""
+};
+""")
+
+fo.close()
+
+#######################################################################
+
+def restrict(fo, spec):
+	d = dict()
+	for j in spec:
+		if j == 'all':
+			for i in vcls:
+				d[i] = True
+		elif j == 'backend':
+			for i in vcls_backend:
+				d[i] = True
+		elif j == 'client':
+			for i in vcls_client:
+				d[i] = True
+		elif j == 'both':
+			for i in vcls_client:
+				d[i] = True
+			for i in vcls_backend:
+				d[i] = True
+		else:
+			assert j in vcls
+			d[j] = True
+	p = ""
+	n = 0
+	l = list(d.keys())
+	l.sort()
+	w = 0
+	fo.write("\t\t")
+	for j in l:
+		x = p + "VCL_MET_" + j.upper()
+		if w + len(x) > 60:
+			fo.write("\n\t\t")
+			w = 0
+		fo.write(x)
+		w += len(x)
+		p = " | "
+	if len(d) == 0:
+		fo.write("0")
+	fo.write(",\n")
+
+#######################################################################
+
+fh = open(buildroot + "/include/vrt_obj.h", "w")
+file_header(fh)
+
+fo = open(buildroot + "/lib/libvcc/vcc_obj.c", "w")
+file_header(fo)
+
+fo.write("""
+#include "config.h"
+
+#include <stdio.h>
+
+#include "vcc_compile.h"
+
+const struct var vcc_vars[] = {
+""")
+
+sp_variables.sort()
+for i in sp_variables:
+	typ = i[1]
+	cnam = i[0].replace(".", "_")
+	ctyp = vcltypes[typ]
+
+	fo.write("\t{ \"%s\", %s, %d,\n" % (i[0], typ, len(i[0])))
+
+	if len(i[2]) == 0:
+		fo.write('\t    NULL,\t/* No reads allowed */\n')
+	elif typ == "HEADER":
+		fo.write('\t    "HDR_')
+		fo.write(i[0].split(".")[0].upper())
+		fo.write('",\n')
+	else:
+		fo.write('\t    "VRT_r_%s(ctx)",\n' % cnam)
+		fh.write(ctyp + " VRT_r_%s(const struct vrt_ctx *);\n" % cnam )
+	restrict(fo, i[2])
+
+	if len(i[3]) == 0:
+		fo.write('\t    NULL,\t/* No writes allowed */\n')
+	elif typ == "HEADER":
+		fo.write('\t    "HDR_')
+		fo.write(i[0].split(".")[0].upper())
+		fo.write('",\n')
+	else:
+		fo.write('\t    "VRT_l_%s(ctx, ",\n' % cnam)
+		fh.write("void VRT_l_%s(const struct vrt_ctx *, " % cnam)
+		if typ != "STRING":
+			fh.write(ctyp + ");\n")
+		else:
+			fh.write(ctyp + ", ...);\n")
+	restrict(fo, i[3])
+
+	fo.write("\t},\n")
+
+fo.write("\t{ NULL }\n};\n")
+
+for i in stv_variables:
+	fh.write(vcltypes[i[1]] + " VRT_Stv_" + i[0] + "(const char *);\n")
+
+fo.close()
+fh.close()
+
+#######################################################################
+
+fo = open(buildroot + "/lib/libvcc/vcc_fixed_token.c", "w")
+
+file_header(fo)
+fo.write("""
+
+#include "config.h"
+
+#include <ctype.h>
+#include <stdio.h>
+
+#include "vcc_compile.h"
+""")
+
+emit_vcl_fixed_token(fo, tokens)
+emit_vcl_tnames(fo, tokens)
+
+fo.write("""
+void
+vcl_output_lang_h(struct vsb *sb)
+{
+""")
+
+emit_file(fo, buildroot + "/include/vcl.h")
+emit_file(fo, srcroot + "/include/vrt.h")
+emit_file(fo, buildroot + "/include/vrt_obj.h")
+
+fo.write("""
+}
+""")
+
+fo.close()
+
+#######################################################################
+ft = open(buildroot + "/include/tbl/vcc_types.h", "w")
+file_header(ft)
+
+ft.write("/*lint -save -e525 -e539 */\n")
+
+i = list(vcltypes.keys())
+i.sort()
+for j in i:
+	ft.write("VCC_TYPE(" + j + ")\n")
+ft.write("/*lint -restore */\n")
+ft.close()
+
+#######################################################################
+
+fo = open(buildroot + "/include/tbl/vrt_stv_var.h", "w")
+
+file_header(fo)
+
+fo.write("""
+#ifndef VRTSTVTYPE
+#define VRTSTVTYPE(ct)
+#define VRTSTVTYPEX
+#endif
+#ifndef VRTSTVVAR
+#define VRTSTVVAR(nm, vtype, ctype, dval)
+#define VRTSTVVARX
+#endif
+""")
+
+x=dict()
+for i in stv_variables:
+	ct = vcltypes[i[1]]
+	if not ct in x:
+		fo.write("VRTSTVTYPE(" + ct + ")\n")
+		x[ct] = 1
+	fo.write("VRTSTVVAR(" + i[0] + ",\t" + i[1] + ",\t")
+	fo.write(ct + ",\t" + i[2] + ")")
+	fo.write("\n")
+
+fo.write("""
+#ifdef VRTSTVTYPEX
+#undef VRTSTVTYPEX
+#undef VRTSTVTYPE
+#endif
+#ifdef VRTSTVVARX
+#undef VRTSTVVARX
+#undef VRTSTVVAR
+#endif
+""")
+
+fo.close
diff --git a/lib/libvcc/vcc_acl.c b/lib/libvcc/vcc_acl.c
new file mode 100644
index 0000000..fa8a7d7
--- /dev/null
+++ b/lib/libvcc/vcc_acl.c
@@ -0,0 +1,502 @@
+/*-
+ * Copyright (c) 2006 Verdens Gang AS
+ * Copyright (c) 2006-2010 Varnish Software AS
+ * All rights reserved.
+ *
+ * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+
+#include <netdb.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "vcc_compile.h"
+
+#include "vrt.h"
+
+struct acl_e {
+	VTAILQ_ENTRY(acl_e)	list;
+	unsigned char		data[VRT_ACL_MAXADDR + 1];
+	unsigned		mask;
+	unsigned		not;
+	unsigned		para;
+	struct token		*t_addr;
+	struct token		*t_mask;
+};
+
+/* Compare two acl rules for ordering */
+
+#define CMP(a, b)							\
+	do {								\
+		if ((a) < (b))						\
+			return (-1);					\
+		else if ((b) < (a))					\
+			return (1);					\
+	} while (0)
+
+static int
+vcl_acl_cmp(struct acl_e *ae1, struct acl_e *ae2)
+{
+	unsigned char *p1, *p2;
+	unsigned m;
+
+	p1 = ae1->data;
+	p2 = ae2->data;
+	m = ae1->mask;
+	if (ae2->mask < m)
+		m = ae2->mask;
+	for (; m >= 8; m -= 8) {
+		CMP(*p1, *p2);
+		p1++;
+		p2++;
+	}
+	if (m) {
+		m = 0xff00 >> m;
+		m &= 0xff;
+		CMP(*p1 & m, *p2 & m);
+	}
+	/* Long mask is less than short mask */
+	CMP(ae2->mask, ae1->mask);
+
+	return (0);
+}
+
+
+static void
+vcc_acl_add_entry(struct vcc *tl, const struct acl_e *ae, int l,
+    const unsigned char *u, int fam)
+{
+	struct acl_e *ae2, *aen;
+	int i;
+
+	if (fam == PF_INET && ae->mask > 32) {
+		VSB_printf(tl->sb,
+		    "Too wide mask (%u) for IPv4 address\n", ae->mask);
+		if (ae->t_mask != NULL)
+			vcc_ErrWhere(tl, ae->t_mask);
+		else
+			vcc_ErrWhere(tl, ae->t_addr);
+		return;
+	}
+	if (fam == PF_INET6 && ae->mask > 128) {
+		VSB_printf(tl->sb,
+		    "Too wide mask (%u) for IPv6 address\n", ae->mask);
+		vcc_ErrWhere(tl, ae->t_mask);
+		return;
+	}
+
+	/* Make a copy from the template */
+	aen = TlAlloc(tl, sizeof *ae2);
+	AN(aen);
+	*aen = *ae;
+
+	/* We treat family as part of address, it saves code */
+	assert(fam <= 0xff);
+	aen->data[0] = fam & 0xff;
+	aen->mask += 8;
+
+	memcpy(aen->data + 1, u, l);
+
+	VTAILQ_FOREACH(ae2, &tl->acl, list) {
+		i = vcl_acl_cmp(aen, ae2);
+		if (i == 0) {
+			/*
+			 * If the two rules agree, silently ignore it
+			 * XXX: is that counter intuitive ?
+			 */
+			if (aen->not == ae2->not)
+				return;
+			VSB_printf(tl->sb, "Conflicting ACL entries:\n");
+			vcc_ErrWhere(tl, ae2->t_addr);
+			VSB_printf(tl->sb, "vs:\n");
+			vcc_ErrWhere(tl, aen->t_addr);
+			return;
+		}
+		/*
+		 * We could eliminate pointless rules here, for instance in:
+		 *	"10.1.0.1";
+		 *	"10.1";
+		 * The first rule is clearly pointless, as the second one
+		 * covers it.
+		 *
+		 * We do not do this however, because the shmlog may
+		 * be used to gather statistics.
+		 */
+		if (i < 0) {
+			VTAILQ_INSERT_BEFORE(ae2, aen, list);
+			return;
+		}
+	}
+	VTAILQ_INSERT_TAIL(&tl->acl, aen, list);
+}
+
+static void
+vcc_acl_try_getaddrinfo(struct vcc *tl, struct acl_e *ae)
+{
+	struct addrinfo *res0, *res, hint;
+	struct sockaddr_in *sin4;
+	struct sockaddr_in6 *sin6;
+	unsigned char *u, i4, i6;
+	int error;
+
+	memset(&hint, 0, sizeof hint);
+	hint.ai_family = PF_UNSPEC;
+	hint.ai_socktype = SOCK_STREAM;
+	error = getaddrinfo(ae->t_addr->dec, "0", &hint, &res0);
+	if (error) {
+		if (ae->para) {
+			VSB_printf(tl->sb,
+			    "Warning: %s ignored\n  -- %s\n",
+			    ae->t_addr->dec, gai_strerror(error));
+			Fh(tl, 1, "/* Ignored ACL entry: %s%s",
+			    ae->para ? "\"(\" " : "", ae->not ? "\"!\" " : "");
+			EncToken(tl->fh, ae->t_addr);
+			if (ae->t_mask)
+				Fh(tl, 0, "/%u", ae->mask);
+			Fh(tl, 0, "%s\n", ae->para ? " \")\"" : "");
+			Fh(tl, 1, " * getaddrinfo:  %s */\n",
+			     gai_strerror(error));
+		} else {
+			VSB_printf(tl->sb,
+			    "DNS lookup(%s): %s\n",
+			    ae->t_addr->dec, gai_strerror(error));
+			vcc_ErrWhere(tl, ae->t_addr);
+		}
+		return;
+	}
+
+	i4 = i6 = 0;
+	for(res = res0; res != NULL; res = res->ai_next) {
+		switch(res->ai_family) {
+		case PF_INET:
+			assert(PF_INET < 256);
+			sin4 = (void*)res->ai_addr;
+			assert(sizeof(sin4->sin_addr) == 4);
+			u = (void*)&sin4->sin_addr;
+			if (ae->t_mask == NULL)
+				ae->mask = 32;
+			i4++;
+			vcc_acl_add_entry(tl, ae, 4, u, res->ai_family);
+			break;
+		case PF_INET6:
+			assert(PF_INET6 < 256);
+			sin6 = (void*)res->ai_addr;
+			assert(sizeof(sin6->sin6_addr) == 16);
+			u = (void*)&sin6->sin6_addr;
+			if (ae->t_mask == NULL)
+				ae->mask = 128;
+			i6++;
+			vcc_acl_add_entry(tl, ae, 16, u, res->ai_family);
+			break;
+		default:
+			VSB_printf(tl->sb,
+			    "Ignoring unknown protocol family (%d) for %.*s\n",
+				res->ai_family, PF(ae->t_addr));
+			continue;
+		}
+		ERRCHK(tl);
+	}
+	freeaddrinfo(res0);
+
+	if (ae->t_mask != NULL && i4 > 0 && i6 > 0) {
+		VSB_printf(tl->sb,
+		    "Mask (%u) specified, but string resolves to"
+		    " both IPv4 and IPv6 addresses.\n", ae->mask);
+		vcc_ErrWhere(tl, ae->t_mask);
+		return;
+	}
+}
+
+/*--------------------------------------------------------------------
+ * Ancient stupidity on the part of X/Open and other standards orgs
+ * dictate that "192.168" be translated to 192.0.0.168.  Ever since
+ * CIDR happened, "192.168/16" notation has been used, but appearantly
+ * no API supports parsing this, so roll our own.
+ */
+
+static int
+vcc_acl_try_netnotation(struct vcc *tl, struct acl_e *ae)
+{
+	unsigned char b[4];
+	int i, j, k;
+	unsigned u;
+	const char *p;
+
+	memset(b, 0, sizeof b);
+	p = ae->t_addr->dec;
+	for (i = 0; i < 4; i++) {
+		j = sscanf(p, "%u%n", &u, &k);
+		if (j != 1)
+			return (0);
+		if (u & ~0xff)
+			return (0);
+		b[i] = (unsigned char)u;
+		if (p[k] == '\0')
+			break;
+		if (p[k] != '.')
+			return (0);
+		p += k + 1;
+	}
+	if (ae->t_mask == NULL)
+		ae->mask = 8 + 8 * i;
+	vcc_acl_add_entry(tl, ae, 4, b, AF_INET);
+	return (1);
+}
+
+static void
+vcc_acl_entry(struct vcc *tl)
+{
+	struct acl_e *ae;
+
+	ae = TlAlloc(tl, sizeof *ae);
+	AN(ae);
+
+	if (tl->t->tok == '!') {
+		ae->not = 1;
+		vcc_NextToken(tl);
+	}
+
+	if (tl->t->tok == '(') {
+		ae->para = 1;
+		vcc_NextToken(tl);
+	}
+
+	if (!ae->not && tl->t->tok == '!') {
+		ae->not = 1;
+		vcc_NextToken(tl);
+	}
+
+	ExpectErr(tl, CSTR);
+	ae->t_addr = tl->t;
+	vcc_NextToken(tl);
+
+	if (tl->t->tok == '/') {
+		vcc_NextToken(tl);
+		ae->t_mask = tl->t;
+		ExpectErr(tl, CNUM);
+		ae->mask = vcc_UintVal(tl);
+	}
+
+	if (ae->para)
+		SkipToken(tl, ')');
+
+	if (!vcc_acl_try_netnotation(tl, ae)) {
+		ERRCHK(tl);
+		vcc_acl_try_getaddrinfo(tl, ae);
+	}
+	ERRCHK(tl);
+}
+
+/*********************************************************************
+ * Emit a function to match the ACL we have collected
+ */
+
+/*
+ * XXX: this is semi-silly.  We try really hard to not depend in the
+ * XXX: systems include files while compiling VCL, but we need to know
+ * XXX: the size of the sa_familiy member.
+ * XXX: FlexeLint complains about these antics, so isolate it in a
+ * XXX: separate function.
+ */
+
+/*lint -save -e506 -e774 -e550 */
+static void
+c_is_a_silly_language(const struct vcc *tl)
+{
+	struct sockaddr sa;
+
+	assert(sizeof (unsigned char) == 1);
+	assert(sizeof (unsigned short) == 2);
+	assert(sizeof (unsigned int) == 4);
+	if (sizeof sa.sa_family == 1)
+		Fh(tl, 0, "\tunsigned char fam;\n");
+	else if (sizeof sa.sa_family == 2)
+		Fh(tl, 0, "\tunsigned short fam;\n");
+	else if (sizeof sa.sa_family == 4)
+		Fh(tl, 0, "\tunsigned int fam;\n");
+	else
+		assert(0 == __LINE__);
+}
+/*lint -restore */
+
+static void
+vcc_acl_emit(const struct vcc *tl, const char *acln, int anon)
+{
+	struct acl_e *ae;
+	int depth, l, m, i;
+	unsigned at[VRT_ACL_MAXADDR + 1];
+	const char *oc;
+
+	Fh(tl, 0, "\nstatic int\n");
+	Fh(tl, 0, "match_acl_%s_%s(const struct vrt_ctx *ctx, const void *p)\n",
+	    anon ? "anon" : "named", acln);
+	Fh(tl, 0, "{\n");
+	Fh(tl, 0, "\tconst unsigned char *a;\n");
+	c_is_a_silly_language(tl);
+
+	Fh(tl, 0, "\n");
+	Fh(tl, 0, "\ta = p;\n");
+	Fh(tl, 0, "\tVRT_memmove(&fam, a + %zd, sizeof fam);\n",
+	    offsetof(struct sockaddr, sa_family));
+	Fh(tl, 0, "\tif (fam == %d)\n", PF_INET);
+	Fh(tl, 0, "\t\ta += %zd;\n", offsetof(struct sockaddr_in, sin_addr));
+	Fh(tl, 0, "\telse if (fam == %d)\n", PF_INET6);
+	Fh(tl, 0, "\t\ta += %zd;\n", offsetof(struct sockaddr_in6, sin6_addr));
+	Fh(tl, 0, "\telse {\n");
+	Fh(tl, 0, "\t\tVRT_acl_log(ctx, \"NO_FAM %s\");\n", acln);
+	Fh(tl, 0, "\t\treturn(0);\n");
+	Fh(tl, 0, "\t}\n\n");
+	depth = -1;
+	oc = 0;
+	at[0] = 256;
+	VTAILQ_FOREACH(ae, &tl->acl, list) {
+
+		/* Find how much common prefix we have */
+		for (l = 0; l <= depth && l * 8 < ae->mask - 7; l++) {
+			assert(l >= 0);
+			if (ae->data[l] != at[l])
+				break;
+		}
+
+		/* Back down, if necessary */
+		oc = "";
+		while (l <= depth) {
+			Fh(tl, 0, "\t%*s}\n", -depth, "");
+			depth--;
+		}
+
+		m = ae->mask;
+		m -= l * 8;
+		assert(m >= 0);
+
+		/* Do whole byte compares */
+		for (i = l; m >= 8; m -= 8, i++) {
+			if (i == 0)
+				Fh(tl, 0, "\t%*s%sif (fam == %d) {\n",
+				    -i, "", oc, ae->data[i]);
+			else
+				Fh(tl, 0, "\t%*s%sif (a[%d] == %d) {\n",
+				    -i, "", oc, i - 1, ae->data[i]);
+			at[i] = ae->data[i];
+			depth = i;
+			oc = "";
+		}
+
+		if (m > 0) {
+			/* Do fractional byte compares */
+			Fh(tl, 0, "\t%*s%sif ((a[%d] & 0x%x) == %d) {\n",
+			    -i, "", oc, i - 1, (0xff00 >> m) & 0xff,
+			    ae->data[i] & ((0xff00 >> m) & 0xff));
+			at[i] = 256;
+			depth = i;
+			oc = "";
+		}
+
+		i = (ae->mask + 7) / 8;
+
+		if (!anon) {
+			Fh(tl, 0, "\t%*sVRT_acl_log(ctx, \"%sMATCH %s \" ",
+			    -i, "", ae->not ? "NEG_" : "", acln);
+			EncToken(tl->fh, ae->t_addr);
+			if (ae->t_mask != NULL)
+				Fh(tl, 0, " \"/%.*s\" ", PF(ae->t_mask));
+			Fh(tl, 0, ");\n");
+		}
+
+		Fh(tl, 0, "\t%*sreturn (%d);\n", -i, "", ae->not ? 0 : 1);
+	}
+
+	/* Unwind */
+	for (; 0 <= depth; depth--)
+		Fh(tl, 0, "\t%*.*s}\n", depth, depth, "");
+
+	/* Deny by default */
+	if (!anon)
+		Fh(tl, 0, "\tVRT_acl_log(ctx, \"NO_MATCH %s\");\n", acln);
+	Fh(tl, 0, "\treturn (0);\n}\n");
+}
+
+void
+vcc_Acl_Hack(struct vcc *tl, char *b)
+{
+	char acln[32];
+	unsigned tcond;
+
+	VTAILQ_INIT(&tl->acl);
+	tcond = tl->t->tok;
+	vcc_NextToken(tl);
+	bprintf(acln, "%u", tl->unique++);
+	vcc_acl_entry(tl);
+	vcc_acl_emit(tl, acln, 1);
+	sprintf(b, "%smatch_acl_anon_%s(ctx, \v1)",
+	    (tcond == T_NEQ ? "!" : ""), acln);
+}
+
+void
+vcc_Acl(struct vcc *tl)
+{
+	struct token *an;
+	int i;
+	char acln[1024];
+
+	vcc_NextToken(tl);
+	VTAILQ_INIT(&tl->acl);
+
+	ExpectErr(tl, ID);
+	if (!vcc_isCid(tl->t)) {
+		VSB_printf(tl->sb,
+		    "Names of VCL acl's cannot contain '-'\n");
+		vcc_ErrWhere(tl, tl->t);
+		return;
+	}
+	an = tl->t;
+	vcc_NextToken(tl);
+
+	i = vcc_AddDef(tl, an, SYM_ACL);
+	if (i > 1) {
+		VSB_printf(tl->sb, "ACL %.*s redefined\n", PF(an));
+		vcc_ErrWhere(tl, an);
+		return;
+	}
+	bprintf(acln, "%.*s", PF(an));
+
+	SkipToken(tl, '{');
+
+	while (tl->t->tok != '}') {
+		vcc_acl_entry(tl);
+		ERRCHK(tl);
+		SkipToken(tl, ';');
+	}
+	SkipToken(tl, '}');
+
+	vcc_acl_emit(tl, acln, 0);
+}
diff --git a/lib/libvcc/vcc_action.c b/lib/libvcc/vcc_action.c
new file mode 100644
index 0000000..4e441d2
--- /dev/null
+++ b/lib/libvcc/vcc_action.c
@@ -0,0 +1,445 @@
+/*-
+ * Copyright (c) 2006 Verdens Gang AS
+ * Copyright (c) 2006-2013 Varnish Software AS
+ * All rights reserved.
+ *
+ * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file parses the real action of the VCL code, the procedure
+ * statements which do the actual work.
+ */
+
+#include "config.h"
+
+#include <string.h>
+
+#include "vcc_compile.h"
+
+/*--------------------------------------------------------------------*/
+
+static void
+parse_call(struct vcc *tl)
+{
+
+	vcc_NextToken(tl);
+	ExpectErr(tl, ID);
+	vcc_AddCall(tl, tl->t);
+	vcc_AddRef(tl, tl->t, SYM_SUB);
+	Fb(tl, 1, "if (VGC_function_%.*s(ctx))\n", PF(tl->t));
+	Fb(tl, 1, "\treturn (1);\n");
+	vcc_NextToken(tl);
+	return;
+}
+
+/*--------------------------------------------------------------------*/
+
+static void
+parse_error(struct vcc *tl)
+{
+
+	VSB_printf(tl->sb,
+	    "Syntax has changed, use:\n"
+	    "\treturn(error(999));\n"
+	    "or\n"
+	    "\treturn(error(999, \"Response text\"));\n");
+	vcc_ErrWhere(tl, tl->t);
+	return;
+}
+
+/*--------------------------------------------------------------------*/
+
+static const struct arith {
+	enum var_type		type;
+	unsigned		oper;
+	enum var_type		want;
+} arith[] = {
+	{ INT,		T_INCR,		INT },
+	{ INT,		T_DECR,		INT },
+	{ INT,		T_MUL,		INT },
+	{ INT,		T_DIV,		INT },
+	{ INT,		'=',		INT },
+	{ INT,		0,		INT },
+	{ TIME,		T_INCR,		DURATION },
+	{ TIME,		T_DECR,		DURATION },
+	{ TIME,		T_MUL,		REAL },
+	{ TIME,		T_DIV,		REAL },
+	{ TIME,		'=',		TIME },
+	{ TIME,		0,		TIME },
+	{ DURATION,	T_INCR,		DURATION },
+	{ DURATION,	T_DECR,		DURATION },
+	{ DURATION,	T_MUL,		REAL },
+	{ DURATION,	T_DIV,		REAL },
+	{ DURATION,	'=',		DURATION },
+	{ DURATION,	0,		DURATION },
+	{ VOID,		'=',		VOID }
+};
+
+static void
+parse_set(struct vcc *tl)
+{
+	const struct var *vp;
+	const struct arith *ap;
+	enum var_type fmt;
+
+	vcc_NextToken(tl);
+	ExpectErr(tl, ID);
+	vp = vcc_FindVar(tl, tl->t, 1, "cannot be set");
+	ERRCHK(tl);
+	assert(vp != NULL);
+	Fb(tl, 1, "%s\n", vp->lname);
+	tl->indent += INDENT;
+	vcc_NextToken(tl);
+	fmt = vp->fmt;
+	for (ap = arith; ap->type != VOID; ap++) {
+		if (ap->type != fmt)
+			continue;
+		if (ap->oper != tl->t->tok)
+			continue;
+		if (ap->oper != '=')
+			Fb(tl, 1, "%s %c ", vp->rname, *tl->t->b);
+		vcc_NextToken(tl);
+		fmt = ap->want;
+		break;
+	}
+	if (ap->type == VOID)
+		SkipToken(tl, ap->oper);
+	if (fmt == HEADER) {
+		vcc_Expr(tl, STRING_LIST);
+	} else if (fmt == STRING) {
+		vcc_Expr(tl, STRING_LIST);
+	} else {
+		vcc_Expr(tl, fmt);
+	}
+	tl->indent -= INDENT;
+	Fb(tl, 1, ");\n");
+}
+
+/*--------------------------------------------------------------------*/
+
+static void
+parse_unset(struct vcc *tl)
+{
+	const struct var *vp;
+
+	/* XXX: Wrong, should use VCC_Expr(HEADER) */
+	vcc_NextToken(tl);
+	ExpectErr(tl, ID);
+	vp = vcc_FindVar(tl, tl->t, 1, "cannot be unset");
+	ERRCHK(tl);
+	assert(vp != NULL);
+	if (vp->fmt != HEADER) {
+		VSB_printf(tl->sb,
+		    "Only http header variables can be unset.\n");
+		vcc_ErrWhere(tl, tl->t);
+		return;
+	}
+	ERRCHK(tl);
+	Fb(tl, 1, "%svrt_magic_string_unset);\n", vp->lname);
+	vcc_NextToken(tl);
+}
+
+/*--------------------------------------------------------------------*/
+
+static void
+parse_new(struct vcc *tl)
+{
+	struct symbol *sy1, *sy2, *sy3;
+	const char *p, *s_obj, *s_init, *s_struct, *s_fini;
+	char buf1[128];
+	char buf2[128];
+
+	vcc_NextToken(tl);
+	ExpectErr(tl, ID);
+	if (!vcc_isCid(tl->t)) {
+		VSB_printf(tl->sb,
+		    "Names of VCL objects cannot contain '-'\n");
+		vcc_ErrWhere(tl, tl->t);
+		return;
+	}
+	sy1 = VCC_FindSymbol(tl, tl->t, SYM_NONE);
+	XXXAZ(sy1);
+
+	sy1 = VCC_AddSymbolTok(tl, tl->t, SYM_NONE);	// XXX: NONE ?
+	XXXAN(sy1);
+	vcc_NextToken(tl);
+
+	ExpectErr(tl, '=');
+	vcc_NextToken(tl);
+
+	ExpectErr(tl, ID);
+	sy2 = VCC_FindSymbol(tl, tl->t, SYM_OBJECT);
+	XXXAN(sy2);
+
+	/*lint -save -e448 */
+	/* Split the first three args */
+	p = sy2->args;
+	s_obj = p;
+	p += strlen(p) + 1;
+	s_init = p;
+	while (p[0] != '\0' || p[1] != '\0')
+		p++;
+	p += 2;
+	s_struct = p;
+	p += strlen(p) + 1;
+	s_fini = p + strlen(p) + 1;
+	while (p[0] != '\0' || p[1] != '\0')
+		p++;
+	p += 2;
+
+	Fh(tl, 0, "static %s *%s;\n\n", s_struct, sy1->name);
+
+	vcc_NextToken(tl);
+
+	bprintf(buf1, ", &%s, \"%s\"", sy1->name, sy1->name);
+	vcc_Eval_Func(tl, s_init, buf1, "ASDF", s_init + strlen(s_init) + 1);
+	Fd(tl, 0, "\t%s(&%s);\n", s_fini, sy1->name);
+	ExpectErr(tl, ';');
+
+	bprintf(buf1, ", %s", sy1->name);
+	/* Split the methods from the args */
+	while (*p != '\0') {
+		p += strlen(s_obj);
+		bprintf(buf2, "%s%s", sy1->name, p);
+		sy3 = VCC_AddSymbolStr(tl, buf2, SYM_FUNC);
+		AN(sy3);
+		sy3->eval = vcc_Eval_SymFunc;
+		p += strlen(p) + 1;
+		sy3->cfunc = p;
+		p += strlen(p) + 1;
+
+		/* Functions which return VOID are procedures */
+		if (!memcmp(p, "VOID\0", 5))
+			sy3->kind = SYM_PROC;
+
+		sy3->args = p;
+		sy3->extra = TlDup(tl, buf1);
+		while (p[0] != '\0' || p[1] != '\0') {
+			if (!memcmp(p, "ENUM\0", 5)) {
+				/* XXX: Special case for ENUM that has
+				   it's own \0\0 end marker. Not exactly
+				   elegant, we should consider
+				   alternatives here. Maybe runlength
+				   encode the entire block? */
+				p += strlen(p) + 1;
+				while (p[0] != '\0' || p[1] != '\0')
+					p++;
+			}
+			p++;
+		}
+		p += 2;
+	}
+	/*lint -restore */
+}
+
+/*--------------------------------------------------------------------*/
+
+static void
+parse_ban(struct vcc *tl)
+{
+
+	vcc_NextToken(tl);
+
+	ExpectErr(tl, '(');
+	vcc_NextToken(tl);
+
+	Fb(tl, 1, "VRT_ban_string(\n");
+	tl->indent += INDENT;
+	vcc_Expr(tl, STRING);
+	tl->indent -= INDENT;
+	ERRCHK(tl);
+	Fb(tl, 1, ");\n");
+
+	ExpectErr(tl, ')');
+	vcc_NextToken(tl);
+}
+
+/*--------------------------------------------------------------------*/
+
+static void
+parse_hash_data(struct vcc *tl)
+{
+	vcc_NextToken(tl);
+	SkipToken(tl, '(');
+
+	Fb(tl, 1, "VRT_hashdata(ctx, ");
+	vcc_Expr(tl, STRING_LIST);
+	ERRCHK(tl);
+	Fb(tl, 0, ");\n");
+	SkipToken(tl, ')');
+}
+
+/*--------------------------------------------------------------------*/
+
+static void
+parse_return(struct vcc *tl)
+{
+	int retval = 0;
+
+	vcc_NextToken(tl);
+	ExpectErr(tl, '(');
+	vcc_NextToken(tl);
+	ExpectErr(tl, ID);
+
+	/* 'error' gets special handling, to allow optional status/response */
+	if (vcc_IdIs(tl->t, "error")) {
+		vcc_NextToken(tl);
+		if (tl->t->tok == ')') {
+			VSB_printf(tl->sb,
+			    "Syntax has changed, use:\n"
+			    "\treturn(error(999));\n"
+			    "or\n"
+			    "\treturn(error(999, \"Response text\"));\n");
+			vcc_ErrWhere(tl, tl->t);
+			return;
+		}
+		ExpectErr(tl, '(');
+		vcc_NextToken(tl);
+		Fb(tl, 1, "VRT_error(ctx,\n");
+		tl->indent += INDENT;
+		vcc_Expr(tl, INT);
+		ERRCHK(tl);
+		Fb(tl, 1, ",\n");
+		if (tl->t->tok == ',') {
+			vcc_NextToken(tl);
+			vcc_Expr(tl, STRING);
+			ERRCHK(tl);
+		} else {
+			Fb(tl, 1, "(const char*)0\n");
+		}
+		tl->indent -= INDENT;
+		ExpectErr(tl, ')');
+		vcc_NextToken(tl);
+		Fb(tl, 1, ");\n");
+		Fb(tl, 1, "VRT_handling(ctx, VCL_RET_ERROR);\n");
+		Fb(tl, 1, "return (1);\n");
+		vcc_ProcAction(tl->curproc, VCL_RET_ERROR, tl->t);
+		ExpectErr(tl, ')');
+		vcc_NextToken(tl);
+		return;
+	}
+
+#define VCL_RET_MAC(l, U, B)						\
+	do {								\
+		if (vcc_IdIs(tl->t, #l)) {				\
+			Fb(tl, 1, "VRT_handling(ctx, VCL_RET_" #U ");\n"); \
+			Fb(tl, 1, "return (1);\n");			\
+			vcc_ProcAction(tl->curproc, VCL_RET_##U, tl->t);\
+			retval = 1;					\
+		}							\
+	} while (0);
+#include "tbl/vcl_returns.h"
+#undef VCL_RET_MAC
+	if (!retval) {
+		VSB_printf(tl->sb, "Expected return action name.\n");
+		vcc_ErrWhere(tl, tl->t);
+		ERRCHK(tl);
+	}
+	vcc_NextToken(tl);
+	ExpectErr(tl, ')');
+	vcc_NextToken(tl);
+}
+
+/*--------------------------------------------------------------------*/
+
+static void
+parse_rollback(struct vcc *tl)
+{
+
+	vcc_NextToken(tl);
+	Fb(tl, 1, "VRT_Rollback(ctx);\n");
+}
+
+/*--------------------------------------------------------------------*/
+
+static void
+parse_purge(struct vcc *tl)
+{
+
+	vcc_NextToken(tl);
+	Fb(tl, 1, "VRT_purge(ctx, 0, 0);\n");
+}
+
+/*--------------------------------------------------------------------*/
+
+static void
+parse_synthetic(struct vcc *tl)
+{
+	vcc_NextToken(tl);
+
+	Fb(tl, 1, "VRT_synth_page(ctx, 0, ");
+	vcc_Expr(tl, STRING_LIST);
+	ERRCHK(tl);
+	Fb(tl, 0, ");\n");
+}
+
+/*--------------------------------------------------------------------*/
+
+typedef void action_f(struct vcc *tl);
+
+static struct action_table {
+	const char		*name;
+	action_f		*func;
+	unsigned		bitmask;
+} action_table[] = {
+	/* Keep list sorted from here */
+	{ "ban",		parse_ban },
+	{ "call",		parse_call },
+	{ "error",		parse_error },
+	{ "hash_data",		parse_hash_data, VCL_MET_HASH },
+	{ "new",		parse_new, VCL_MET_INIT},
+	{ "purge",		parse_purge, VCL_MET_MISS | VCL_MET_HIT },
+	{ "remove",		parse_unset }, /* backward compatibility */
+	{ "return",		parse_return },
+	{ "rollback",		parse_rollback },
+	{ "set",		parse_set },
+	{ "synthetic",		parse_synthetic, VCL_MET_ERROR },
+	{ "unset",		parse_unset },
+	{ NULL,			NULL }
+};
+
+int
+vcc_ParseAction(struct vcc *tl)
+{
+	struct token *at;
+	struct action_table *atp;
+	const struct symbol *sym;
+
+	at = tl->t;
+	assert(at->tok == ID);
+	for(atp = action_table; atp->name != NULL; atp++) {
+		if (vcc_IdIs(at, atp->name)) {
+			if (atp->bitmask != 0)
+				vcc_AddUses(tl, at, atp->bitmask,
+				    "not a valid action");
+			atp->func(tl);
+			return (1);
+		}
+	}
+	sym = VCC_FindSymbol(tl, tl->t, SYM_NONE);
+	if (sym != NULL && sym->kind == SYM_PROC) {
+		vcc_Expr_Call(tl, sym);
+		return (1);
+	}
+	return (0);
+}
diff --git a/lib/libvcc/vcc_backend.c b/lib/libvcc/vcc_backend.c
new file mode 100644
index 0000000..b548d94
--- /dev/null
+++ b/lib/libvcc/vcc_backend.c
@@ -0,0 +1,484 @@
+/*-
+ * Copyright (c) 2006 Verdens Gang AS
+ * Copyright (c) 2006-2013 Varnish Software AS
+ * All rights reserved.
+ *
+ * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "vcc_compile.h"
+
+#include "vss.h"
+
+/*--------------------------------------------------------------------
+ * Struct sockaddr is not really designed to be a compile time
+ * initialized data structure, so we encode it as a byte-string
+ * and put it in an official sockaddr when we load the VCL.
+ */
+
+static void
+Emit_Sockaddr(struct vcc *tl, const struct token *t_host, const char *port)
+{
+	const char *ipv4, *ipv4a, *ipv6, *ipv6a, *pa;
+	const char *err;
+	char *hop, *pop;
+
+	AN(t_host->dec);
+
+	err = VSS_parse(t_host->dec, &hop, &pop);
+	if (err != NULL) {
+		VSB_printf(tl->sb,
+		    "Backend host '%.*s': %s\n", PF(t_host), err);
+		vcc_ErrWhere(tl, t_host);
+		return;
+	}
+	Resolve_Sockaddr(tl,
+	    hop != NULL ? hop : t_host->dec,
+	    pop != NULL ? pop : port,
+	    &ipv4, &ipv4a, &ipv6, &ipv6a, &pa, 2, t_host, "Backend host");
+	ERRCHK(tl);
+	if (ipv4 != NULL) {
+		Fb(tl, 0, "\t.ipv4_sockaddr = %s,\n", ipv4);
+		Fb(tl, 0, "\t.ipv4_addr = \"%s\",\n", ipv4a);
+	}
+	if (ipv6 != NULL) {
+		Fb(tl, 0, "\t.ipv6_sockaddr = %s,\n", ipv6);
+		Fb(tl, 0, "\t.ipv6_addr = \"%s\",\n", ipv6a);
+	}
+	Fb(tl, 0, "\t.port = \"%s\",\n", pa);
+}
+
+/*--------------------------------------------------------------------
+ * Parse a backend probe specification
+ */
+
+static void
+vcc_ProbeRedef(struct vcc *tl, struct token **t_did,
+    struct token *t_field)
+{
+	/* .url and .request are mutually exclusive */
+
+	if (*t_did != NULL) {
+		VSB_printf(tl->sb, "Probe request redefinition at:\n");
+		vcc_ErrWhere(tl, t_field);
+		VSB_printf(tl->sb, "Previous definition:\n");
+		vcc_ErrWhere(tl, *t_did);
+		return;
+	}
+	*t_did = t_field;
+}
+
+static void
+vcc_ParseProbeSpec(struct vcc *tl)
+{
+	struct fld_spec *fs;
+	struct token *t_field;
+	struct token *t_did = NULL, *t_window = NULL, *t_threshold = NULL;
+	struct token *t_initial = NULL;
+	unsigned window, threshold, initial, status;
+	double t;
+
+	fs = vcc_FldSpec(tl,
+	    "?url",
+	    "?request",
+	    "?expected_response",
+	    "?timeout",
+	    "?interval",
+	    "?window",
+	    "?threshold",
+	    "?initial",
+	    NULL);
+
+	SkipToken(tl, '{');
+
+	window = 0;
+	threshold = 0;
+	initial = 0;
+	status = 0;
+	Fh(tl, 0, "static const struct vrt_backend_probe vgc_probe__%d = {\n",
+	    tl->nprobe++);
+	while (tl->t->tok != '}') {
+
+		vcc_IsField(tl, &t_field, fs);
+		ERRCHK(tl);
+		if (vcc_IdIs(t_field, "url")) {
+			vcc_ProbeRedef(tl, &t_did, t_field);
+			ERRCHK(tl);
+			ExpectErr(tl, CSTR);
+			Fh(tl, 0, "\t.url = ");
+			EncToken(tl->fh, tl->t);
+			Fh(tl, 0, ",\n");
+			vcc_NextToken(tl);
+		} else if (vcc_IdIs(t_field, "request")) {
+			vcc_ProbeRedef(tl, &t_did, t_field);
+			ERRCHK(tl);
+			ExpectErr(tl, CSTR);
+			Fh(tl, 0, "\t.request =\n");
+			while (tl->t->tok == CSTR) {
+				Fh(tl, 0, "\t\t");
+				EncToken(tl->fh, tl->t);
+				Fh(tl, 0, " \"\\r\\n\"\n");
+				vcc_NextToken(tl);
+			}
+			Fh(tl, 0, "\t\t\"\\r\\n\",\n");
+		} else if (vcc_IdIs(t_field, "timeout")) {
+			Fh(tl, 0, "\t.timeout = ");
+			vcc_Duration(tl, &t);
+			ERRCHK(tl);
+			Fh(tl, 0, "%g,\n", t);
+		} else if (vcc_IdIs(t_field, "interval")) {
+			Fh(tl, 0, "\t.interval = ");
+			vcc_Duration(tl, &t);
+			ERRCHK(tl);
+			Fh(tl, 0, "%g,\n", t);
+		} else if (vcc_IdIs(t_field, "window")) {
+			t_window = tl->t;
+			window = vcc_UintVal(tl);
+			ERRCHK(tl);
+		} else if (vcc_IdIs(t_field, "initial")) {
+			t_initial = tl->t;
+			initial = vcc_UintVal(tl);
+			ERRCHK(tl);
+		} else if (vcc_IdIs(t_field, "expected_response")) {
+			status = vcc_UintVal(tl);
+			if (status < 100 || status > 999) {
+				VSB_printf(tl->sb,
+				    "Must specify .expected_response with "
+				    "exactly three digits "
+				    "(100 <= x <= 999)\n");
+				vcc_ErrWhere(tl, tl->t);
+				return;
+			}
+			ERRCHK(tl);
+		} else if (vcc_IdIs(t_field, "threshold")) {
+			t_threshold = tl->t;
+			threshold = vcc_UintVal(tl);
+			ERRCHK(tl);
+		} else {
+			vcc_ErrToken(tl, t_field);
+			vcc_ErrWhere(tl, t_field);
+			ErrInternal(tl);
+			return;
+		}
+
+		SkipToken(tl, ';');
+	}
+
+	if (t_threshold != NULL || t_window != NULL) {
+		if (t_threshold == NULL && t_window != NULL) {
+			VSB_printf(tl->sb,
+			    "Must specify .threshold with .window\n");
+			vcc_ErrWhere(tl, t_window);
+			return;
+		} else if (t_threshold != NULL && t_window == NULL) {
+			if (threshold > 64) {
+				VSB_printf(tl->sb,
+				    "Threshold must be 64 or less.\n");
+				vcc_ErrWhere(tl, t_threshold);
+				return;
+			}
+			window = threshold + 1;
+		} else if (window > 64) {
+			AN(t_window);
+			VSB_printf(tl->sb, "Window must be 64 or less.\n");
+			vcc_ErrWhere(tl, t_window);
+			return;
+		}
+		if (threshold > window ) {
+			VSB_printf(tl->sb,
+			    "Threshold can not be greater than window.\n");
+			AN(t_threshold);
+			vcc_ErrWhere(tl, t_threshold);
+			AN(t_window);
+			vcc_ErrWhere(tl, t_window);
+		}
+		Fh(tl, 0, "\t.window = %u,\n", window);
+		Fh(tl, 0, "\t.threshold = %u,\n", threshold);
+	}
+	if (t_initial != NULL)
+		Fh(tl, 0, "\t.initial = %u,\n", initial);
+	else
+		Fh(tl, 0, "\t.initial = ~0U,\n");
+	if (status > 0)
+		Fh(tl, 0, "\t.exp_status = %u,\n", status);
+	Fh(tl, 0, "};\n");
+	SkipToken(tl, '}');
+}
+
+/*--------------------------------------------------------------------
+ * Parse and emit a probe definition
+ */
+
+void
+vcc_ParseProbe(struct vcc *tl)
+{
+	struct token *t_probe;
+	int i;
+
+	vcc_NextToken(tl);		/* ID: probe */
+
+	vcc_ExpectCid(tl);		/* ID: name */
+	ERRCHK(tl);
+	t_probe = tl->t;
+	vcc_NextToken(tl);
+	i = vcc_AddDef(tl, t_probe, SYM_PROBE);
+	if (i > 1) {
+		VSB_printf(tl->sb, "Probe %.*s redefined\n", PF(t_probe));
+		vcc_ErrWhere(tl, t_probe);
+	}
+
+	Fh(tl, 0, "\n#define vgc_probe_%.*s\tvgc_probe__%d\n",
+	    PF(t_probe), tl->nprobe);
+	vcc_ParseProbeSpec(tl);
+}
+
+/*--------------------------------------------------------------------
+ * Parse and emit a backend host definition
+ *
+ * The struct vrt_backend is emitted to Fh().
+ */
+
+static void
+vcc_ParseHostDef(struct vcc *tl, const struct token *t_be)
+{
+	struct token *t_field;
+	struct token *t_host = NULL;
+	struct token *t_port = NULL;
+	struct token *t_hosthdr = NULL;
+	struct fld_spec *fs;
+	struct vsb *vsb;
+	unsigned u;
+	double t;
+	char vgcname[MAX_BACKEND_NAME + 8];
+
+	sprintf(vgcname, "_%.*s", PF(t_be));
+
+	Fh(tl, 1, "\n#define VGC_backend_%s %d\n", vgcname, tl->ndirector);
+
+	fs = vcc_FldSpec(tl,
+	    "!host",
+	    "?port",
+	    "?host_header",
+	    "?connect_timeout",
+	    "?first_byte_timeout",
+	    "?between_bytes_timeout",
+	    "?probe",
+	    "?max_connections",
+	    NULL);
+
+	SkipToken(tl, '{');
+
+	vsb = VSB_new_auto();
+	AN(vsb);
+	tl->fb = vsb;
+
+	Fb(tl, 0, "\nstatic const struct vrt_backend vgc_dir_priv_%s = {\n",
+	    vgcname);
+
+	Fb(tl, 0, "\t.vcl_name = \"%.*s", PF(t_be));
+	Fb(tl, 0, "\",\n");
+
+	/* Check for old syntax */
+	if (tl->t->tok == ID && vcc_IdIs(tl->t, "set")) {
+		VSB_printf(tl->sb,
+		    "NB: Backend Syntax has changed:\n"
+		    "Remove \"set\" and \"backend\" in front"
+		    " of backend fields.\n" );
+		vcc_ErrToken(tl, tl->t);
+		VSB_printf(tl->sb, " at ");
+		vcc_ErrWhere(tl, tl->t);
+		return;
+	}
+
+	while (tl->t->tok != '}') {
+
+		vcc_IsField(tl, &t_field, fs);
+		ERRCHK(tl);
+		if (vcc_IdIs(t_field, "host")) {
+			ExpectErr(tl, CSTR);
+			assert(tl->t->dec != NULL);
+			t_host = tl->t;
+			vcc_NextToken(tl);
+			SkipToken(tl, ';');
+		} else if (vcc_IdIs(t_field, "port")) {
+			ExpectErr(tl, CSTR);
+			assert(tl->t->dec != NULL);
+			t_port = tl->t;
+			vcc_NextToken(tl);
+			SkipToken(tl, ';');
+		} else if (vcc_IdIs(t_field, "host_header")) {
+			ExpectErr(tl, CSTR);
+			assert(tl->t->dec != NULL);
+			t_hosthdr = tl->t;
+			vcc_NextToken(tl);
+			SkipToken(tl, ';');
+		} else if (vcc_IdIs(t_field, "connect_timeout")) {
+			Fb(tl, 0, "\t.connect_timeout = ");
+			vcc_Duration(tl, &t);
+			ERRCHK(tl);
+			Fb(tl, 0, "%g,\n", t);
+			SkipToken(tl, ';');
+		} else if (vcc_IdIs(t_field, "first_byte_timeout")) {
+			Fb(tl, 0, "\t.first_byte_timeout = ");
+			vcc_Duration(tl, &t);
+			ERRCHK(tl);
+			Fb(tl, 0, "%g,\n", t);
+			SkipToken(tl, ';');
+		} else if (vcc_IdIs(t_field, "between_bytes_timeout")) {
+			Fb(tl, 0, "\t.between_bytes_timeout = ");
+			vcc_Duration(tl, &t);
+			ERRCHK(tl);
+			Fb(tl, 0, "%g,\n", t);
+			SkipToken(tl, ';');
+		} else if (vcc_IdIs(t_field, "max_connections")) {
+			u = vcc_UintVal(tl);
+			ERRCHK(tl);
+			SkipToken(tl, ';');
+			Fb(tl, 0, "\t.max_connections = %u,\n", u);
+		} else if (vcc_IdIs(t_field, "probe") && tl->t->tok == '{') {
+			Fb(tl, 0, "\t.probe = &vgc_probe__%d,\n", tl->nprobe);
+			vcc_ParseProbeSpec(tl);
+			ERRCHK(tl);
+		} else if (vcc_IdIs(t_field, "probe") && tl->t->tok == ID) {
+			Fb(tl, 0, "\t.probe = &vgc_probe_%.*s,\n", PF(tl->t));
+			vcc_AddRef(tl, tl->t, SYM_PROBE);
+			vcc_NextToken(tl);
+			SkipToken(tl, ';');
+		} else if (vcc_IdIs(t_field, "probe")) {
+			VSB_printf(tl->sb,
+			    "Expected '{' or name of probe, got ");
+			vcc_ErrToken(tl, tl->t);
+			VSB_printf(tl->sb, " at\n");
+			vcc_ErrWhere(tl, tl->t);
+			return;
+		} else {
+			ErrInternal(tl);
+			return;
+		}
+
+	}
+
+	vcc_FieldsOk(tl, fs);
+	ERRCHK(tl);
+
+	/* Check that the hostname makes sense */
+	assert(t_host != NULL);
+	if (t_port != NULL)
+		Emit_Sockaddr(tl, t_host, t_port->dec);
+	else
+		Emit_Sockaddr(tl, t_host, "80");
+	ERRCHK(tl);
+
+	ExpectErr(tl, '}');
+
+	/* We have parsed it all, emit the ident string */
+
+	/* Emit the hosthdr field, fall back to .host if not specified */
+	Fb(tl, 0, "\t.hosthdr = ");
+	if (t_hosthdr != NULL)
+		EncToken(tl->fb, t_hosthdr);
+	else
+		EncToken(tl->fb, t_host);
+	Fb(tl, 0, ",\n");
+
+	/* Close the struct */
+	Fb(tl, 0, "};\n");
+
+	vcc_NextToken(tl);
+
+	tl->fb = NULL;
+	AZ(VSB_finish(vsb));
+	Fh(tl, 0, "%s", VSB_data(vsb));
+	VSB_delete(vsb);
+
+	Fi(tl, 0, "\tVRT_init_dir(cli, VCL_conf.director,\n"
+	    "\t    VGC_backend_%s, &vgc_dir_priv_%s);\n", vgcname, vgcname);
+	Ff(tl, 0, "\tVRT_fini_dir(cli, VGCDIR(%s));\n", vgcname);
+	tl->ndirector++;
+}
+
+/*--------------------------------------------------------------------
+ * Parse directors and backends
+ */
+
+void
+vcc_ParseBackend(struct vcc *tl)
+{
+	struct token *t_first, *t_be;
+	int isfirst;
+	struct symbol *sym;
+
+	t_first = tl->t;
+	vcc_NextToken(tl);		/* ID: backend */
+
+	vcc_ExpectCid(tl);		/* ID: name */
+	ERRCHK(tl);
+
+	if (tl->t->e - tl->t->b > MAX_BACKEND_NAME) {
+		VSB_printf(tl->sb,
+		    "Name of %.*s too long (max %d, is %zu):\n",
+		    PF(t_first), MAX_BACKEND_NAME,
+		    (size_t)(tl->t->e - tl->t->b));
+		vcc_ErrWhere(tl, tl->t);
+		return;
+	}
+
+	t_be = tl->t;
+	vcc_NextToken(tl);
+
+	isfirst = tl->ndirector;
+
+	sym = VCC_GetSymbolTok(tl, t_be, SYM_BACKEND);
+	AN(sym);
+	if (sym->ndef > 0) {
+		VSB_printf(tl->sb, "Backend %.*s redefined\n", PF(t_be));
+		vcc_ErrWhere(tl, t_be);
+		return;
+	}
+	sym->fmt = BACKEND;
+	sym->eval = vcc_Eval_Backend;
+	sym->ndef++;
+	ERRCHK(tl);
+
+	vcc_ParseHostDef(tl, t_be);
+	ERRCHK(tl);
+
+	if (tl->err) {
+		VSB_printf(tl->sb,
+		    "\nIn %.*s specification starting at:\n", PF(t_first));
+		vcc_ErrWhere(tl, t_first);
+		return;
+	}
+
+	if (isfirst == 1 || vcc_IdIs(t_be, "default")) {
+		tl->defaultdir = tl->ndirector - 1;
+		tl->t_defaultdir = t_be;
+	}
+}
diff --git a/lib/libvcc/vcc_backend_util.c b/lib/libvcc/vcc_backend_util.c
new file mode 100644
index 0000000..de361a5
--- /dev/null
+++ b/lib/libvcc/vcc_backend_util.c
@@ -0,0 +1,134 @@
+/*-
+ * Copyright (c) 2006 Verdens Gang AS
+ * Copyright (c) 2006-2011 Varnish Software AS
+ * All rights reserved.
+ *
+ * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include "config.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "vcc_compile.h"
+
+/*--------------------------------------------------------------------
+ * Helper functions to complain about duplicate and missing fields
+ *
+ * XXX: idea: add groups to check for exclusivity, such that
+ * XXX:    ("!foo", "?bar", "!{", "this", "that", "}", NULL)
+ * XXX: means exactly one of "this" or "that", and
+ * XXX:    ("!foo", "?bar", "?{", "this", "that", "}", NULL)
+ * XXX: means at most one of "this" or "that".
+ */
+
+struct fld_spec {
+	const char	*name;
+	struct token	*found;
+};
+
+static void
+vcc_ResetFldSpec(struct fld_spec *f)
+{
+
+	for (; f->name != NULL; f++)
+		f->found = NULL;
+}
+
+struct fld_spec *
+vcc_FldSpec(struct vcc *tl, const char *first, ...)
+{
+	struct fld_spec f[100], *r;
+	int n = 0;
+	va_list ap;
+	const char *p;
+
+	f[n++].name = first;
+	va_start(ap, first);
+	while (1) {
+		p = va_arg(ap, const char *);
+		if (p == NULL)
+			break;
+		f[n++].name = p;
+		assert(n < 100);
+	}
+	va_end(ap);
+	f[n++].name = NULL;
+
+	vcc_ResetFldSpec(f);
+
+	r = TlAlloc(tl, sizeof *r * n);
+	memcpy(r, f, n * sizeof *r);
+	return (r);
+}
+
+void
+vcc_IsField(struct vcc *tl, struct token **t, struct fld_spec *fs)
+{
+	struct token *t_field;
+
+	SkipToken(tl, '.');
+	ExpectErr(tl, ID);
+	t_field = tl->t;
+	*t = t_field;
+	vcc_NextToken(tl);
+	SkipToken(tl, '=');
+
+	for (; fs->name != NULL; fs++) {
+		if (!vcc_IdIs(t_field, fs->name + 1))
+			continue;
+		if (fs->found == NULL) {
+			fs->found = t_field;
+			return;
+		}
+		VSB_printf(tl->sb, "Field ");
+		vcc_ErrToken(tl, t_field);
+		VSB_printf(tl->sb, " redefined at:\n");
+		vcc_ErrWhere(tl, t_field);
+		VSB_printf(tl->sb, "\nFirst defined at:\n");
+		vcc_ErrWhere(tl, fs->found);
+		return;
+	}
+	VSB_printf(tl->sb, "Unknown field: ");
+	vcc_ErrToken(tl, t_field);
+	VSB_printf(tl->sb, " at\n");
+	vcc_ErrWhere(tl, t_field);
+	return;
+}
+
+void
+vcc_FieldsOk(struct vcc *tl, const struct fld_spec *fs)
+{
+
+	for (; fs->name != NULL; fs++) {
+		if (*fs->name == '!' && fs->found == NULL) {
+			VSB_printf(tl->sb,
+			    "Mandatory field '%s' missing.\n", fs->name + 1);
+			tl->err = 1;
+		}
+	}
+}
diff --git a/lib/libvcc/vcc_compile.c b/lib/libvcc/vcc_compile.c
new file mode 100644
index 0000000..1b3ee4e
--- /dev/null
+++ b/lib/libvcc/vcc_compile.c
@@ -0,0 +1,823 @@
+/*-
+ * Copyright (c) 2006 Verdens Gang AS
+ * Copyright (c) 2006-2013 Varnish Software AS
+ * All rights reserved.
+ *
+ * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * XXX:
+ *	Better error messages, throughout.
+ *	>It also accured to me that we could link the errors to the error
+ *	>documentation.
+ *	>
+ *	>Unreferenced  function 'request_policy', first mention is
+ *	>         Line 8 Pos 4
+ *	>         sub request_policy {
+ *	>         ----##############--
+ *	>Read more about this type of error:
+ *	>http://varnish/doc/error.html#Unreferenced%20function
+ *	>
+ *	>
+ *	>         Unknown variable 'obj.bandwidth'
+ *	>         At: Line 88 Pos 12
+ *	>                 if (obj.bandwidth < 1 kb/h) {
+ *	>         ------------#############------------
+ *	>Read more about this type of error:
+ *	>http://varnish/doc/error.html#Unknown%20variable
+ *
+ */
+
+#include "config.h"
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "vcc_compile.h"
+
+#include "libvcc.h"
+#include "vfil.h"
+
+struct method method_tab[] = {
+#define VCL_MET_MAC(l,U,m)	{ "vcl_"#l, m, VCL_MET_##U },
+#include "tbl/vcl_returns.h"
+#undef VCL_MET_MAC
+	{ NULL, 0U, 0}
+};
+
+/*--------------------------------------------------------------------*/
+
+static void
+TlDoFree(struct vcc *tl, void *p)
+{
+	struct membit *mb;
+
+	mb = calloc(sizeof *mb, 1);
+	assert(mb != NULL);
+	mb->ptr = p;
+	VTAILQ_INSERT_TAIL(&tl->membits, mb, list);
+}
+
+
+void *
+TlAlloc(struct vcc *tl, unsigned len)
+{
+	void *p;
+
+	p = calloc(len, 1);
+	assert(p != NULL);
+	TlDoFree(tl, p);
+	return (p);
+}
+
+char *
+TlDup(struct vcc *tl, const char *s)
+{
+	char *p;
+
+	p = TlAlloc(tl, strlen(s) + 1);
+	AN(p);
+	strcpy(p, s);
+	return (p);
+}
+
+char *
+TlDupTok(struct vcc *tl, const struct token *tok)
+{
+	char *p;
+	int i;
+
+	i = tok->e - tok->b;
+	p = TlAlloc(tl, i + 1);
+	AN(p);
+	memcpy(p, tok->b, i);
+	p[i] = '\0';
+	return (p);
+}
+
+/*--------------------------------------------------------------------*/
+
+int
+IsMethod(const struct token *t)
+{
+	struct method *m;
+
+	assert(t->tok == ID);
+	for(m = method_tab; m->name != NULL; m++) {
+		if (vcc_IdIs(t, m->name))
+			return (m - method_tab);
+	}
+	if ((t->b[0] == 'v'|| t->b[0] == 'V') &&
+	    (t->b[1] == 'c'|| t->b[1] == 'C') &&
+	    (t->b[2] == 'l'|| t->b[2] == 'L'))
+		return (-2);
+	return (-1);
+}
+
+/*--------------------------------------------------------------------
+ * Printf output to the vsbs, possibly indented
+ */
+
+void
+Fh(const struct vcc *tl, int indent, const char *fmt, ...)
+{
+	va_list ap;
+
+	if (indent)
+		VSB_printf(tl->fh, "%*.*s", tl->hindent, tl->hindent, "");
+	va_start(ap, fmt);
+	VSB_vprintf(tl->fh, fmt, ap);
+	va_end(ap);
+}
+
+void
+Fb(const struct vcc *tl, int indent, const char *fmt, ...)
+{
+	va_list ap;
+
+	assert(tl->fb != NULL);
+	if (indent)
+		VSB_printf(tl->fb, "%*.*s", tl->indent, tl->indent, "");
+	va_start(ap, fmt);
+	VSB_vprintf(tl->fb, fmt, ap);
+	va_end(ap);
+}
+
+void
+Fc(const struct vcc *tl, int indent, const char *fmt, ...)
+{
+	va_list ap;
+
+	if (indent)
+		VSB_printf(tl->fc, "%*.*s", tl->indent, tl->indent, "");
+	va_start(ap, fmt);
+	VSB_vprintf(tl->fc, fmt, ap);
+	va_end(ap);
+}
+
+void
+Fi(const struct vcc *tl, int indent, const char *fmt, ...)
+{
+	va_list ap;
+
+	if (indent)
+		VSB_printf(tl->fi, "%*.*s", tl->iindent, tl->iindent, "");
+	va_start(ap, fmt);
+	VSB_vprintf(tl->fi, fmt, ap);
+	va_end(ap);
+}
+
+void
+Fd(const struct vcc *tl, int indent, const char *fmt, ...)
+{
+	va_list ap;
+
+	if (indent)
+		VSB_printf(tl->fd, "%*.*s", tl->findent, tl->findent, "");
+	va_start(ap, fmt);
+	VSB_vprintf(tl->fd, fmt, ap);
+	va_end(ap);
+}
+
+
+void
+Ff(const struct vcc *tl, int indent, const char *fmt, ...)
+{
+	va_list ap;
+
+	if (indent)
+		VSB_printf(tl->ff, "%*.*s", tl->findent, tl->findent, "");
+	va_start(ap, fmt);
+	VSB_vprintf(tl->ff, fmt, ap);
+	va_end(ap);
+}
+
+/*--------------------------------------------------------------------*/
+
+void
+EncString(struct vsb *sb, const char *b, const char *e, int mode)
+{
+
+	if (e == NULL)
+		e = strchr(b, '\0');
+
+	VSB_cat(sb, "\"");
+	for (; b < e; b++) {
+		switch (*b) {
+		case '\\':
+		case '"':
+			VSB_printf(sb, "\\%c", *b);
+			break;
+		case '\n':
+			VSB_printf(sb, "\\n");
+			if (mode)
+				VSB_printf(sb, "\"\n\t\"");
+			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", (uint8_t)*b);
+			break;
+		}
+	}
+	VSB_cat(sb, "\"");
+}
+
+void
+EncToken(struct vsb *sb, const struct token *t)
+{
+
+	assert(t->tok == CSTR);
+	EncString(sb, t->dec, NULL, 1);
+}
+
+/*--------------------------------------------------------------------
+ * Output the location/profiling table.  For each counted token, we
+ * record source+line+charpos for the first character in the token.
+ */
+
+static void
+LocTable(const struct vcc *tl)
+{
+	struct token *t;
+	unsigned lin, pos;
+	struct source *sp;
+	const char *p;
+
+	Fh(tl, 0, "\n#define VGC_NREFS %u\n", tl->cnt + 1);
+	Fc(tl, 0, "\nstatic struct vrt_ref VGC_ref[VGC_NREFS] = {\n");
+	lin = 1;
+	pos = 0;
+	sp = 0;
+	p = NULL;
+	VTAILQ_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 == '\n') {
+				lin++;
+				pos = 0;
+			} else if (*p == '\t') {
+				pos &= ~7;
+				pos += 8;
+			} else
+				pos++;
+
+		}
+		Fc(tl, 0, "  [%3u] = { %d, %8tu, %4u, %3u, 0, ",
+		    t->cnt, sp->idx, t->b - sp->b, lin, pos + 1);
+		if (t->tok == CSRC)
+			Fc(tl, 0, " \"C{\"},\n");
+		else
+			Fc(tl, 0, " \"%.*s\" },\n", PF(t));
+	}
+	Fc(tl, 0, "};\n");
+}
+
+/*--------------------------------------------------------------------*/
+
+static void
+EmitInitFunc(const struct vcc *tl)
+{
+
+	Fc(tl, 0, "\nstatic int\nVGC_Init(struct cli *cli)\n{\n\n");
+	AZ(VSB_finish(tl->fi));
+	VSB_cat(tl->fc, VSB_data(tl->fi));
+	Fc(tl, 0, "\treturn(0);\n");
+	Fc(tl, 0, "}\n");
+}
+
+static void
+EmitFiniFunc(const struct vcc *tl)
+{
+	unsigned u;
+
+	Fc(tl, 0, "\nstatic void\nVGC_Fini(struct cli *cli)\n{\n\n");
+
+	AZ(VSB_finish(tl->fd));
+	VSB_cat(tl->fc, VSB_data(tl->fd));
+
+	/*
+	 * We do this here, so we are sure they happen before any
+	 * per-vcl vmod_privs get cleaned.
+	 */
+	for (u = 0; u < tl->nvmodpriv; u++)
+		Fc(tl, 0, "\tvmod_priv_fini(&vmod_priv_%u);\n", u);
+
+	AZ(VSB_finish(tl->ff));
+	VSB_cat(tl->fc, VSB_data(tl->ff));
+	Fc(tl, 0, "}\n");
+}
+
+/*--------------------------------------------------------------------*/
+
+static void
+EmitStruct(const struct vcc *tl)
+{
+	struct source *sp;
+
+	Fc(tl, 0, "\nconst char *srcname[%u] = {\n", tl->nsources);
+	VTAILQ_FOREACH(sp, &tl->sources, list) {
+		Fc(tl, 0, "\t");
+		EncString(tl->fc, sp->name, NULL, 0);
+		Fc(tl, 0, ",\n");
+	}
+	Fc(tl, 0, "};\n");
+
+	Fc(tl, 0, "\nconst char *srcbody[%u] = {\n", tl->nsources);
+	VTAILQ_FOREACH(sp, &tl->sources, list) {
+		Fc(tl, 0, "    /* ");
+		EncString(tl->fc, sp->name, NULL, 0);
+		Fc(tl, 0, "*/\n");
+		Fc(tl, 0, "\t");
+		EncString(tl->fc, sp->b, sp->e, 1);
+		Fc(tl, 0, ",\n");
+	}
+	Fc(tl, 0, "};\n");
+
+	Fc(tl, 0, "\nstatic struct director\t*directors[%d];\n",
+	    tl->ndirector);
+
+	Fc(tl, 0, "\nconst struct VCL_conf VCL_conf = {\n");
+	Fc(tl, 0, "\t.magic = VCL_CONF_MAGIC,\n");
+	Fc(tl, 0, "\t.init_vcl = VGC_Init,\n");
+	Fc(tl, 0, "\t.fini_vcl = VGC_Fini,\n");
+	Fc(tl, 0, "\t.ndirector = %d,\n", tl->ndirector);
+	Fc(tl, 0, "\t.director = directors,\n");
+	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_MET_MAC(l,u,b) \
+	Fc(tl, 0, "\t." #l "_func = VGC_function_vcl_" #l ",\n");
+#include "tbl/vcl_returns.h"
+#undef VCL_MET_MAC
+	Fc(tl, 0, "};\n");
+}
+
+/*--------------------------------------------------------------------*/
+
+static struct source *
+vcc_new_source(const char *b, const char *e, const char *name)
+{
+	struct source *sp;
+
+	if (e == NULL)
+		e = strchr(b, '\0');
+	sp = calloc(sizeof *sp, 1);
+	assert(sp != NULL);
+	sp->name = strdup(name);
+	AN(sp->name);
+	sp->b = b;
+	sp->e = e;
+	return (sp);
+}
+
+static void
+vcc_destroy_source(struct source *sp)
+{
+
+	if (sp->freeit != NULL)
+		free(sp->freeit);
+	free(sp->name);
+	free(sp);
+}
+
+/*--------------------------------------------------------------------*/
+
+static struct source *
+vcc_file_source(const struct vcc *tl, struct vsb *sb, const char *fn)
+{
+	char *f;
+	struct source *sp;
+
+	if (!tl->unsafe_path && strchr(fn, '/') != NULL) {
+		VSB_printf(sb, "Include path is unsafe '%s'\n", fn);
+		return (NULL);
+	}
+	f = VFIL_readfile(tl->vcl_dir, fn, NULL);
+	if (f == NULL) {
+		VSB_printf(sb, "Cannot read file '%s': %s\n",
+		    fn, strerror(errno));
+		return (NULL);
+	}
+	sp = vcc_new_source(f, NULL, fn);
+	sp->freeit = f;
+	return (sp);
+}
+
+/*--------------------------------------------------------------------*/
+
+static void
+vcc_resolve_includes(struct vcc *tl)
+{
+	struct token *t, *t1, *t2;
+	struct source *sp;
+
+	VTAILQ_FOREACH(t, &tl->tokens, list) {
+		if (t->tok != ID || !vcc_IdIs(t, "include"))
+			continue;
+
+		t1 = VTAILQ_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 = VTAILQ_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;
+		}
+
+		sp = vcc_file_source(tl, tl->sb, t1->dec);
+		if (sp == NULL) {
+			vcc_ErrWhere(tl, t1);
+			return;
+		}
+		VTAILQ_INSERT_TAIL(&tl->sources, sp, list);
+		sp->idx = tl->nsources++;
+		tl->t = t2;
+		vcc_Lexer(tl, sp);
+
+		VTAILQ_REMOVE(&tl->tokens, t, list);
+		VTAILQ_REMOVE(&tl->tokens, t1, list);
+		VTAILQ_REMOVE(&tl->tokens, t2, list);
+		if (!tl->err)
+			vcc_resolve_includes(tl);
+		return;
+	}
+}
+
+/*--------------------------------------------------------------------*/
+
+static struct vcc *
+vcc_NewVcc(const struct vcc *tl0)
+{
+	struct vcc *tl;
+	int i;
+
+	ALLOC_OBJ(tl, VCC_MAGIC);
+	AN(tl);
+	if (tl0 != NULL) {
+		REPLACE(tl->default_vcl, tl0->default_vcl);
+		REPLACE(tl->vcl_dir, tl0->vcl_dir);
+		REPLACE(tl->vmod_dir, tl0->vmod_dir);
+		tl->vars = tl0->vars;
+		tl->err_unref = tl0->err_unref;
+		tl->allow_inline_c = tl0->allow_inline_c;
+		tl->unsafe_path = tl0->unsafe_path;
+	} else {
+		tl->err_unref = 1;
+	}
+	VTAILQ_INIT(&tl->symbols);
+	VTAILQ_INIT(&tl->membits);
+	VTAILQ_INIT(&tl->tokens);
+	VTAILQ_INIT(&tl->sources);
+
+	tl->nsources = 0;
+	tl->ndirector = 1;
+
+	/* General C code */
+	tl->fc = VSB_new_auto();
+	assert(tl->fc != NULL);
+
+	/* Forward decls (.h like) */
+	tl->fh = VSB_new_auto();
+	assert(tl->fh != NULL);
+
+	/* Init C code */
+	tl->fi = VSB_new_auto();
+	assert(tl->fi != NULL);
+
+	/* Destroy Objects */
+	tl->fd = VSB_new_auto();
+	assert(tl->fd != NULL);
+
+	/* Finish C code */
+	tl->ff = VSB_new_auto();
+	assert(tl->ff != NULL);
+
+	/* body code of methods */
+	for (i = 0; i < VCL_MET_MAX; i++) {
+		tl->fm[i] = VSB_new_auto();
+		assert(tl->fm[i] != NULL);
+	}
+	return (tl);
+}
+
+/*--------------------------------------------------------------------*/
+
+static char *
+vcc_DestroyTokenList(struct vcc *tl, char *ret)
+{
+	struct membit *mb;
+	struct source *sp;
+	struct symbol *sym;
+	int i;
+
+	while (!VTAILQ_EMPTY(&tl->membits)) {
+		mb = VTAILQ_FIRST(&tl->membits);
+		VTAILQ_REMOVE(&tl->membits, mb, list);
+		free(mb->ptr);
+		free(mb);
+	}
+	while (!VTAILQ_EMPTY(&tl->sources)) {
+		sp = VTAILQ_FIRST(&tl->sources);
+		VTAILQ_REMOVE(&tl->sources, sp, list);
+		vcc_destroy_source(sp);
+	}
+
+	while (!VTAILQ_EMPTY(&tl->symbols)) {
+		sym = VTAILQ_FIRST(&tl->symbols);
+		VTAILQ_REMOVE(&tl->symbols, sym, list);
+		FREE_OBJ(sym);
+	}
+
+	VSB_delete(tl->fh);
+	VSB_delete(tl->fc);
+	VSB_delete(tl->fi);
+	VSB_delete(tl->ff);
+	for (i = 0; i < VCL_MET_MAX; i++)
+		VSB_delete(tl->fm[i]);
+
+	free(tl);
+	return (ret);
+}
+
+/*--------------------------------------------------------------------
+ * Compile the VCL code from the given source and return the C-source
+ */
+
+static char *
+vcc_CompileSource(const struct vcc *tl0, struct vsb *sb, struct source *sp)
+{
+	struct vcc *tl;
+	struct symbol *sym;
+	const struct var *v;
+	char *of;
+	int i;
+
+	tl = vcc_NewVcc(tl0);
+	tl->sb = sb;
+
+	vcc_Expr_Init(tl);
+
+	for (v = tl->vars; v->name != NULL; v++) {
+		if (v->fmt == HEADER) {
+			sym = VCC_AddSymbolStr(tl, v->name, SYM_WILDCARD);
+			sym->wildcard = vcc_Var_Wildcard;
+		} else {
+			sym = VCC_AddSymbolStr(tl, v->name, SYM_VAR);
+		}
+		sym->var = v;
+		sym->fmt = v->fmt;
+		sym->eval = vcc_Eval_Var;
+		sym->r_methods = v->r_methods;
+	}
+
+	sym = VCC_AddSymbolStr(tl, "storage.", SYM_WILDCARD);
+	sym->wildcard = vcc_Stv_Wildcard;
+
+	vcl_output_lang_h(tl->fh);
+	Fh(tl, 0, "\n/* ---===### VCC generated below here ###===---*/\n");
+	Fh(tl, 0, "\nextern const struct VCL_conf VCL_conf;\n");
+
+	/* Macro for accessing directors */
+	Fh(tl, 0, "#define VGCDIR(n) VCL_conf.director[VGC_backend_##n]\n");
+
+	Fh(tl, 0, "#define __match_proto__(xxx)		/*lint -e{818} */\n");
+
+	/* Register and lex the main source */
+	VTAILQ_INSERT_TAIL(&tl->sources, sp, list);
+	sp->idx = tl->nsources++;
+	vcc_Lexer(tl, sp);
+	if (tl->err)
+		return (vcc_DestroyTokenList(tl, NULL));
+
+	/* Register and lex the default VCL */
+	sp = vcc_new_source(tl->default_vcl, NULL, "Default");
+	assert(sp != NULL);
+	VTAILQ_INSERT_TAIL(&tl->sources, sp, list);
+	sp->idx = tl->nsources++;
+	vcc_Lexer(tl, sp);
+	if (tl->err)
+		return (vcc_DestroyTokenList(tl, NULL));
+
+	/* Add "END OF INPUT" token */
+	vcc_AddToken(tl, EOI, sp->e, sp->e);
+	if (tl->err)
+		return (vcc_DestroyTokenList(tl, NULL));
+
+	/* Expand and lex any includes in the token string */
+	vcc_resolve_includes(tl);
+	if (tl->err)
+		return (vcc_DestroyTokenList(tl, NULL));
+
+	/* Parse the token string */
+	tl->t = VTAILQ_FIRST(&tl->tokens);
+	vcc_Parse(tl);
+	if (tl->err)
+		return (vcc_DestroyTokenList(tl, NULL));
+
+	/* Check if we have any backends at all */
+	if (tl->ndirector == 1) {
+		VSB_printf(tl->sb,
+		    "No backends or directors found in VCL program, "
+		    "at least one is necessary.\n");
+		tl->err = 1;
+		return (vcc_DestroyTokenList(tl, NULL));
+	}
+
+	/* Configure the default director */
+	Fi(tl, 0, "\tVCL_conf.director[0] = VCL_conf.director[%d];\n",
+	    tl->defaultdir);
+	vcc_AddRef(tl, tl->t_defaultdir, SYM_BACKEND);
+
+	/* Check for orphans */
+	if (vcc_CheckReferences(tl))
+		return (vcc_DestroyTokenList(tl, NULL));
+
+	/* Check that all action returns are legal */
+	if (vcc_CheckAction(tl) || tl->err)
+		return (vcc_DestroyTokenList(tl, NULL));
+
+	/* Check that all variable uses are legal */
+	if (vcc_CheckUses(tl) || tl->err)
+		return (vcc_DestroyTokenList(tl, NULL));
+
+	/* Emit method functions */
+	for (i = 0; i < VCL_MET_MAX; i++) {
+		Fc(tl, 1, "\nstatic int __match_proto__(vcl_func_f)\n");
+		Fc(tl, 1,
+		    "VGC_function_%s(const struct vrt_ctx *ctx)\n",
+		    method_tab[i].name);
+		AZ(VSB_finish(tl->fm[i]));
+		Fc(tl, 1, "{\n");
+		Fc(tl, 1, "%s", VSB_data(tl->fm[i]));
+		Fc(tl, 1, "}\n");
+	}
+
+	LocTable(tl);
+
+	EmitInitFunc(tl);
+
+	EmitFiniFunc(tl);
+
+	EmitStruct(tl);
+
+	/* Combine it all in the fh vsb */
+	AZ(VSB_finish(tl->fc));
+	VSB_cat(tl->fh, VSB_data(tl->fc));
+	AZ(VSB_finish(tl->fh));
+
+	of = strdup(VSB_data(tl->fh));
+	AN(of);
+
+	/* done */
+	return (vcc_DestroyTokenList(tl, of));
+}
+
+/*--------------------------------------------------------------------
+ * Compile the VCL code in the argument.  Error messages, if any are
+ * formatted into the vsb.
+ */
+
+char *
+VCC_Compile(const struct vcc *tl, struct vsb *sb, const char *b)
+{
+	struct source *sp;
+	char *r;
+
+	sp = vcc_new_source(b, NULL, "input");
+	if (sp == NULL)
+		return (NULL);
+	r = vcc_CompileSource(tl, sb, sp);
+	return (r);
+}
+
+/*--------------------------------------------------------------------
+ * Allocate a compiler instance
+ */
+
+struct vcc *
+VCC_New(void)
+{
+	struct vcc *tl;
+
+	tl = vcc_NewVcc(NULL);
+
+	tl->vars = vcc_vars;
+
+	return (tl);
+}
+
+/*--------------------------------------------------------------------
+ * Configure default VCL source code
+ */
+
+void
+VCC_Default_VCL(struct vcc *tl, const char *str)
+{
+
+	CHECK_OBJ_NOTNULL(tl, VCC_MAGIC);
+	REPLACE(tl->default_vcl, str);
+}
+
+/*--------------------------------------------------------------------
+ * Configure default VCL source directory
+ */
+
+void
+VCC_VCL_dir(struct vcc *tl, const char *str)
+{
+
+	CHECK_OBJ_NOTNULL(tl, VCC_MAGIC);
+	REPLACE(tl->vcl_dir, str);
+}
+
+/*--------------------------------------------------------------------
+ * Configure default VMOD directory
+ */
+
+void
+VCC_VMOD_dir(struct vcc *tl, const char *str)
+{
+
+	CHECK_OBJ_NOTNULL(tl, VCC_MAGIC);
+	REPLACE(tl->vmod_dir, str);
+}
+
+/*--------------------------------------------------------------------
+ * Configure settings
+ */
+
+void
+VCC_Err_Unref(struct vcc *tl, unsigned u)
+{
+
+	CHECK_OBJ_NOTNULL(tl, VCC_MAGIC);
+	tl->err_unref = u;
+}
+
+void
+VCC_Allow_InlineC(struct vcc *tl, unsigned u)
+{
+
+	CHECK_OBJ_NOTNULL(tl, VCC_MAGIC);
+	tl->allow_inline_c = u;
+}
+
+void
+VCC_Unsafe_Path(struct vcc *tl, unsigned u)
+{
+
+	CHECK_OBJ_NOTNULL(tl, VCC_MAGIC);
+	tl->unsafe_path = u;
+}
diff --git a/lib/libvcc/vcc_compile.h b/lib/libvcc/vcc_compile.h
new file mode 100644
index 0000000..b0983cc
--- /dev/null
+++ b/lib/libvcc/vcc_compile.h
@@ -0,0 +1,351 @@
+/*-
+ * Copyright (c) 2006 Verdens Gang AS
+ * Copyright (c) 2006-2013 Varnish Software AS
+ * All rights reserved.
+ *
+ * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdint.h>
+
+#include "miniobj.h"
+#include "vas.h"
+#include "vcl.h"
+#include "vdef.h"
+#include "vqueue.h"
+#include "vsb.h"
+
+
+#include "vcc_token_defs.h"
+
+#ifndef NULL
+#define NULL ((void*)0)
+#endif
+
+struct vsb;
+struct token;
+struct sockaddr_storage;
+
+#define isident1(c) (isalpha(c))
+#define isident(c) (isalpha(c) || isdigit(c) || (c) == '_' || (c) == '-')
+#define isvar(c) (isident(c) || (c) == '.')
+int vcc_isCid(const struct token *t);
+unsigned vcl_fixed_token(const char *p, const char **q);
+extern const char * const vcl_tnames[256];
+void vcl_output_lang_h(struct vsb *sb);
+
+#define PF(t)	(int)((t)->e - (t)->b), (t)->b
+
+#define INDENT		2
+
+struct acl_e;
+struct proc;
+struct expr;
+struct vcc;
+struct symbol;
+
+enum var_type {
+#define VCC_TYPE(foo)		foo,
+#include "tbl/vcc_types.h"
+#undef VCC_TYPE
+};
+
+struct membit {
+	VTAILQ_ENTRY(membit)	list;
+	void			*ptr;
+};
+
+struct source {
+	VTAILQ_ENTRY(source)	list;
+	char			*name;
+	const char		*b;
+	const char		*e;
+	unsigned		idx;
+	char			*freeit;
+};
+
+struct token {
+	unsigned		tok;
+	const char		*b;
+	const char		*e;
+	struct source		*src;
+	VTAILQ_ENTRY(token)	list;
+	unsigned		cnt;
+	char			*dec;
+};
+
+enum symkind {
+#define VCC_SYMB(uu, ll)	SYM_##uu,
+#include "tbl/symbol_kind.h"
+#undef VCC_SYMB
+};
+
+typedef void sym_expr_t(struct vcc *tl, struct expr **,
+    const struct symbol *sym);
+typedef struct symbol *sym_wildcard_t(struct vcc *tl, const struct token *t,
+    const struct symbol *sym);
+
+struct symbol {
+	unsigned			magic;
+#define SYMBOL_MAGIC			0x3368c9fb
+	VTAILQ_ENTRY(symbol)		list;
+
+	char				*name;
+	unsigned			nlen;
+	sym_wildcard_t			*wildcard;
+	enum symkind			kind;
+
+	const struct token		*def_b, *def_e;
+
+	enum var_type			fmt;
+
+	sym_expr_t			*eval;
+	void				*eval_priv;
+
+	/* xref.c */
+	struct proc			*proc;
+	unsigned			nref, ndef;
+
+	/* SYM_PROC, SYM_FUNC */
+	const char			*cfunc;
+	const char			*extra;
+	const char			*args;
+
+	/* SYM_VAR */
+	const struct var		*var;
+	unsigned			r_methods;
+};
+
+VTAILQ_HEAD(tokenhead, token);
+
+struct vcc {
+	unsigned		magic;
+#define VCC_MAGIC		0x24ad719d
+
+	/* Parameter/Template section */
+	char			*default_vcl;
+	char			*vcl_dir;
+	char			*vmod_dir;
+
+	const struct var	*vars;
+	VTAILQ_HEAD(, symbol)	symbols;
+
+	/* Instance section */
+	struct tokenhead	tokens;
+	VTAILQ_HEAD(, source)	sources;
+	VTAILQ_HEAD(, membit)	membits;
+	unsigned		nsources;
+	struct source		*src;
+	struct token		*t;
+	int			indent;
+	int			hindent;
+	int			iindent;
+	int			findent;
+	unsigned		cnt;
+
+	struct vsb		*fc;		/* C-code */
+	struct vsb		*fh;		/* H-code (before C-code) */
+	struct vsb		*fi;		/* Init func code */
+	struct vsb		*fd;		/* Object destructors */
+	struct vsb		*ff;		/* Finish func code */
+	struct vsb		*fb;		/* Body of current sub
+						 * NULL otherwise
+						 */
+	struct vsb		*fm[VCL_MET_MAX];	/* Method bodies */
+	struct vsb		*sb;
+	int			err;
+	int			ndirector;
+	struct proc		*curproc;
+	struct proc		*mprocs[VCL_MET_MAX];
+
+	VTAILQ_HEAD(, acl_e)	acl;
+
+	int			nprobe;
+
+	int			defaultdir;
+	struct token		*t_defaultdir;
+
+	unsigned		unique;
+	unsigned		nvmodpriv;
+
+	unsigned		err_unref;
+	unsigned		allow_inline_c;
+	unsigned		unsafe_path;
+};
+
+struct var {
+	const char		*name;
+	enum var_type		fmt;
+	unsigned		len;
+	const char		*rname;
+	unsigned		r_methods;
+	const char		*lname;
+	unsigned		w_methods;
+};
+
+struct method {
+	const char		*name;
+	unsigned		ret_bitmap;
+	unsigned		bitval;
+};
+
+/*--------------------------------------------------------------------*/
+
+/* vcc_acl.c */
+
+void vcc_Acl(struct vcc *tl);
+void vcc_Acl_Hack(struct vcc *tl, char *b);
+
+/* vcc_action.c */
+int vcc_ParseAction(struct vcc *tl);
+
+/* vcc_backend.c */
+#define MAX_BACKEND_NAME	64
+struct fld_spec;
+
+void vcc_ParseProbe(struct vcc *tl);
+void vcc_ParseBackend(struct vcc *tl);
+struct fld_spec * vcc_FldSpec(struct vcc *tl, const char *first, ...);
+void vcc_IsField(struct vcc *tl, struct token **t, struct fld_spec *fs);
+void vcc_FieldsOk(struct vcc *tl, const struct fld_spec *fs);
+
+/* vcc_compile.c */
+extern struct method method_tab[];
+/*
+ * H -> Header, before the C code
+ * C -> C-code
+ * B -> Body of function, ends up in C once function is completed
+ * I -> Initializer function
+ * F -> Finish function
+ */
+void Fh(const struct vcc *tl, int indent, const char *fmt, ...)
+    __printflike(3, 4);
+void Fc(const struct vcc *tl, int indent, const char *fmt, ...)
+    __printflike(3, 4);
+void Fb(const struct vcc *tl, int indent, const char *fmt, ...)
+    __printflike(3, 4);
+void Fi(const struct vcc *tl, int indent, const char *fmt, ...)
+    __printflike(3, 4);
+void Ff(const struct vcc *tl, int indent, const char *fmt, ...)
+    __printflike(3, 4);
+void Fd(const struct vcc *tl, int indent, const char *fmt, ...)
+    __printflike(3, 4);
+void EncToken(struct vsb *sb, const struct token *t);
+int IsMethod(const struct token *t);
+void *TlAlloc(struct vcc *tl, unsigned len);
+char *TlDup(struct vcc *tl, const char *s);
+char *TlDupTok(struct vcc *tl, const struct token *tok);
+
+void EncString(struct vsb *sb, const char *b, const char *e, int mode);
+
+/* vcc_expr.c */
+void vcc_Duration(struct vcc *tl, double *);
+unsigned vcc_UintVal(struct vcc *tl);
+void vcc_Expr(struct vcc *tl, enum var_type typ);
+void vcc_Expr_Call(struct vcc *tl, const struct symbol *sym);
+void vcc_Expr_Init(struct vcc *tl);
+sym_expr_t vcc_Eval_Var;
+sym_expr_t vcc_Eval_SymFunc;
+void vcc_Eval_Func(struct vcc *tl, const char *cfunc, const char *extra,
+    const char *name, const char *args);
+sym_expr_t vcc_Eval_Backend;
+
+/* vcc_obj.c */
+extern const struct var vcc_vars[];
+
+/* vcc_parse.c */
+void vcc_Parse(struct vcc *tl);
+
+/* vcc_storage.c */
+sym_wildcard_t vcc_Stv_Wildcard;
+
+/* vcc_utils.c */
+const char *vcc_regexp(struct vcc *tl);
+void Resolve_Sockaddr(struct vcc *tl, const char *host, const char *port, \
+    const char **ipv4, const char **ipv4_ascii, const char **ipv6, \
+    const char **ipv6_ascii, const char **p_ascii, int maxips,
+    const struct token *t_err, const char *errid);
+
+/* vcc_symb.c */
+struct symbol *VCC_AddSymbolStr(struct vcc *tl, const char *name, enum symkind);
+struct symbol *VCC_AddSymbolTok(struct vcc *tl, const struct token *t,
+    enum symkind kind);
+struct symbol *VCC_GetSymbolTok(struct vcc *tl, const struct token *tok,
+    enum symkind);
+struct symbol *VCC_FindSymbol(struct vcc *tl,
+    const struct token *t, enum symkind kind);
+const char * VCC_SymKind(struct vcc *tl, const struct symbol *s);
+typedef void symwalk_f(struct vcc *tl, const struct symbol *s);
+void VCC_WalkSymbols(struct vcc *tl, symwalk_f *func, enum symkind kind);
+
+/* vcc_token.c */
+void vcc_Coord(const struct vcc *tl, struct vsb *vsb,
+    const struct token *t);
+void vcc_ErrToken(const struct vcc *tl, const struct token *t);
+void vcc_ErrWhere(struct vcc *, const struct token *);
+void vcc_ErrWhere2(struct vcc *, const struct token *, const struct token *);
+
+void vcc__Expect(struct vcc *tl, unsigned tok, unsigned line);
+int vcc_IdIs(const struct token *t, const char *p);
+void vcc_ExpectCid(struct vcc *tl);
+void vcc_Lexer(struct vcc *tl, struct source *sp);
+void vcc_NextToken(struct vcc *tl);
+void vcc__ErrInternal(struct vcc *tl, const char *func,
+    unsigned line);
+void vcc_AddToken(struct vcc *tl, unsigned tok, const char *b,
+    const char *e);
+
+/* vcc_var.c */
+sym_wildcard_t vcc_Var_Wildcard;
+const struct var *vcc_FindVar(struct vcc *tl, const struct token *t,
+    int wr_access, const char *use);
+
+/* vcc_vmod.c */
+void vcc_ParseImport(struct vcc *tl);
+
+/* vcc_xref.c */
+int vcc_AddDef(struct vcc *tl, const struct token *t, enum symkind type);
+void vcc_AddRef(struct vcc *tl, const struct token *t, enum symkind type);
+int vcc_CheckReferences(struct vcc *tl);
+
+void vcc_AddCall(struct vcc *tl, struct token *t);
+struct proc *vcc_AddProc(struct vcc *tl, struct token *t);
+void vcc_ProcAction(struct proc *p, unsigned action, struct token *t);
+int vcc_CheckAction(struct vcc *tl);
+void vcc_AddUses(struct vcc *tl, const struct token *t, unsigned mask,
+    const char *use);
+int vcc_CheckUses(struct vcc *tl);
+
+#define ERRCHK(tl)      do { if ((tl)->err) return; } while (0)
+#define ErrInternal(tl) vcc__ErrInternal(tl, __func__, __LINE__)
+#define Expect(a, b) vcc__Expect(a, b, __LINE__)
+#define ExpectErr(a, b) \
+    do { vcc__Expect(a, b, __LINE__); ERRCHK(a);} while (0)
+#define SkipToken(a, b) \
+    do { vcc__Expect(a, b, __LINE__); ERRCHK(a); vcc_NextToken(a); } while (0)
diff --git a/lib/libvcc/vcc_expr.c b/lib/libvcc/vcc_expr.c
new file mode 100644
index 0000000..164a8d6
--- /dev/null
+++ b/lib/libvcc/vcc_expr.c
@@ -0,0 +1,1257 @@
+/*-
+ * Copyright (c) 2006 Verdens Gang AS
+ * Copyright (c) 2006-2011 Varnish Software AS
+ * All rights reserved.
+ *
+ * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * XXX: add VRT_count()'s
+ */
+
+#include "config.h"
+
+#include <math.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "vcc_compile.h"
+
+static const char *
+vcc_Type(enum var_type fmt)
+{
+	switch(fmt) {
+#define VCC_TYPE(a)	case a: return(#a);
+#include "tbl/vcc_types.h"
+#undef VCC_TYPE
+	default:
+		assert("Unknown Type");
+		return(NULL);
+	}
+}
+
+/*--------------------------------------------------------------------
+ * Recognize and convert units of time, return seconds.
+ */
+
+static double
+vcc_TimeUnit(struct vcc *tl)
+{
+	double sc = 1.0;
+
+	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 {
+		VSB_printf(tl->sb, "Unknown time unit ");
+		vcc_ErrToken(tl, tl->t);
+		VSB_printf(tl->sb, ".  Legal are 's', 'm', 'h' and 'd'\n");
+		vcc_ErrWhere(tl, tl->t);
+		return (1.0);
+	}
+	vcc_NextToken(tl);
+	return (sc);
+}
+
+/*--------------------------------------------------------------------
+ * Recognize and convert { CNUM } to unsigned value
+ * The tokenizer made sure we only get digits.
+ */
+
+unsigned
+vcc_UintVal(struct vcc *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';
+	}
+	vcc_NextToken(tl);
+	return (d);
+}
+
+/*--------------------------------------------------------------------
+ * Recognize and convert { CNUM [ '.' [ CNUM ] ] } to double value
+ * The tokenizer made sure we only get digits and a '.'
+ */
+
+static void
+vcc_NumVal(struct vcc *tl, double *d, int *frac)
+{
+	double e = 0.1;
+	const char *p;
+
+	*frac = 0;
+	*d = 0.0;
+	Expect(tl, CNUM);
+	if (tl->err) {
+		*d = NAN;
+		return;
+	}
+	for (p = tl->t->b; p < tl->t->e; p++) {
+		*d *= 10;
+		*d += *p - '0';
+	}
+	vcc_NextToken(tl);
+	if (tl->t->tok != '.')
+		return;
+	*frac = 1;
+	vcc_NextToken(tl);
+	if (tl->t->tok != CNUM)
+		return;
+	for (p = tl->t->b; p < tl->t->e; p++) {
+		*d += (*p - '0') * e;
+		e *= 0.1;
+	}
+	vcc_NextToken(tl);
+}
+
+static double
+vcc_DoubleVal(struct vcc *tl)
+{
+	double d;
+	int i;
+
+	vcc_NumVal(tl, &d, &i);
+	return (d);
+}
+
+/*--------------------------------------------------------------------*/
+
+void
+vcc_Duration(struct vcc *tl, double *d)
+{
+	double v, sc;
+
+	v = vcc_DoubleVal(tl);
+	ERRCHK(tl);
+	ExpectErr(tl, ID);
+	sc = vcc_TimeUnit(tl);
+	*d = v * sc;
+}
+
+/*--------------------------------------------------------------------*/
+
+static void
+vcc_ByteVal(struct vcc *tl, double *d)
+{
+	double v, sc;
+
+	v = vcc_DoubleVal(tl);
+	ERRCHK(tl);
+	if (tl->t->tok != ID) {
+		VSB_printf(tl->sb, "Expected BYTES unit (B, KB, MB...) got ");
+		vcc_ErrToken(tl, tl->t);
+		VSB_printf(tl->sb, "\n");
+		vcc_ErrWhere(tl, tl->t);
+		return;
+	}
+	if (vcc_IdIs(tl->t, "B"))
+		sc = 1.;
+	else if (vcc_IdIs(tl->t, "KB"))
+		sc = 1024.;
+	else if (vcc_IdIs(tl->t, "MB"))
+		sc = 1024. * 1024.;
+	else if (vcc_IdIs(tl->t, "GB"))
+		sc = 1024. * 1024. * 1024.;
+	else if (vcc_IdIs(tl->t, "TB"))
+		sc = 1024. * 1024. * 1024. * 1024.;
+	else {
+		VSB_printf(tl->sb, "Unknown BYTES unit ");
+		vcc_ErrToken(tl, tl->t);
+		VSB_printf(tl->sb,
+		    ".  Legal are 'B', 'KB', 'MB', 'GB' and 'TB'\n");
+		vcc_ErrWhere(tl, tl->t);
+		return;
+	}
+	vcc_NextToken(tl);
+	*d = v * sc;
+}
+
+/*--------------------------------------------------------------------
+ * Facility for carrying expressions around and do text-processing on
+ * them.
+ */
+
+struct expr {
+	unsigned	magic;
+#define EXPR_MAGIC	0x38c794ab
+	enum var_type	fmt;
+	struct vsb	*vsb;
+	uint8_t		constant;
+#define EXPR_VAR	(1<<0)
+#define EXPR_CONST	(1<<1)
+#define EXPR_STR_CONST	(1<<2)
+	struct token	*t1, *t2;
+};
+
+static inline int
+vcc_isconst(const struct expr *e)
+{
+	AN(e->constant);
+	return (e->constant & EXPR_CONST);
+}
+
+static void vcc_expr0(struct vcc *tl, struct expr **e, enum var_type fmt);
+
+static struct expr *
+vcc_new_expr(void)
+{
+	struct expr *e;
+
+	/* XXX: use TlAlloc() ? */
+	ALLOC_OBJ(e, EXPR_MAGIC);
+	AN(e);
+	e->vsb = VSB_new_auto();
+	e->fmt = VOID;
+	e->constant = EXPR_VAR;
+	return (e);
+}
+
+static struct expr *
+vcc_mk_expr(enum var_type fmt, const char *str, ...)
+    __printflike(2, 3);
+
+static struct expr *
+vcc_mk_expr(enum var_type fmt, const char *str, ...)
+{
+	va_list ap;
+	struct expr *e;
+
+	e = vcc_new_expr();
+	e->fmt = fmt;
+	va_start(ap, str);
+	VSB_vprintf(e->vsb, str, ap);
+	va_end(ap);
+	AZ(VSB_finish(e->vsb));
+	return (e);
+}
+
+static void
+vcc_delete_expr(struct expr *e)
+{
+	if (e == NULL)
+		return;
+	CHECK_OBJ_NOTNULL(e, EXPR_MAGIC);
+	VSB_delete(e->vsb);
+	FREE_OBJ(e);
+}
+/*--------------------------------------------------------------------
+ * We want to get the indentation right in the emitted C code so we have
+ * to represent it symbolically until we are ready to render.
+ *
+ * Many of the operations have very schematic output syntaxes, so we
+ * use the same facility to simplify the text-processing of emitting
+ * a given operation on two subexpressions.
+ *
+ * We use '\v' as the magic escape character.
+ *	\v1  insert subexpression 1
+ *	\v2  insert subexpression 2
+ *	\v+  increase indentation
+ *	\v-  increase indentation
+ *	anything else is literal
+ *
+ * When editing, we check if any of the subexpressions contain a newline
+ * and issue it as an indented block of so.
+ *
+ * XXX: check line lengths in edit, should pass indent in for this
+ */
+
+static struct expr *
+vcc_expr_edit(enum var_type fmt, const char *p, struct expr *e1,
+    struct expr *e2)
+{
+	struct expr *e;
+	int nl = 1;
+
+	AN(e1);
+	e = vcc_new_expr();
+	while (*p != '\0') {
+		if (*p != '\v') {
+			if (*p != '\n' || !nl)
+				VSB_putc(e->vsb, *p);
+			nl = (*p == '\n');
+			p++;
+			continue;
+		}
+		assert(*p == '\v');
+		switch(*++p) {
+		case '+': VSB_cat(e->vsb, "\v+"); break;
+		case '-': VSB_cat(e->vsb, "\v-"); break;
+		case '1':
+			VSB_cat(e->vsb, VSB_data(e1->vsb));
+			break;
+		case '2':
+			AN(e2);
+			VSB_cat(e->vsb, VSB_data(e2->vsb));
+			break;
+		default:
+			WRONG("Illegal edit in VCC expression");
+		}
+		p++;
+	}
+	AZ(VSB_finish(e->vsb));
+	e->t1 = e1->t1;
+	e->t2 = e1->t2;
+	if (e2 != NULL)
+		e->t2 = e2->t2;
+	vcc_delete_expr(e1);
+	vcc_delete_expr(e2);
+	e->fmt = fmt;
+	return (e);
+}
+
+/*--------------------------------------------------------------------
+ * Expand finished expression into C-source code
+ */
+
+static void
+vcc_expr_fmt(struct vsb *d, int ind, const struct expr *e1)
+{
+	char *p;
+	int i;
+
+	for (i = 0; i < ind; i++)
+		VSB_cat(d, " ");
+	p = VSB_data(e1->vsb);
+	while (*p != '\0') {
+		if (*p == '\n') {
+			VSB_putc(d, '\n');
+			if (p[1] != '\0') {
+				for (i = 0; i < ind; i++)
+					VSB_cat(d, " ");
+			}
+			p++;
+			continue;
+		}
+		if (*p != '\v') {
+			VSB_putc(d, *p);
+			p++;
+			continue;
+		}
+		p++;
+		switch(*p) {
+		case '+': ind += 2; break;
+		case '-': ind -= 2; break;
+		default:
+			WRONG("Illegal format in VCC expression");
+		}
+		p++;
+	}
+}
+
+/*--------------------------------------------------------------------
+ */
+
+static enum var_type
+vcc_arg_type(const char **p)
+{
+
+#define VCC_TYPE(a) if (!strcmp(#a, *p)) { *p += strlen(#a) + 1; return (a);}
+#include "tbl/vcc_types.h"
+#undef VCC_TYPE
+	return (VOID);
+}
+
+/*--------------------------------------------------------------------
+ */
+
+static void
+vcc_expr_tostring(struct expr **e, enum var_type fmt)
+{
+	const char *p;
+	uint8_t	constant = EXPR_VAR;
+
+	CHECK_OBJ_NOTNULL(*e, EXPR_MAGIC);
+	AN(fmt == STRING || fmt == STRING_LIST);
+
+	p = NULL;
+	switch((*e)->fmt) {
+	case BACKEND:	p = "VRT_BACKEND_string(\v1)"; break;
+	case BOOL:	p = "VRT_BOOL_string(\v1)"; break;
+	case DURATION:	p = "VRT_REAL_string(ctx, \v1)"; break;
+			 /* XXX: should DURATION insist on "s" suffix ? */
+	case INT:
+		if (vcc_isconst(*e)) {
+			p = "\"\v1\"";
+			constant = EXPR_CONST;
+		} else {
+			p = "VRT_INT_string(ctx, \v1)";
+		}
+		break;
+	case IP:	p = "VRT_IP_string(ctx, \v1)"; break;
+	case BYTES:	p = "VRT_REAL_string(ctx, \v1)"; break; /* XXX */
+	case REAL:	p = "VRT_REAL_string(ctx, \v1)"; break;
+	case TIME:	p = "VRT_TIME_string(ctx, \v1)"; break;
+	case HEADER:	p = "VRT_GetHdr(ctx, \v1)"; break;
+	case ENUM:
+	case STRING:
+	case STRING_LIST:
+			break;
+	default:
+			INCOMPL();
+			break;
+	}
+	if (p != NULL) {
+		*e = vcc_expr_edit(fmt, p, *e, NULL);
+		(*e)->constant = constant;
+	}
+}
+
+/*--------------------------------------------------------------------
+ */
+
+static void
+vcc_Eval_Regsub(struct vcc *tl, struct expr **e, const struct symbol *sym)
+{
+	struct expr *e2;
+	int all = sym->eval_priv == NULL ? 0 : 1;
+	const char *p;
+	char buf[128];
+
+	vcc_delete_expr(*e);
+	SkipToken(tl, ID);
+	SkipToken(tl, '(');
+
+	vcc_expr0(tl, &e2, STRING);
+	if (e2 == NULL)
+		return;
+	if (e2->fmt != STRING)
+		vcc_expr_tostring(&e2, STRING);
+
+	SkipToken(tl, ',');
+	ExpectErr(tl, CSTR);
+	p = vcc_regexp(tl);
+	vcc_NextToken(tl);
+
+	bprintf(buf, "VRT_regsub(ctx, %d,\v+\n\v1,\n%s", all, p);
+	*e = vcc_expr_edit(STRING, buf, e2, *e);
+
+	SkipToken(tl, ',');
+	vcc_expr0(tl, &e2, STRING);
+	if (e2 == NULL)
+		return;
+	if (e2->fmt != STRING)
+		vcc_expr_tostring(&e2, STRING);
+	*e = vcc_expr_edit(STRING, "\v1,\n\v2)\v-", *e, e2);
+	SkipToken(tl, ')');
+}
+
+/*--------------------------------------------------------------------
+ */
+
+static void
+vcc_Eval_BoolConst(struct vcc *tl, struct expr **e, const struct symbol *sym)
+{
+
+	vcc_NextToken(tl);
+	*e = vcc_mk_expr(BOOL, "(0==%d)", sym->eval_priv == NULL ? 1 : 0);
+	(*e)->constant = EXPR_CONST;
+}
+
+/*--------------------------------------------------------------------
+ */
+
+void
+vcc_Eval_Backend(struct vcc *tl, struct expr **e, const struct symbol *sym)
+{
+
+	assert(sym->kind == SYM_BACKEND);
+
+	vcc_ExpectCid(tl);
+	vcc_AddRef(tl, tl->t, SYM_BACKEND);
+	*e = vcc_mk_expr(BACKEND, "VGCDIR(_%.*s)", PF(tl->t));
+	(*e)->constant = EXPR_VAR;	/* XXX ? */
+	vcc_NextToken(tl);
+}
+
+/*--------------------------------------------------------------------
+ */
+void
+vcc_Eval_Var(struct vcc *tl, struct expr **e, const struct symbol *sym)
+{
+	const struct var *vp;
+
+	assert(sym->kind == SYM_VAR);
+	vcc_AddUses(tl, tl->t, sym->r_methods, "Not available");
+	vp = vcc_FindVar(tl, tl->t, 0, "cannot be read");
+	ERRCHK(tl);
+	assert(vp != NULL);
+	*e = vcc_mk_expr(vp->fmt, "%s", vp->rname);
+	vcc_NextToken(tl);
+}
+
+/*--------------------------------------------------------------------
+ */
+
+static void
+vcc_func(struct vcc *tl, struct expr **e, const char *cfunc,
+    const char *extra, const char *name, const char *args)
+{
+	const char *p, *r;
+	struct expr *e1, *e2;
+	enum var_type fmt;
+	char buf[32];
+
+	AN(cfunc);
+	AN(args);
+	AN(name);
+	SkipToken(tl, '(');
+	p = args;
+	if (extra == NULL)
+		extra = "";
+	e2 = vcc_mk_expr(vcc_arg_type(&p), "%s(ctx%s\v+", cfunc, extra);
+	while (*p != '\0') {
+		e1 = NULL;
+		fmt = vcc_arg_type(&p);
+		if (fmt == VOID && !strcmp(p, "PRIV_VCL")) {
+			r = strchr(name, '.');
+			AN(r);
+			e1 = vcc_mk_expr(VOID, "&vmod_priv_%.*s",
+			    (int) (r - name), name);
+			p += strlen(p) + 1;
+		} else if (fmt == VOID && !strcmp(p, "PRIV_CALL")) {
+			bprintf(buf, "vmod_priv_%u", tl->nvmodpriv++);
+			Fh(tl, 0, "struct vmod_priv %s;\n", buf);
+			e1 = vcc_mk_expr(VOID, "&%s", buf);
+			p += strlen(p) + 1;
+		} else if (fmt == ENUM) {
+			ExpectErr(tl, ID);
+			ERRCHK(tl);
+			r = p;
+			do {
+				if (vcc_IdIs(tl->t, p))
+					break;
+				p += strlen(p) + 1;
+			} while (*p != '\0');
+			if (*p == '\0') {
+				VSB_printf(tl->sb, "Wrong enum value.");
+				VSB_printf(tl->sb, "  Expected one of:\n");
+				do {
+					VSB_printf(tl->sb, "\t%s\n", r);
+					r += strlen(r) + 1;
+				} while (*r != '\0');
+				vcc_ErrWhere(tl, tl->t);
+				return;
+			}
+			e1 = vcc_mk_expr(VOID, "\"%.*s\"", PF(tl->t));
+			while (*p != '\0')
+				p += strlen(p) + 1;
+			p++;
+			SkipToken(tl, ID);
+			if (*p != '\0')		/*lint !e448 */
+				SkipToken(tl, ',');
+		} else {
+			vcc_expr0(tl, &e1, fmt);
+			ERRCHK(tl);
+			if (e1->fmt != fmt) {
+				VSB_printf(tl->sb, "Wrong argument type.");
+				VSB_printf(tl->sb, "  Expected %s.",
+					vcc_Type(fmt));
+				VSB_printf(tl->sb, "  Got %s.\n",
+					vcc_Type(e1->fmt));
+				vcc_ErrWhere2(tl, e1->t1, tl->t);
+				return;
+			}
+			assert(e1->fmt == fmt);
+			if (e1->fmt == STRING_LIST) {
+				e1 = vcc_expr_edit(STRING_LIST,
+				    "\v+\n\v1,\nvrt_magic_string_end\v-",
+				    e1, NULL);
+			}
+			if (*p != '\0')
+				SkipToken(tl, ',');
+		}
+		e2 = vcc_expr_edit(e2->fmt, "\v1,\n\v2", e2, e1);
+	}
+	SkipToken(tl, ')');
+	e2 = vcc_expr_edit(e2->fmt, "\v1\n)\v-", e2, NULL);
+	*e = e2;
+}
+
+/*--------------------------------------------------------------------
+ */
+
+void
+vcc_Eval_Func(struct vcc *tl, const char *cfunc,
+    const char *extra, const char *name, const char *args)
+{
+	struct expr *e = NULL;
+	struct token *t1;
+
+	t1 = tl->t;
+	vcc_func(tl, &e, cfunc, extra, name, args);
+	if (!tl->err) {
+		vcc_expr_fmt(tl->fb, tl->indent, e);
+		VSB_cat(tl->fb, ";\n");
+	} else if (t1 != tl->t) {
+		vcc_ErrWhere2(tl, t1, tl->t);
+	}
+	vcc_delete_expr(e);
+}
+
+/*--------------------------------------------------------------------
+ */
+
+void
+vcc_Eval_SymFunc(struct vcc *tl, struct expr **e, const struct symbol *sym)
+{
+
+	assert(sym->kind == SYM_FUNC || sym->kind == SYM_PROC);
+	AN(sym->cfunc);
+	AN(sym->name);
+	AN(sym->args);
+	SkipToken(tl, ID);
+	vcc_func(tl, e, sym->cfunc, sym->extra, sym->name, sym->args);
+}
+
+/*--------------------------------------------------------------------
+ * SYNTAX:
+ *    Expr4:
+ *	'(' Expr0 ')'
+ *	CNUM
+ *	CSTR
+ */
+
+static void
+vcc_expr4(struct vcc *tl, struct expr **e, enum var_type fmt)
+{
+	struct expr *e1, *e2;
+	const char *ip;
+	const struct symbol *sym;
+	double d;
+
+	*e = NULL;
+	if (tl->t->tok == '(') {
+		SkipToken(tl, '(');
+		vcc_expr0(tl, &e2, fmt);
+		ERRCHK(tl);
+		SkipToken(tl, ')');
+		*e = vcc_expr_edit(e2->fmt, "(\v1)", e2, NULL);
+		return;
+	}
+	switch(tl->t->tok) {
+	case ID:
+		/*
+		 * XXX: what if var and func/proc had same name ?
+		 * XXX: look for SYM_VAR first for consistency ?
+		 */
+		sym = VCC_FindSymbol(tl, tl->t, SYM_NONE);
+		if (sym == NULL || sym->eval == NULL) {
+			VSB_printf(tl->sb, "Symbol not found: ");
+			vcc_ErrToken(tl, tl->t);
+			VSB_printf(tl->sb, " (expected type %s):\n",
+			    vcc_Type(fmt));
+			vcc_ErrWhere(tl, tl->t);
+			return;
+		}
+		AN(sym);
+		switch(sym->kind) {
+		case SYM_VAR:
+		case SYM_FUNC:
+		case SYM_BACKEND:
+			AN(sym->eval);
+			AZ(*e);
+			sym->eval(tl, e, sym);
+			return;
+		default:
+			break;
+		}
+		VSB_printf(tl->sb,
+		    "Symbol type (%s) can not be used in expression.\n",
+		    VCC_SymKind(tl, sym));
+		vcc_ErrWhere(tl, tl->t);
+		return;
+	case CSTR:
+		assert(fmt != VOID);
+		if (fmt == IP) {
+			Resolve_Sockaddr(tl, tl->t->dec, "80",
+			    &ip, NULL, &ip, NULL, NULL, 1,
+			    tl->t, "IP constant");
+			ERRCHK(tl);
+			e1 = vcc_mk_expr(IP, "%s", ip);
+			ERRCHK(tl);
+		} else {
+			e1 = vcc_new_expr();
+			EncToken(e1->vsb, tl->t);
+			e1->fmt = STRING;
+			AZ(VSB_finish(e1->vsb));
+		}
+		e1->t1 = tl->t;
+		e1->constant = EXPR_CONST;
+		vcc_NextToken(tl);
+		*e = e1;
+		break;
+	case CNUM:
+		/*
+		 * XXX: %g may not have enough decimals by default
+		 * XXX: but %a is ugly, isn't it ?
+		 */
+		assert(fmt != VOID);
+		if (fmt == DURATION) {
+			vcc_Duration(tl, &d);
+			ERRCHK(tl);
+			e1 = vcc_mk_expr(DURATION, "%g", d);
+		} else if (fmt == BYTES) {
+			vcc_ByteVal(tl, &d);
+			ERRCHK(tl);
+			e1 = vcc_mk_expr(BYTES, "%.1f", d);
+			ERRCHK(tl);
+		} else if (fmt == REAL) {
+			e1 = vcc_mk_expr(REAL, "%g", vcc_DoubleVal(tl));
+			ERRCHK(tl);
+		} else {
+			e1 = vcc_mk_expr(INT, "%.*s", PF(tl->t));
+			vcc_NextToken(tl);
+		}
+		e1->constant = EXPR_CONST;
+		*e = e1;
+		break;
+	default:
+		VSB_printf(tl->sb, "Unknown token ");
+		vcc_ErrToken(tl, tl->t);
+		VSB_printf(tl->sb, " when looking for %s\n\n", vcc_Type(fmt));
+		vcc_ErrWhere(tl, tl->t);
+		break;
+	}
+}
+
+/*--------------------------------------------------------------------
+ * SYNTAX:
+ *    Expr3:
+ *      Expr4 { {'*'|'/'} Expr4 } *
+ */
+
+static void
+vcc_expr_mul(struct vcc *tl, struct expr **e, enum var_type fmt)
+{
+	struct expr *e2;
+	enum var_type f2, f3;
+	struct token *tk;
+
+	*e = NULL;
+	vcc_expr4(tl, e, fmt);
+	ERRCHK(tl);
+	f3 = f2 = (*e)->fmt;
+
+	switch(f2) {
+	case INT:	f2 = INT; break;
+	case DURATION:	f2 = REAL; break;
+	case BYTES:	f2 = REAL; break;
+	default:
+		if (tl->t->tok != '*' && tl->t->tok != '/')
+			return;
+		VSB_printf(tl->sb, "Operator %.*s not possible on type %s.\n",
+		    PF(tl->t), vcc_Type(f2));
+		vcc_ErrWhere(tl, tl->t);
+		return;
+	}
+
+	while (tl->t->tok == '*' || tl->t->tok == '/') {
+		tk = tl->t;
+		vcc_NextToken(tl);
+		vcc_expr4(tl, &e2, f2);
+		ERRCHK(tl);
+		assert(e2->fmt == f2);
+		if (tk->tok == '*')
+			*e = vcc_expr_edit(f3, "(\v1*\v2)", *e, e2);
+		else
+			*e = vcc_expr_edit(f3, "(\v1/\v2)", *e, e2);
+	}
+}
+
+/*--------------------------------------------------------------------
+ * SYNTAX:
+ *    ExprAdd:
+ *      ExprMul { {'+'|'-'} ExprMul } *
+ *
+ * For reasons of memory allocation/copying and general performance,
+ * STRINGs in VCL are quite special.   Addition/concatenation is split
+ * into it's own subfunction to encapsulate this.
+ */
+
+static void
+vcc_expr_string_add(struct vcc *tl, struct expr **e)
+{
+	struct expr  *e2;
+	enum var_type f2;
+
+	f2 = (*e)->fmt;
+
+	while (tl->t->tok == '+') {
+		vcc_NextToken(tl);
+		vcc_expr_mul(tl, &e2, STRING);
+		ERRCHK(tl);
+		if (e2->fmt != STRING && e2->fmt != STRING_LIST)
+			vcc_expr_tostring(&e2, f2);
+		ERRCHK(tl);
+		assert(e2->fmt == STRING || e2->fmt == STRING_LIST);
+
+		if (vcc_isconst(*e) && vcc_isconst(e2)) {
+			assert((*e)->fmt == STRING);
+			assert(e2->fmt == STRING);
+			*e = vcc_expr_edit(STRING, "\v1\n\v2", *e, e2);
+			(*e)->constant = EXPR_CONST;
+		} else if (((*e)->constant & EXPR_STR_CONST) &&
+		    vcc_isconst(e2)) {
+			assert((*e)->fmt == STRING_LIST);
+			assert(e2->fmt == STRING);
+			*e = vcc_expr_edit(STRING_LIST, "\v1\n\v2", *e, e2);
+			(*e)->constant = EXPR_VAR | EXPR_STR_CONST;
+		} else if (e2->fmt == STRING && vcc_isconst(e2)) {
+			*e = vcc_expr_edit(STRING_LIST, "\v1,\n\v2", *e, e2);
+			(*e)->constant = EXPR_VAR | EXPR_STR_CONST;
+		} else {
+			*e = vcc_expr_edit(STRING_LIST, "\v1,\n\v2", *e, e2);
+			(*e)->constant = EXPR_VAR;
+		}
+	}
+}
+
+static void
+vcc_expr_add(struct vcc *tl, struct expr **e, enum var_type fmt)
+{
+	struct expr  *e2;
+	enum var_type f2;
+	struct token *tk;
+
+	*e = NULL;
+	vcc_expr_mul(tl, e, fmt);
+	ERRCHK(tl);
+	f2 = (*e)->fmt;
+
+	/* Unless we specifically ask for a HEADER, fold them to string here */
+	if (fmt != HEADER && f2 == HEADER) {
+		vcc_expr_tostring(e, STRING);
+		f2 = (*e)->fmt;
+		assert(f2 == STRING);
+	}
+
+	if (tl->t->tok != '+' && tl->t->tok != '-')
+		return;
+
+	switch(f2) {
+	case STRING:
+	case STRING_LIST:
+		vcc_expr_string_add(tl, e);
+		return;
+	case INT:		break;
+	case TIME:		break;
+	case DURATION:		break;
+	case BYTES:		break;
+	default:
+		VSB_printf(tl->sb, "Operator %.*s not possible on type %s.\n",
+		    PF(tl->t), vcc_Type(f2));
+		vcc_ErrWhere(tl, tl->t);
+		return;
+	}
+
+	while (tl->t->tok == '+' || tl->t->tok == '-') {
+		if (f2 == TIME)
+			f2 = DURATION;
+		tk = tl->t;
+		vcc_NextToken(tl);
+		vcc_expr_mul(tl, &e2, f2);
+		ERRCHK(tl);
+		if (tk->tok == '-' && (*e)->fmt == TIME && e2->fmt == TIME) {
+			/* OK */
+		} else if ((*e)->fmt == TIME && e2->fmt == DURATION) {
+			f2 = TIME;
+			/* OK */
+		} else if (tk->tok == '-' &&
+		    (*e)->fmt == BYTES && e2->fmt == BYTES) {
+			/* OK */
+		} else if (e2->fmt != f2) {
+			VSB_printf(tl->sb, "%s %.*s %s not possible.\n",
+			    vcc_Type((*e)->fmt), PF(tk), vcc_Type(e2->fmt));
+			vcc_ErrWhere2(tl, tk, tl->t);
+			return;
+		}
+		if (tk->tok == '+')
+			*e = vcc_expr_edit(f2, "(\v1+\v2)", *e, e2);
+		else if (f2 == TIME && e2->fmt == TIME)
+			*e = vcc_expr_edit(DURATION, "(\v1-\v2)", *e, e2);
+		else
+			*e = vcc_expr_edit(f2, "(\v1-\v2)", *e, e2);
+	}
+}
+
+/*--------------------------------------------------------------------
+ * Fold the STRING types correctly
+ */
+
+static void
+vcc_expr_strfold(struct vcc *tl, struct expr **e, enum var_type fmt)
+{
+
+	vcc_expr_add(tl, e, fmt);
+	ERRCHK(tl);
+
+	if (fmt != STRING_LIST && (*e)->fmt == STRING_LIST)
+		*e = vcc_expr_edit(STRING,
+		    "\v+VRT_CollectString(ctx,\n\v1,\nvrt_magic_string_end)\v-",
+		    *e, NULL);
+	if (fmt == STRING_LIST && (*e)->fmt == STRING)
+		(*e)->fmt = STRING_LIST;
+}
+
+/*--------------------------------------------------------------------
+ * SYNTAX:
+ *    ExprCmp:
+ *	ExprAdd
+ *      ExprAdd Relation ExprAdd
+ *	ExprAdd(STRING) '~' CString
+ *	ExprAdd(STRING) '!~' CString
+ *	ExprAdd(IP) '~' IP
+ *	ExprAdd(IP) '!~' IP
+ */
+
+#define NUM_REL(typ)					\
+	{typ,		T_EQ,	"(\v1 == \v2)" },	\
+	{typ,		T_NEQ,	"(\v1 != \v2)" },	\
+	{typ,		T_LEQ,	"(\v1 <= \v2)" },	\
+	{typ,		T_GEQ,	"(\v1 >= \v2)" },	\
+	{typ,		'<',	"(\v1 < \v2)" },	\
+	{typ,		'>',	"(\v1 > \v2)" }
+
+static const struct cmps {
+	enum var_type		fmt;
+	unsigned		token;
+	const char		*emit;
+} vcc_cmps[] = {
+	NUM_REL(INT),
+	NUM_REL(DURATION),
+	NUM_REL(BYTES),
+	NUM_REL(REAL),
+
+	{STRING,	T_EQ,	"!VRT_strcmp(\v1, \v2)" },
+	{STRING,	T_NEQ,	"VRT_strcmp(\v1, \v2)" },
+
+	{VOID, 0, NULL}
+};
+
+#undef NUM_REL
+
+static void
+vcc_expr_cmp(struct vcc *tl, struct expr **e, enum var_type fmt)
+{
+	struct expr *e2;
+	const struct cmps *cp;
+	char buf[256];
+	const char *re;
+	const char *not;
+	struct token *tk;
+
+	*e = NULL;
+
+	vcc_expr_strfold(tl, e, fmt);
+	ERRCHK(tl);
+
+	if ((*e)->fmt == BOOL)
+		return;
+
+	tk = tl->t;
+	for (cp = vcc_cmps; cp->fmt != VOID; cp++)
+		if ((*e)->fmt == cp->fmt && tl->t->tok == cp->token)
+			break;
+	if (cp->fmt != VOID) {
+		vcc_NextToken(tl);
+		vcc_expr_strfold(tl, &e2, (*e)->fmt);
+		ERRCHK(tl);
+		if (e2->fmt != (*e)->fmt) { /* XXX */
+			VSB_printf(tl->sb, "Comparison of different types: ");
+			VSB_printf(tl->sb, "%s ", vcc_Type((*e)->fmt));
+			vcc_ErrToken(tl, tk);
+			VSB_printf(tl->sb, " %s\n", vcc_Type(e2->fmt));
+			vcc_ErrWhere(tl, tk);
+			return;
+		}
+		*e = vcc_expr_edit(BOOL, cp->emit, *e, e2);
+		return;
+	}
+	if ((*e)->fmt == STRING &&
+	    (tl->t->tok == '~' || tl->t->tok == T_NOMATCH)) {
+	        not = tl->t->tok == '~' ? "" : "!";
+		vcc_NextToken(tl);
+		ExpectErr(tl, CSTR);
+		re = vcc_regexp(tl);
+		ERRCHK(tl);
+		vcc_NextToken(tl);
+		bprintf(buf, "%sVRT_re_match(ctx, \v1, %s)", not, re);
+		*e = vcc_expr_edit(BOOL, buf, *e, NULL);
+		return;
+	}
+	if ((*e)->fmt == IP &&
+	    (tl->t->tok == '~' || tl->t->tok == T_NOMATCH)) {
+	        not = tl->t->tok == '~' ? "" : "!";
+		vcc_NextToken(tl);
+		ExpectErr(tl, ID);
+		vcc_AddRef(tl, tl->t, SYM_ACL);
+		bprintf(buf, "%smatch_acl_named_%.*s(ctx, \v1)",
+		    not, PF(tl->t));
+		vcc_NextToken(tl);
+		*e = vcc_expr_edit(BOOL, buf, *e, NULL);
+		return;
+	}
+	if ((*e)->fmt == IP && (tl->t->tok == T_EQ || tl->t->tok == T_NEQ)) {
+		vcc_Acl_Hack(tl, buf);
+		*e = vcc_expr_edit(BOOL, buf, *e, NULL);
+		return;
+	}
+	if ((*e)->fmt == BACKEND &&
+	    (tl->t->tok == T_EQ || tl->t->tok == T_NEQ)) {
+		vcc_NextToken(tl);
+		ExpectErr(tl, ID);
+		vcc_AddRef(tl, tl->t, SYM_BACKEND);
+		bprintf(buf, "(\v1 %.*s VGCDIR(_%.*s))", PF(tk), PF(tl->t));
+		vcc_NextToken(tl);
+		*e = vcc_expr_edit(BOOL, buf, *e, NULL);
+		return;
+	}
+	switch (tl->t->tok) {
+	case T_EQ:
+	case T_NEQ:
+	case '<':
+	case T_LEQ:
+	case '>':
+	case T_GEQ:
+	case '~':
+	case T_NOMATCH:
+		VSB_printf(tl->sb, "Operator %.*s not possible on %s\n",
+		    PF(tl->t), vcc_Type((*e)->fmt));
+		vcc_ErrWhere(tl, tl->t);
+		return;
+	default:
+		break;
+	}
+	if (fmt == BOOL && (*e)->fmt == STRING) {
+		*e = vcc_expr_edit(BOOL, "(\v1 != 0)", *e, NULL);
+		return;
+	}
+}
+
+/*--------------------------------------------------------------------
+ * SYNTAX:
+ *    ExprNot:
+ *      '!' ExprCmp
+ */
+
+static void
+vcc_expr_not(struct vcc *tl, struct expr **e, enum var_type fmt)
+{
+	struct expr *e2;
+	struct token *tk;
+
+	*e = NULL;
+	if (fmt != BOOL || tl->t->tok != '!') {
+		vcc_expr_cmp(tl, e, fmt);
+		return;
+	}
+
+	vcc_NextToken(tl);
+	tk = tl->t;
+	vcc_expr_cmp(tl, &e2, fmt);
+	ERRCHK(tl);
+	if (e2->fmt == BOOL) {
+		*e = vcc_expr_edit(BOOL, "!(\v1)", e2, NULL);
+		return;
+	}
+	VSB_printf(tl->sb, "'!' must be followed by BOOL, found ");
+	VSB_printf(tl->sb, "%s.\n", vcc_Type(e2->fmt));
+	vcc_ErrWhere2(tl, tk, tl->t);
+}
+
+/*--------------------------------------------------------------------
+ * SYNTAX:
+ *    ExprCand:
+ *      ExprNot { '&&' ExprNot } *
+ */
+
+static void
+vcc_expr_cand(struct vcc *tl, struct expr **e, enum var_type fmt)
+{
+	struct expr *e2;
+	struct token *tk;
+
+	*e = NULL;
+	vcc_expr_not(tl, e, fmt);
+	ERRCHK(tl);
+	if ((*e)->fmt != BOOL || tl->t->tok != T_CAND)
+		return;
+	*e = vcc_expr_edit(BOOL, "(\v+\n\v1", *e, NULL);
+	while (tl->t->tok == T_CAND) {
+		vcc_NextToken(tl);
+		tk = tl->t;
+		vcc_expr_not(tl, &e2, fmt);
+		ERRCHK(tl);
+		if (e2->fmt != BOOL) {
+			VSB_printf(tl->sb,
+			    "'&&' must be followed by BOOL, found ");
+			VSB_printf(tl->sb, "%s.\n", vcc_Type(e2->fmt));
+			vcc_ErrWhere2(tl, tk, tl->t);
+			return;
+		}
+		*e = vcc_expr_edit(BOOL, "\v1\v-\n&&\v+\n\v2", *e, e2);
+	}
+	*e = vcc_expr_edit(BOOL, "\v1\v-\n)", *e, NULL);
+}
+
+/*--------------------------------------------------------------------
+ * SYNTAX:
+ *    Expr0:
+ *      ExprCand { '||' ExprCand } *
+ */
+
+static void
+vcc_expr0(struct vcc *tl, struct expr **e, enum var_type fmt)
+{
+	struct expr *e2;
+	struct token *tk;
+
+	*e = NULL;
+	vcc_expr_cand(tl, e, fmt);
+	ERRCHK(tl);
+	if ((*e)->fmt != BOOL || tl->t->tok != T_COR)
+		return;
+	*e = vcc_expr_edit(BOOL, "(\v+\n\v1", *e, NULL);
+	while (tl->t->tok == T_COR) {
+		vcc_NextToken(tl);
+		tk = tl->t;
+		vcc_expr_cand(tl, &e2, fmt);
+		ERRCHK(tl);
+		if (e2->fmt != BOOL) {
+			VSB_printf(tl->sb,
+			    "'||' must be followed by BOOL, found ");
+			VSB_printf(tl->sb, "%s.\n", vcc_Type(e2->fmt));
+			vcc_ErrWhere2(tl, tk, tl->t);
+			return;
+		}
+		*e = vcc_expr_edit(BOOL, "\v1\v-\n||\v+\n\v2", *e, e2);
+	}
+	*e = vcc_expr_edit(BOOL, "\v1\v-\n)", *e, NULL);
+}
+
+/*--------------------------------------------------------------------
+ * This function parses and emits the C-code to evaluate an expression
+ *
+ * We know up front what kind of type we want the expression to be,
+ * and this function is the backstop if that doesn't succeed.
+ */
+
+void
+vcc_Expr(struct vcc *tl, enum var_type fmt)
+{
+	struct expr *e;
+	struct token *t1;
+
+	assert(fmt != VOID);
+
+	t1 = tl->t;
+	vcc_expr0(tl, &e, fmt);
+	ERRCHK(tl);
+	if (fmt == STRING || fmt == STRING_LIST)
+		vcc_expr_tostring(&e, fmt);
+	if (!tl->err && fmt != e->fmt)  {
+		VSB_printf(tl->sb, "Expression has type %s, expected %s\n",
+		    vcc_Type(e->fmt), vcc_Type(fmt));
+		tl->err = 1;
+	}
+	if (!tl->err) {
+		if (e->fmt == STRING_LIST) {
+			e = vcc_expr_edit(STRING_LIST,
+			    "\v+\n\v1,\nvrt_magic_string_end\v-", e, NULL);
+		}
+		vcc_expr_fmt(tl->fb, tl->indent, e);
+		VSB_putc(tl->fb, '\n');
+	} else {
+		if (t1 != tl->t)
+			vcc_ErrWhere2(tl, t1, tl->t);
+	}
+	vcc_delete_expr(e);
+}
+
+/*--------------------------------------------------------------------
+ */
+
+void
+vcc_Expr_Call(struct vcc *tl, const struct symbol *sym)
+{
+
+	struct expr *e;
+	struct token *t1;
+
+	t1 = tl->t;
+	e = NULL;
+	vcc_Eval_SymFunc(tl, &e, sym);
+	if (!tl->err) {
+		vcc_expr_fmt(tl->fb, tl->indent, e);
+		VSB_cat(tl->fb, ";\n");
+	} else if (t1 != tl->t) {
+		vcc_ErrWhere2(tl, t1, tl->t);
+	}
+	vcc_delete_expr(e);
+}
+
+/*--------------------------------------------------------------------
+ */
+
+void
+vcc_Expr_Init(struct vcc *tl)
+{
+	struct symbol *sym;
+
+	sym = VCC_AddSymbolStr(tl, "regsub", SYM_FUNC);
+	AN(sym);
+	sym->eval = vcc_Eval_Regsub;
+	sym->eval_priv = NULL;
+
+	sym = VCC_AddSymbolStr(tl, "regsuball", SYM_FUNC);
+	AN(sym);
+	sym->eval = vcc_Eval_Regsub;
+	sym->eval_priv = sym;
+
+	sym = VCC_AddSymbolStr(tl, "true", SYM_FUNC);
+	AN(sym);
+	sym->eval = vcc_Eval_BoolConst;
+	sym->eval_priv = sym;
+
+	sym = VCC_AddSymbolStr(tl, "false", SYM_FUNC);
+	AN(sym);
+	sym->eval = vcc_Eval_BoolConst;
+	sym->eval_priv = NULL;
+}
diff --git a/lib/libvcc/vcc_parse.c b/lib/libvcc/vcc_parse.c
new file mode 100644
index 0000000..ab562f5
--- /dev/null
+++ b/lib/libvcc/vcc_parse.c
@@ -0,0 +1,359 @@
+/*-
+ * Copyright (c) 2006 Verdens Gang AS
+ * Copyright (c) 2006-2013 Varnish Software AS
+ * All rights reserved.
+ *
+ * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include "vcc_compile.h"
+
+/*--------------------------------------------------------------------*/
+
+static void vcc_Compound(struct vcc *tl);
+
+/*--------------------------------------------------------------------*/
+
+#define L(tl, foo)	do {	\
+	tl->indent += INDENT;	\
+	foo;			\
+	tl->indent -= INDENT;	\
+} while (0)
+
+#define C(tl, sep)	do {					\
+	Fb(tl, 1, "VRT_count(ctx, %u)%s\n", ++tl->cnt, sep);	\
+	tl->t->cnt = tl->cnt;					\
+} while (0)
+
+/*--------------------------------------------------------------------
+ * SYNTAX:
+ *    Conditional:
+ *	'(' Cond_0 ')'
+ */
+
+static void
+vcc_Conditional(struct vcc *tl)
+{
+
+	SkipToken(tl, '(');
+	Fb(tl, 0, "(\n");
+	L(tl, vcc_Expr(tl, BOOL));
+	ERRCHK(tl);
+	Fb(tl, 1, ")\n");
+	SkipToken(tl, ')');
+}
+
+/*--------------------------------------------------------------------
+ * SYNTAX:
+ *    IfStmt:
+ *	'if' Conditional  Compound Branch1* Branch2
+ *    Branch1:
+ *      'elseif' Conditional Compound
+ *    Branch2:
+ *      'else' Compound
+ *	null
+ */
+
+static void
+vcc_IfStmt(struct vcc *tl)
+{
+
+	SkipToken(tl, ID);
+	Fb(tl, 1, "if ");
+	vcc_Conditional(tl);
+	ERRCHK(tl);
+	L(tl, vcc_Compound(tl));
+	ERRCHK(tl);
+	while (tl->t->tok == ID) {
+		if (vcc_IdIs(tl->t, "else")) {
+			vcc_NextToken(tl);
+			if (tl->t->tok == '{') {
+				Fb(tl, 1, "else\n");
+				L(tl, vcc_Compound(tl));
+				ERRCHK(tl);
+				return;
+			}
+			if (tl->t->tok != ID || !vcc_IdIs(tl->t, "if")) {
+				VSB_printf(tl->sb,
+				    "'else' must be followed by 'if' or '{'\n");
+				vcc_ErrWhere(tl, tl->t);
+				return;
+			}
+			Fb(tl, 1, "else if ");
+			vcc_NextToken(tl);
+			vcc_Conditional(tl);
+			ERRCHK(tl);
+			L(tl, vcc_Compound(tl));
+			ERRCHK(tl);
+		} else if (vcc_IdIs(tl->t, "elseif") ||
+		     vcc_IdIs(tl->t, "elsif") ||
+		     vcc_IdIs(tl->t, "elif")) {
+			Fb(tl, 1, "else if ");
+			vcc_NextToken(tl);
+			vcc_Conditional(tl);
+			ERRCHK(tl);
+			L(tl, vcc_Compound(tl));
+			ERRCHK(tl);
+		} else {
+			break;
+		}
+	}
+	C(tl, ";");
+}
+
+/*--------------------------------------------------------------------
+ * SYNTAX:
+ *    Compound:
+ *	'{' Stmt* '}'
+ *
+ *    Stmt:
+ *	Compound
+ *	IfStmt
+ *	CSRC
+ *	Id(Action) (XXX)
+ */
+
+static void
+vcc_Compound(struct vcc *tl)
+{
+	int i;
+
+	SkipToken(tl, '{');
+	Fb(tl, 1, "{\n");
+	tl->indent += INDENT;
+	C(tl, ";");
+	while (1) {
+		ERRCHK(tl);
+		switch (tl->t->tok) {
+		case '{':
+			vcc_Compound(tl);
+			break;
+		case '}':
+			vcc_NextToken(tl);
+			tl->indent -= INDENT;
+			Fb(tl, 1, "}\n");
+			return;
+		case CSRC:
+			if (tl->allow_inline_c) {
+				Fb(tl, 1, "%.*s\n",
+				    (int) (tl->t->e - (tl->t->b + 2)),
+				    tl->t->b + 1);
+				vcc_NextToken(tl);
+			} else {
+				VSB_printf(tl->sb,
+				    "Inline-C not allowed\n");
+				vcc_ErrWhere(tl, tl->t);
+			}
+			break;
+		case EOI:
+			VSB_printf(tl->sb,
+			    "End of input while in compound statement\n");
+			tl->err = 1;
+			return;
+		case ID:
+			if (vcc_IdIs(tl->t, "if")) {
+				vcc_IfStmt(tl);
+				break;
+			} else {
+				i = vcc_ParseAction(tl);
+				ERRCHK(tl);
+				if (i) {
+					SkipToken(tl, ';');
+					break;
+				}
+			}
+			/* FALLTHROUGH */
+		default:
+			/* We deliberately do not mention inline C */
+			VSB_printf(tl->sb,
+			    "Expected an action, 'if', '{' or '}'\n");
+			vcc_ErrWhere(tl, tl->t);
+			return;
+		}
+	}
+}
+
+/*--------------------------------------------------------------------
+ * SYNTAX:
+ *    Function:
+ *	'sub' ID(name) Compound
+ */
+
+static void
+vcc_Function(struct vcc *tl)
+{
+	int m, i;
+
+	vcc_NextToken(tl);
+	ExpectErr(tl, ID);
+	if (!vcc_isCid(tl->t)) {
+		VSB_printf(tl->sb,
+		    "Names of VCL sub's cannot contain '-'\n");
+		vcc_ErrWhere(tl, tl->t);
+		return;
+	}
+
+	m = IsMethod(tl->t);
+	if (m == -2) {
+		VSB_printf(tl->sb,
+		    "VCL sub's named 'vcl*' are reserved names.\n");
+		vcc_ErrWhere(tl, tl->t);
+		VSB_printf(tl->sb, "Valid vcl_* methods are:\n");
+		for (i = 0; method_tab[i].name != NULL; i++)
+			VSB_printf(tl->sb, "\t%s\n", method_tab[i].name);
+		return;
+	} else if (m != -1) {
+		assert(m < VCL_MET_MAX);
+		tl->fb = tl->fm[m];
+		if (tl->mprocs[m] == NULL) {
+			(void)vcc_AddDef(tl, tl->t, SYM_SUB);
+			vcc_AddRef(tl, tl->t, SYM_SUB);
+			tl->mprocs[m] = vcc_AddProc(tl, tl->t);
+		}
+		tl->curproc = tl->mprocs[m];
+		Fb(tl, 1, "  /* ... from ");
+		vcc_Coord(tl, tl->fb, NULL);
+		Fb(tl, 0, " */\n");
+	} else {
+		tl->fb = tl->fc;
+		i = vcc_AddDef(tl, tl->t, SYM_SUB);
+		if (i > 1) {
+			VSB_printf(tl->sb,
+			    "Function %.*s redefined\n", PF(tl->t));
+			vcc_ErrWhere(tl, tl->t);
+			return;
+		}
+		tl->curproc = vcc_AddProc(tl, tl->t);
+		Fh(tl, 0, "static int VGC_function_%.*s "
+		    "(struct vrt_ctx *ctx);\n", PF(tl->t));
+		Fc(tl, 1, "\nstatic int __match_proto__(vcl_func_t)\n");
+		Fc(tl, 1, "VGC_function_%.*s(struct vrt_ctx *ctx)\n",
+		    PF(tl->t));
+	}
+	vcc_NextToken(tl);
+	tl->indent += INDENT;
+	Fb(tl, 1, "{\n");
+	L(tl, vcc_Compound(tl));
+	if (m == -1) {
+		/*
+		 * non-method subroutines must have an explicit non-action
+		 * return in case they just fall through the bottom.
+		 */
+		Fb(tl, 1, "  return(0);\n");
+	}
+	Fb(tl, 1, "}\n");
+	tl->indent -= INDENT;
+	tl->fb = NULL;
+	tl->curproc = NULL;
+}
+
+/*--------------------------------------------------------------------
+ */
+
+static void
+vcc_Director(struct vcc *tl)
+{
+	VSB_printf(tl->sb, "\ndirectors are now in directors VMOD.\n");
+	vcc_ErrWhere(tl, tl->t);
+}
+
+/*--------------------------------------------------------------------
+ * Top level of parser, recognize:
+ *	Inline C-code
+ *	ACL definitions
+ *	Function definitions
+ *	Backend & Director definitions
+ *	End of input
+ */
+
+typedef void parse_f(struct vcc *tl);
+
+static struct toplev {
+	const char	*name;
+	parse_f		*func;
+} toplev[] = {
+	{ "acl",		vcc_Acl },
+	{ "sub",		vcc_Function },
+	{ "backend",		vcc_ParseBackend },
+	{ "director",		vcc_Director },
+	{ "probe",		vcc_ParseProbe },
+	{ "import",		vcc_ParseImport },
+	{ NULL, NULL }
+};
+
+void
+vcc_Parse(struct vcc *tl)
+{
+	struct toplev *tp;
+
+	while (tl->t->tok != EOI) {
+		ERRCHK(tl);
+		switch (tl->t->tok) {
+		case CSRC:
+			if (tl->allow_inline_c) {
+				Fc(tl, 0, "%.*s\n",
+				    (int) (tl->t->e - (tl->t->b + 4)),
+				    tl->t->b + 2);
+				vcc_NextToken(tl);
+			} else {
+				VSB_printf(tl->sb,
+				    "Inline-C not allowed\n");
+				vcc_ErrWhere(tl, tl->t);
+			}
+			break;
+		case EOI:
+			break;
+		case ID:
+			for (tp = toplev; tp->name != NULL; tp++) {
+				if (!vcc_IdIs(tl->t, tp->name))
+					continue;
+				tp->func(tl);
+				break;
+			}
+			if (tp->name != NULL)
+				break;
+			/* FALLTHROUGH */
+		default:
+			/* We deliberately do not mention inline-C */
+			VSB_printf(tl->sb, "Expected one of\n\t");
+			for (tp = toplev; tp->name != NULL; tp++) {
+				if (tp[1].name == NULL)
+					VSB_printf(tl->sb, " or ");
+				VSB_printf(tl->sb, "'%s'", tp->name);
+				if (tp[1].name != NULL)
+					VSB_printf(tl->sb, ", ");
+			}
+			VSB_printf(tl->sb, "\nFound: ");
+			vcc_ErrToken(tl, tl->t);
+			VSB_printf(tl->sb, " at\n");
+			vcc_ErrWhere(tl, tl->t);
+			return;
+		}
+	}
+}
diff --git a/lib/libvcc/vcc_storage.c b/lib/libvcc/vcc_storage.c
new file mode 100644
index 0000000..5f9712a
--- /dev/null
+++ b/lib/libvcc/vcc_storage.c
@@ -0,0 +1,149 @@
+/*-
+ * Copyright (c) 2010 Varnish Software AS
+ * All rights reserved.
+ *
+ * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * All stuff related to the storage.* part of the namespace.
+ *
+ * "All" is actually only a wildcard function, which instantiates variables
+ * on demand under the storage.* tree of the namespace.
+ *
+ * About the syntax:
+ * -----------------
+ *
+ * One of our long term goals is to have dynamic storage configuration, such
+ * as the ability to add or remove a stevedore on the fly, without restarting
+ * the worker process.
+ *
+ * Even though this goal is far out in the future, it influences the syntax
+ * design of storage selection from VCL.
+ *
+ * In difference from backends, where we know the possible set of backends at
+ * compile time, we will not in the future know the identity of the stevedores
+ * available at compile time, so we have to rely on VRT name resolution.
+ *
+ * This indicates a namespace on the form storage.<stevedore>.<property>
+ *
+ * For each property, we must define a default value if the named stevedore
+ * does not exists, such that for instance stevedore.forgetit.freespace
+ * returns zero etc.
+ *
+ */
+
+#include "config.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "vcc_compile.h"
+
+#define PFX "storage."
+
+/*--------------------------------------------------------------------
+ *
+ */
+
+static struct var *
+vcc_Stv_mkvar(struct vcc *tl, const struct token *t, enum var_type fmt)
+{
+	struct var *v;
+
+	v = TlAlloc(tl, sizeof *v);
+	AN(v);
+
+	v->name = TlDupTok(tl, t);
+	v->r_methods = 0
+#define VCL_MET_MAC(l,u,b)	| VCL_MET_##u
+#include "tbl/vcl_returns.h"
+#undef VCL_MET_MAC
+		;
+	v->fmt = fmt;
+
+	return (v);
+}
+
+static struct stvars {
+	const char	*name;
+	enum var_type	fmt;
+} stvars[] = {
+#define VRTSTVVAR(nm, vtype, ctype, dval)	{ #nm, vtype },
+#include "tbl/vrt_stv_var.h"
+#undef VRTSTVVAR
+	{ NULL,			BOOL }
+};
+
+struct symbol *
+vcc_Stv_Wildcard(struct vcc *tl, const struct token *t,
+    const struct symbol *wcsym)
+{
+	const char *p, *q;
+	struct var *v = NULL;
+	struct symbol *sym;
+	struct stvars *sv;
+	char stv[1024];
+	char buf[1024];
+
+	(void)wcsym;
+	assert((t->e - t->b) > strlen(PFX));
+	assert(!memcmp(t->b, PFX, strlen(PFX)));
+
+	p = t->b + strlen(PFX);
+	for (q = p; q < t->e && *q != '.'; q++)
+		continue;
+	bprintf(stv, "%.*s", (int)(q - p), p);
+
+	if (q == t->e) {
+		v = vcc_Stv_mkvar(tl, t, BOOL);
+		bprintf(buf, "VRT_Stv(\"%s\")", stv);
+		v->rname = TlDup(tl, buf);
+	} else {
+		assert(*q  == '.');
+		q++;
+		for(sv = stvars; sv->name != NULL; sv++) {
+			if (strncmp(q, sv->name, t->e - q))
+				continue;
+			if (sv->name[t->e - q] != '\0')
+				continue;
+			v = vcc_Stv_mkvar(tl, t, sv->fmt);
+			bprintf(buf, "VRT_Stv_%s(\"%s\")", sv->name, stv);
+			v->rname = TlDup(tl, buf);
+			break;
+		}
+	}
+
+	if (v == NULL)
+		return (NULL);
+
+	sym = VCC_AddSymbolTok(tl, t, SYM_VAR);
+	AN(sym);
+	sym->var = v;
+	sym->fmt = v->fmt;
+	sym->eval = vcc_Eval_Var;
+	sym->r_methods = v->r_methods;
+
+	return (sym);
+}
diff --git a/lib/libvcc/vcc_symb.c b/lib/libvcc/vcc_symb.c
new file mode 100644
index 0000000..c3d8a13
--- /dev/null
+++ b/lib/libvcc/vcc_symb.c
@@ -0,0 +1,142 @@
+/*-
+ * Copyright (c) 2010 Varnish Software AS
+ * All rights reserved.
+ *
+ * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "vcc_compile.h"
+
+/*--------------------------------------------------------------------*/
+
+const char *
+VCC_SymKind(struct vcc *tl, const struct symbol *s)
+{
+	switch(s->kind) {
+#define VCC_SYMB(uu, ll)	case SYM_##uu: return(#ll);
+#include "tbl/symbol_kind.h"
+#undef VCC_SYMB
+	default:
+		ErrInternal(tl);
+		VSB_printf(tl->sb, "Symbol Kind 0x%x\n", s->kind);
+		return("INTERNALERROR");
+	}
+}
+
+
+static struct symbol *
+vcc_AddSymbol(struct vcc *tl, const char *nb, int l, enum symkind kind)
+{
+	struct symbol *sym;
+
+	VTAILQ_FOREACH(sym, &tl->symbols, list) {
+		if (sym->nlen != l)
+			continue;
+		if (memcmp(nb, sym->name, l))
+			continue;
+		if (kind != sym->kind)
+			continue;
+		VSB_printf(tl->sb, "Name Collision: <%.*s> <%s>\n",
+		    l, nb, VCC_SymKind(tl, sym));
+		ErrInternal(tl);
+		return (NULL);
+	}
+	ALLOC_OBJ(sym, SYMBOL_MAGIC);
+	AN(sym);
+	sym->name = malloc(l + 1L);
+	AN(sym->name);
+	memcpy(sym->name, nb, l);
+	sym->name[l] = '\0';
+	sym->nlen = l;
+	VTAILQ_INSERT_HEAD(&tl->symbols, sym, list);
+	sym->kind = kind;
+	return (sym);
+}
+
+struct symbol *
+VCC_AddSymbolStr(struct vcc *tl, const char *name, enum symkind kind)
+{
+
+	return (vcc_AddSymbol(tl, name, strlen(name), kind));
+}
+
+struct symbol *
+VCC_AddSymbolTok(struct vcc *tl, const struct token *t, enum symkind kind)
+{
+
+	return (vcc_AddSymbol(tl, t->b, t->e - t->b, kind));
+}
+
+struct symbol *
+VCC_GetSymbolTok(struct vcc *tl, const struct token *tok, enum symkind kind)
+{
+	struct symbol *sym;
+
+	sym = VCC_FindSymbol(tl, tok, kind);
+	if (sym == NULL) {
+		sym = vcc_AddSymbol(tl, tok->b, tok->e - tok->b, kind);
+		AN(sym);
+		sym->def_b = tok;
+	}
+	return (sym);
+}
+
+struct symbol *
+VCC_FindSymbol(struct vcc *tl, const struct token *t, enum symkind kind)
+{
+	struct symbol *sym;
+
+	assert(t->tok == ID);
+	VTAILQ_FOREACH(sym, &tl->symbols, list) {
+		if (sym->kind == SYM_WILDCARD &&
+		   (t->e - t->b > sym->nlen) &&
+		   !memcmp(sym->name, t->b, sym->nlen)) {
+			AN(sym->wildcard);
+			return (sym->wildcard(tl, t, sym));
+		}
+		if (kind != SYM_NONE && kind != sym->kind)
+			continue;
+		if (vcc_IdIs(t, sym->name))
+			return (sym);
+	}
+	return (NULL);
+}
+
+void
+VCC_WalkSymbols(struct vcc *tl, symwalk_f *func, enum symkind kind)
+{
+	struct symbol *sym;
+
+	VTAILQ_FOREACH(sym, &tl->symbols, list) {
+		if (kind == SYM_NONE || kind == sym->kind)
+			func(tl, sym);
+		ERRCHK(tl);
+	}
+}
diff --git a/lib/libvcc/vcc_token.c b/lib/libvcc/vcc_token.c
new file mode 100644
index 0000000..6201fea
--- /dev/null
+++ b/lib/libvcc/vcc_token.c
@@ -0,0 +1,523 @@
+/*-
+ * Copyright (c) 2006 Verdens Gang AS
+ * Copyright (c) 2006-2011 Varnish Software AS
+ * All rights reserved.
+ *
+ * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "vcc_compile.h"
+
+/*--------------------------------------------------------------------*/
+
+void
+vcc_ErrToken(const struct vcc *tl, const struct token *t)
+{
+
+	if (t->tok == EOI)
+		VSB_printf(tl->sb, "end of input");
+	else if (t->tok == CSRC)
+		VSB_printf(tl->sb, "C{ ... }C");
+	else
+		VSB_printf(tl->sb, "'%.*s'", PF(t));
+}
+
+void
+vcc__ErrInternal(struct vcc *tl, const char *func, unsigned line)
+{
+
+	VSB_printf(tl->sb, "VCL compiler internal error at %s():%u\n",
+	    func, line);
+	tl->err = 1;
+}
+
+/*--------------------------------------------------------------------
+ * Find start of source-line of token
+ */
+
+static void
+vcc_iline(const struct token *t, const char **ll, int tail)
+{
+	const char *p, *b, *x;
+
+	b = t->src->b;
+	if (ll != NULL)
+		*ll = b;
+	x = tail ? t->e - 1 : t->b;
+	for (p = b; p < x; p++) {
+		if (*p == '\n') {
+			if (ll != NULL)
+				*ll = p + 1;
+		}
+	}
+}
+
+/*--------------------------------------------------------------------
+ * Find and print src+line+pos of this token
+ */
+
+static void
+vcc_icoord(struct vsb *vsb, const struct token *t, int tail)
+{
+	unsigned lin, pos;
+	const char *p, *b, *x;
+
+	lin = 1;
+	pos = 0;
+	b = t->src->b;
+	x = tail ? t->e - 1 : t->b;
+	for (p = b; p < x; p++) {
+		if (*p == '\n') {
+			lin++;
+			pos = 0;
+		} else if (*p == '\t') {
+			pos &= ~7;
+			pos += 8;
+		} else
+			pos++;
+	}
+	VSB_printf(vsb, "('%s' Line %u Pos %u)", t->src->name, lin, pos + 1);
+}
+
+/*--------------------------------------------------------------------*/
+
+void
+vcc_Coord(const struct vcc *tl, struct vsb *vsb, const struct token *t)
+{
+
+	if (t == NULL)
+		t = tl->t;
+	vcc_icoord(vsb, t, 0);
+}
+
+/*--------------------------------------------------------------------
+ * Output one line of source code, starting at 'l' and ending at the
+ * first NL or 'le'.
+ */
+
+static void
+vcc_quoteline(const struct vcc *tl, const char *l, const char *le)
+{
+	const char *p;
+	unsigned x, y;
+
+	x = y = 0;
+	for (p = l; p < le && *p != '\n'; p++) {
+		if (*p == '\t') {
+			y &= ~7;
+			y += 8;
+			while (x < y) {
+				VSB_bcat(tl->sb, " ", 1);
+				x++;
+			}
+		} else {
+			x++;
+			y++;
+			VSB_bcat(tl->sb, p, 1);
+		}
+	}
+	VSB_putc(tl->sb, '\n');
+}
+
+/*--------------------------------------------------------------------
+ * Output a marker line for a sourceline starting at 'l' and ending at
+ * the first NL or 'le'.  Characters between 'b' and 'e' are marked.
+ */
+
+static void
+vcc_markline(const struct vcc *tl, const char *l, const char *le,
+    const char *b, const char *e)
+{
+	const char *p;
+	unsigned x, y;
+	char c;
+
+	x = y = 0;
+	for (p = l; p < le && *p != '\n'; p++) {
+		if (p >= b && p < e)
+			c = '#';
+		else
+			c = '-';
+
+		if (*p == '\t') {
+			y &= ~7;
+			y += 8;
+		} else
+			y++;
+		while (x < y) {
+			VSB_putc(tl->sb, c);
+			x++;
+		}
+	}
+	VSB_putc(tl->sb, '\n');
+}
+
+/*--------------------------------------------------------------------*/
+/* XXX: should take first+last token */
+
+void
+vcc_ErrWhere2(struct vcc *tl, const struct token *t, const struct token *t2)
+{
+	const char  *l1, *l2, *l3;
+
+	if (t == NULL) {
+		vcc_ErrWhere(tl, t2);
+		return;
+	}
+	vcc_iline(t, &l1, 0);
+	t2 = VTAILQ_PREV(t2, tokenhead, list);
+	vcc_iline(t2, &l2, 1);
+
+
+	if (l1 == l2) {
+		vcc_icoord(tl->sb, t, 0);
+		VSB_cat(tl->sb, " -- ");
+		vcc_icoord(tl->sb, t2, 1);
+		VSB_putc(tl->sb, '\n');
+		/* Two tokens on same line */
+		vcc_quoteline(tl, l1, t->src->e);
+		vcc_markline(tl, l1, t->src->e, t->b, t2->e);
+	} else {
+		/* Two tokens different lines */
+		l3 = strchr(l1, '\n');
+		AN(l3);
+		/* XXX: t had better be before t2 */
+		vcc_icoord(tl->sb, t, 0);
+		if (l3 + 1 == l2) {
+			VSB_cat(tl->sb, " -- ");
+			vcc_icoord(tl->sb, t2, 1);
+		}
+		VSB_putc(tl->sb, '\n');
+		vcc_quoteline(tl, l1, t->src->e);
+		vcc_markline(tl, l1, t->src->e, t->b, t2->e);
+		if (l3 + 1 != l2) {
+			VSB_cat(tl->sb, "[...]\n");
+			vcc_icoord(tl->sb, t2, 1);
+			VSB_putc(tl->sb, '\n');
+		}
+		vcc_quoteline(tl, l2, t->src->e);
+		vcc_markline(tl, l2, t->src->e, t->b, t2->e);
+	}
+	VSB_putc(tl->sb, '\n');
+	tl->err = 1;
+}
+
+void
+vcc_ErrWhere(struct vcc *tl, const struct token *t)
+{
+	const char  *l1;
+
+	vcc_iline(t, &l1, 0);
+	vcc_icoord(tl->sb, t, 0);
+	VSB_putc(tl->sb, '\n');
+	vcc_quoteline(tl, l1, t->src->e);
+	vcc_markline(tl, l1, t->src->e, t->b, t->e);
+	VSB_putc(tl->sb, '\n');
+	tl->err = 1;
+}
+
+/*--------------------------------------------------------------------*/
+
+void
+vcc_NextToken(struct vcc *tl)
+{
+
+	tl->t = VTAILQ_NEXT(tl->t, list);
+	if (tl->t == NULL) {
+		VSB_printf(tl->sb,
+		    "Ran out of input, something is missing or"
+		    " maybe unbalanced (...) or {...}\n");
+		tl->err = 1;
+		return;
+	}
+}
+
+void
+vcc__Expect(struct vcc *tl, unsigned tok, unsigned line)
+{
+	if (tl->t->tok == tok)
+		return;
+	VSB_printf(tl->sb, "Expected %s got ", vcl_tnames[tok]);
+	vcc_ErrToken(tl, tl->t);
+	VSB_printf(tl->sb, "\n(program line %u), at\n", line);
+	vcc_ErrWhere(tl, tl->t);
+}
+
+/*--------------------------------------------------------------------
+ * Compare ID token to string, return true of match
+ */
+
+int
+vcc_IdIs(const 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);
+}
+
+/*--------------------------------------------------------------------
+ * Check that we have a C-identifier
+ */
+
+int
+vcc_isCid(const struct token *t)
+{
+	const char *q;
+
+	assert(t->tok == ID);
+	for (q = t->b; q < t->e; q++) {
+		if (!isalnum(*q) && *q != '_')
+			return (0);
+	}
+	return (1);
+}
+
+void
+vcc_ExpectCid(struct vcc *tl)
+{
+
+	ExpectErr(tl, ID);
+	ERRCHK(tl);
+	if (vcc_isCid(tl->t))
+		return;
+	VSB_printf(tl->sb, "Identifier ");
+	vcc_ErrToken(tl, tl->t);
+	VSB_printf(tl->sb,
+	    " contains illegal characters, use [0-9a-zA-Z_] only.\n");
+	vcc_ErrWhere(tl, tl->t);
+}
+
+/*--------------------------------------------------------------------
+ * Decode a string
+ */
+
+static int
+vcc_decstr(struct vcc *tl)
+{
+	char *q;
+	unsigned int l;
+
+	assert(tl->t->tok == CSTR);
+	l = (tl->t->e - tl->t->b) - 2;
+	tl->t->dec = TlAlloc(tl, l + 1);
+	assert(tl->t->dec != NULL);
+	q = tl->t->dec;
+	memcpy(q, tl->t->b + 1, l);
+	q[l] = '\0';
+	return (0);
+}
+
+/*--------------------------------------------------------------------
+ * Add a token to the token list.
+ */
+
+void
+vcc_AddToken(struct vcc *tl, unsigned tok, const char *b, const char *e)
+{
+	struct token *t;
+
+	t = TlAlloc(tl, sizeof *t);
+	assert(t != NULL);
+	t->tok = tok;
+	t->b = b;
+	t->e = e;
+	t->src = tl->src;
+	if (tl->t != NULL)
+		VTAILQ_INSERT_AFTER(&tl->tokens, tl->t, t, list);
+	else
+		VTAILQ_INSERT_TAIL(&tl->tokens, t, list);
+	tl->t = t;
+}
+
+/*--------------------------------------------------------------------
+ * Lexical analysis and token generation
+ */
+
+void
+vcc_Lexer(struct vcc *tl, struct source *sp)
+{
+	const char *p, *q;
+	unsigned u;
+
+	tl->src = sp;
+	for (p = sp->b; p < sp->e; ) {
+
+		/* Skip any whitespace */
+		if (isspace(*p)) {
+			p++;
+			continue;
+		}
+
+		/* Skip '#.*\n' comments */
+		if (*p == '#') {
+			while (p < sp->e && *p != '\n')
+				p++;
+			continue;
+		}
+
+		/* Skip C-style comments */
+		if (*p == '/' && p[1] == '*') {
+			for (q = p + 2; q < sp->e; q++) {
+				if (*q == '/' && q[1] == '*') {
+					VSB_printf(tl->sb,
+					    "/* ... */ comment contains /*\n");
+					vcc_AddToken(tl, EOI, p, p + 2);
+					vcc_ErrWhere(tl, tl->t);
+					vcc_AddToken(tl, EOI, q, q + 2);
+					vcc_ErrWhere(tl, tl->t);
+					return;
+				}
+				if (*q == '*' && q[1] == '/') {
+					p = q + 2;
+					break;
+				}
+			}
+			if (q < sp->e)
+				continue;
+			vcc_AddToken(tl, EOI, p, p + 2);
+			VSB_printf(tl->sb,
+			    "Unterminated /* ... */ comment, starting at\n");
+			vcc_ErrWhere(tl, tl->t);
+			return;
+		}
+
+		/* Skip C++-style comments */
+		if (*p == '/' && p[1] == '/') {
+			while (p < sp->e && *p != '\n')
+				p++;
+			continue;
+		}
+
+		/* Recognize inline C-code */
+		if (*p == 'C' && p[1] == '{') {
+			for (q = p + 2; q < sp->e; q++) {
+				if (*q == '}' && q[1] == 'C') {
+					vcc_AddToken(tl, CSRC, p, q + 2);
+					break;
+				}
+			}
+			if (q < sp->e) {
+				p = q + 2;
+				continue;
+			}
+			vcc_AddToken(tl, EOI, p, p + 2);
+			VSB_printf(tl->sb,
+			    "Unterminated inline C source, starting at\n");
+			vcc_ErrWhere(tl, tl->t);
+			return;
+		}
+
+		/* Recognize long-strings */
+		if (*p == '{' && p[1] == '"') {
+			for (q = p + 2; q < sp->e; q++) {
+				if (*q == '"' && q[1] == '}') {
+					vcc_AddToken(tl, CSTR, p, q + 2);
+					break;
+				}
+			}
+			if (q < sp->e) {
+				p = q + 2;
+				u = tl->t->e - tl->t->b;
+				u -= 4;		/* {" ... "} */
+				tl->t->dec = TlAlloc(tl, u + 1 );
+				AN(tl->t->dec);
+				memcpy(tl->t->dec, tl->t->b + 2, u);
+				tl->t->dec[u] = '\0';
+				continue;
+			}
+			vcc_AddToken(tl, EOI, p, p + 2);
+			VSB_printf(tl->sb,
+			    "Unterminated long-string, starting at\n");
+			vcc_ErrWhere(tl, tl->t);
+			return;
+		}
+
+		/* Match for the fixed tokens (see token.tcl) */
+		u = vcl_fixed_token(p, &q);
+		if (u != 0) {
+			vcc_AddToken(tl, u, p, q);
+			p = q;
+			continue;
+		}
+
+		/* Match strings */
+		if (*p == '"') {
+			for (q = p + 1; q < sp->e; q++) {
+				if (*q == '"') {
+					q++;
+					break;
+				}
+				if (*q == '\r' || *q == '\n') {
+					vcc_AddToken(tl, EOI, p, q);
+					VSB_printf(tl->sb,
+					    "Unterminated string at\n");
+					vcc_ErrWhere(tl, tl->t);
+					return;
+				}
+			}
+			vcc_AddToken(tl, CSTR, p, q);
+			if (vcc_decstr(tl))
+				return;
+			p = q;
+			continue;
+		}
+
+		/* Match Identifiers */
+		if (isident1(*p)) {
+			for (q = p; q < sp->e; q++)
+				if (!isvar(*q))
+					break;
+			vcc_AddToken(tl, ID, p, q);
+			p = q;
+			continue;
+		}
+
+		/* Match numbers { [0-9]+ } */
+		if (isdigit(*p)) {
+			for (q = p; q < sp->e; q++)
+				if (!isdigit(*q))
+					break;
+			vcc_AddToken(tl, CNUM, p, q);
+			p = q;
+			continue;
+		}
+		vcc_AddToken(tl, EOI, p, p + 1);
+		VSB_printf(tl->sb, "Syntax error at\n");
+		vcc_ErrWhere(tl, tl->t);
+		return;
+	}
+}
diff --git a/lib/libvcc/vcc_utils.c b/lib/libvcc/vcc_utils.c
new file mode 100644
index 0000000..5870af5
--- /dev/null
+++ b/lib/libvcc/vcc_utils.c
@@ -0,0 +1,255 @@
+/*-
+ * Copyright (c) 2006 Verdens Gang AS
+ * Copyright (c) 2006-2013 Varnish Software AS
+ * All rights reserved.
+ *
+ * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+
+#include "vcc_compile.h"
+
+#include "vre.h"
+#include "vrt.h"
+#include "vsa.h"
+
+/*--------------------------------------------------------------------*/
+
+const char *
+vcc_regexp(struct vcc *tl)
+{
+	char buf[BUFSIZ], *p;
+	vre_t *t;
+	const char *error;
+	int erroroffset;
+
+	Expect(tl, CSTR);
+	if (tl->err)
+		return (NULL);
+	memset(&t, 0, sizeof t);
+	t = VRE_compile(tl->t->dec, 0, &error, &erroroffset);
+	if (t == NULL) {
+		VSB_printf(tl->sb,
+		    "Regexp compilation error:\n\n%s\n\n", error);
+		vcc_ErrWhere(tl, tl->t);
+		return (NULL);
+	}
+	VRE_free(&t);
+	sprintf(buf, "VGC_re_%u", tl->unique++);
+	p = TlAlloc(tl, strlen(buf) + 1);
+	strcpy(p, buf);
+
+	Fh(tl, 0, "static void *%s;\n", buf);
+	Fi(tl, 0, "\tVRT_re_init(&%s, ",buf);
+	EncToken(tl->fi, tl->t);
+	Fi(tl, 0, ");\n");
+	Ff(tl, 0, "\tVRT_re_fini(%s);\n", buf);
+	return (p);
+}
+
+/*
+ * The IPv6 crew royally screwed up the entire idea behind
+ * struct sockaddr, and combined with various other incomptency
+ * in the OS business, that means that there is no sane or even
+ * remotely portable way to initialize a sockaddr at compile time.
+ *
+ * In our case it is slightly more tricky than that, because we don't
+ * even want to #include the struct sockaddr* definitions.
+ *
+ * Instead we make sure the sockaddr is sane (for our values of sane)
+ * and dump it in binary, using a 64 bit integertype, hoping that this
+ * will ensure good enough alignment.
+ */
+
+static const char *
+vcc_sockaddr(struct vcc *tl, const void *sa, unsigned sal)
+{
+	unsigned n = (sal + 7) / 8, len;
+	uint64_t b[n];
+	char *p;
+
+	assert(VSA_Sane(sa));
+	AN(sa);
+	AN(sal);
+	assert(sal < sizeof(struct sockaddr_storage));
+	assert(sizeof(unsigned long long) == 8);
+
+	p = TlAlloc(tl, 20);
+	sprintf(p, "sockaddr_%u", tl->unique++);
+
+	Fh(tl, 0, "static const unsigned long long");
+	Fh(tl, 0, " %s[%d] = {\n", p, n);
+	memcpy(b, sa, sal);
+	for (len = 0; len <n; len++) {
+		Fh(tl, 0, "%s    0x%016jx",
+		    len ? ",\n" : "",
+		    (uintmax_t)b[len]);
+	}
+	Fh(tl, 0, "\n};\n");
+	return (p);
+}
+
+/*--------------------------------------------------------------------
+ * This routine is a monster, but at least we only have one such monster.
+ * Look up a IP number, and return IPv4/IPv6 address as VGC produced names
+ * and optionally ascii strings.
+ *
+ * For IP compile time constants we only want one IP#, but it can be
+ * IPv4 or IPv6.
+ *
+ * For backends, we accept up to one IPv4 and one IPv6.
+ */
+
+struct foo_proto {
+	const char		*name;
+	int			family;
+	struct sockaddr_storage	sa;
+	socklen_t		l;
+	const char		**dst;
+	const char		**dst_ascii;
+};
+
+void
+Resolve_Sockaddr(struct vcc *tl,
+    const char *host,
+    const char *port,
+    const char **ipv4,
+    const char **ipv4_ascii,
+    const char **ipv6,
+    const char **ipv6_ascii,
+    const char **p_ascii,
+    int maxips,
+    const struct token *t_err,
+    const char *errid)
+{
+	struct foo_proto protos[3], *pp;
+	struct addrinfo *res, *res0, *res1, hint;
+	int error, retval;
+	char hbuf[NI_MAXHOST];
+
+	memset(protos, 0, sizeof protos);
+	protos[0].name = "ipv4";
+	protos[0].family = PF_INET;
+	protos[0].dst = ipv4;
+	protos[0].dst_ascii = ipv4_ascii;
+	*ipv4 = NULL;
+
+	protos[1].name = "ipv6";
+	protos[1].family = PF_INET6;
+	protos[1].dst = ipv6;
+	protos[1].dst_ascii = ipv6_ascii;
+	*ipv6 = NULL;
+
+	retval = 0;
+	memset(&hint, 0, sizeof hint);
+	hint.ai_family = PF_UNSPEC;
+	hint.ai_socktype = SOCK_STREAM;
+
+	error = getaddrinfo(host, port, &hint, &res0);
+	if (error) {
+		VSB_printf(tl->sb,
+		    "%s '%.*s' could not be resolved to an IP address:\n",
+		    errid, PF(t_err));
+		VSB_printf(tl->sb,
+		    "\t%s\n"
+		    "(Sorry if that error message is gibberish.)\n",
+		    gai_strerror(error));
+		vcc_ErrWhere(tl, t_err);
+		return;
+	}
+
+	for (res = res0; res; res = res->ai_next) {
+		for (pp = protos; pp->name != NULL; pp++)
+			if (res->ai_family == pp->family)
+				break;
+		if (pp->name == NULL) {
+			/* Unknown proto, ignore */
+			continue;
+		}
+		if (pp->l == res->ai_addrlen &&
+		    !memcmp(&pp->sa, res->ai_addr, pp->l)) {
+			/*
+			 * Same address we already emitted.
+			 * This can happen using /etc/hosts
+			 */
+			continue;
+		}
+
+		if (pp->l != 0 || retval == maxips) {
+			VSB_printf(tl->sb,
+			    "%s %.*s: resolves to too many addresses.\n"
+			    "Only one IPv4 %s IPv6 are allowed.\n"
+			    "Please specify which exact address "
+			    "you want to use, we found all of these:\n",
+			    errid, PF(t_err),
+			    maxips > 1 ? "and one" :  "or");
+			for (res1 = res0; res1 != NULL; res1 = res1->ai_next) {
+				error = getnameinfo(res1->ai_addr,
+				    res1->ai_addrlen, hbuf, sizeof hbuf,
+				    NULL, 0, NI_NUMERICHOST);
+				AZ(error);
+				VSB_printf(tl->sb, "\t%s\n", hbuf);
+			}
+			freeaddrinfo(res0);
+			vcc_ErrWhere(tl, t_err);
+			return;
+		}
+
+		pp->l =  res->ai_addrlen;
+		assert(pp->l < sizeof(struct sockaddr_storage));
+		memcpy(&pp->sa, res->ai_addr, pp->l);
+
+		error = getnameinfo(res->ai_addr, res->ai_addrlen,
+		    hbuf, sizeof hbuf, NULL, 0, NI_NUMERICHOST);
+		AZ(error);
+
+		Fh(tl, 0, "\n/* \"%s\" -> %s */\n", host, hbuf);
+		*(pp->dst) = vcc_sockaddr(tl, &pp->sa, pp->l);
+		if (pp->dst_ascii != NULL) {
+			*pp->dst_ascii = TlDup(tl, hbuf);
+		}
+		retval++;
+	}
+	if (p_ascii != NULL) {
+		error = getnameinfo(res0->ai_addr,
+		    res0->ai_addrlen, NULL, 0, hbuf, sizeof hbuf,
+		    NI_NUMERICSERV);
+		AZ(error);
+		*p_ascii = TlDup(tl, hbuf);
+	}
+	if (retval == 0) {
+		VSB_printf(tl->sb,
+		    "%s '%.*s': resolves to "
+		    "neither IPv4 nor IPv6 addresses.\n",
+		    errid, PF(t_err) );
+		vcc_ErrWhere(tl, t_err);
+	}
+}
diff --git a/lib/libvcc/vcc_var.c b/lib/libvcc/vcc_var.c
new file mode 100644
index 0000000..74713b8
--- /dev/null
+++ b/lib/libvcc/vcc_var.c
@@ -0,0 +1,134 @@
+/*-
+ * Copyright (c) 2006 Verdens Gang AS
+ * Copyright (c) 2006-2011 Varnish Software AS
+ * All rights reserved.
+ *
+ * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include "vcc_compile.h"
+#include "vct.h"
+
+/*--------------------------------------------------------------------*/
+
+struct symbol *
+vcc_Var_Wildcard(struct vcc *tl, const struct token *t, const struct symbol *wc)
+{
+	struct symbol *sym;
+	struct var *v;
+	const struct var *vh;
+	int l, i;
+	char c;
+	char buf[258];
+	char cnam[256];
+
+	vh = wc->var;
+
+	v = TlAlloc(tl, sizeof *v);
+	AN(v);
+
+	assert(vh->fmt == HEADER);
+	v->name = TlDupTok(tl, t);
+	v->r_methods = vh->r_methods;
+	v->w_methods = vh->w_methods;
+	v->fmt = vh->fmt;
+
+	/* Create a C-name version of the header name */
+	l = strlen(v->name + vh->len) + 1;
+	for (i = 0; i < l - 1; i++) {
+		c = *(v->name + vh->len + i);
+		if (vct_isalpha(c) || vct_isdigit(c))
+			cnam[i] = c;
+		else
+			cnam[i] = '_';
+	}
+	cnam[i] = '\0';
+
+	/* Create the static identifier */
+	Fh(tl, 0, "static const struct gethdr_s VGC_%s_%s =\n",
+	    vh->rname, cnam);
+	Fh(tl, 0, "    { %s, \"\\%03o%s:\"};\n",
+	    vh->rname, (unsigned)l, v->name + vh->len);
+
+	bprintf(buf, "&VGC_%s_%s", vh->rname, cnam);
+	v->rname = TlDup(tl, buf);
+	bprintf(buf, "VRT_SetHdr(ctx, %s, ", v->rname);
+	v->lname = TlDup(tl, buf);
+
+	sym = VCC_AddSymbolTok(tl, t, SYM_VAR);
+	AN(sym);
+	sym->var = v;
+	sym->fmt = v->fmt;
+	sym->eval = vcc_Eval_Var;
+	sym->r_methods = v->r_methods;
+	return (sym);
+}
+
+/*--------------------------------------------------------------------*/
+
+const struct var *
+vcc_FindVar(struct vcc *tl, const struct token *t, int wr_access,
+    const char *use)
+{
+	const struct var *v;
+	const struct symbol *sym;
+
+	AN(tl->vars);
+	sym = VCC_FindSymbol(tl, t, SYM_VAR);
+	if (sym != NULL) {
+		v = sym->var;
+		AN(v);
+
+		if (wr_access && v->w_methods == 0) {
+			VSB_printf(tl->sb, "Variable ");
+			vcc_ErrToken(tl, t);
+			VSB_printf(tl->sb, " is read only.");
+			VSB_cat(tl->sb, "\nAt: ");
+			vcc_ErrWhere(tl, t);
+			return (NULL);
+		} else if (wr_access) {
+			vcc_AddUses(tl, t, v->w_methods, use);
+		} else if (v->r_methods == 0) {
+			VSB_printf(tl->sb, "Variable ");
+			vcc_ErrToken(tl, t);
+			VSB_printf(tl->sb, " is write only.");
+			VSB_cat(tl->sb, "\nAt: ");
+			vcc_ErrWhere(tl, t);
+			return (NULL);
+		} else {
+			vcc_AddUses(tl, t, v->r_methods, use);
+		}
+		return (v);
+	}
+	VSB_printf(tl->sb, "Unknown variable ");
+	vcc_ErrToken(tl, t);
+	VSB_cat(tl->sb, "\nAt: ");
+	vcc_ErrWhere(tl, t);
+	return (NULL);
+}
diff --git a/lib/libvcc/vcc_vmod.c b/lib/libvcc/vcc_vmod.c
new file mode 100644
index 0000000..7eb9d32c
--- /dev/null
+++ b/lib/libvcc/vcc_vmod.c
@@ -0,0 +1,204 @@
+/*-
+ * Copyright (c) 2010-2013 Varnish Software AS
+ * All rights reserved.
+ *
+ * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#include <dlfcn.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "vcc_compile.h"
+
+#include "vmod_abi.h"
+
+void
+vcc_ParseImport(struct vcc *tl)
+{
+	void *hdl;
+	char fn[1024];
+	char buf[256];
+	struct token *mod, *t1;
+	const char *modname;
+	const char *proto;
+	const char *abi;
+	const char **spec;
+	struct symbol *sym;
+	const struct symbol *osym;
+	const char *p;
+	// int *modlen;
+
+	t1 = tl->t;
+	SkipToken(tl, ID);		/* "import" */
+
+	ExpectErr(tl, ID);
+	mod = tl->t;
+	vcc_NextToken(tl);
+
+	osym = VCC_FindSymbol(tl, mod, SYM_NONE);
+	if (osym != NULL && osym->kind != SYM_VMOD) {
+		VSB_printf(tl->sb, "Module %.*s conflics with other symbol.\n",
+		    PF(mod));
+		vcc_ErrWhere2(tl, t1, tl->t);
+		return;
+	}
+	if (osym != NULL) {
+		VSB_printf(tl->sb, "Module %.*s already imported.\n",
+		    PF(mod));
+		vcc_ErrWhere2(tl, t1, tl->t);
+		VSB_printf(tl->sb, "Previous import was here:\n");
+		vcc_ErrWhere2(tl, osym->def_b, osym->def_e);
+		return;
+	}
+
+	bprintf(fn, "%.*s", PF(mod));
+	sym = VCC_AddSymbolStr(tl, fn, SYM_VMOD);
+	ERRCHK(tl);
+	AN(sym);
+	sym->def_b = t1;
+	sym->def_e = tl->t;
+
+	if (tl->t->tok == ID) {
+		if (!tl->unsafe_path) {
+			VSB_printf(tl->sb,
+			    "'import ... from path...'"
+			    " not allowed.\nAt:");
+			vcc_ErrToken(tl, tl->t);
+			vcc_ErrWhere(tl, tl->t);
+			return;
+		}
+		if (!vcc_IdIs(tl->t, "from")) {
+			VSB_printf(tl->sb, "Expected 'from path...'\n");
+			vcc_ErrWhere(tl, tl->t);
+			return;
+		}
+		vcc_NextToken(tl);
+		ExpectErr(tl, CSTR);
+		bprintf(fn, "%s", tl->t->dec);
+		vcc_NextToken(tl);
+	} else {
+		bprintf(fn, "%s/libvmod_%.*s.so", tl->vmod_dir, PF(mod));
+	}
+
+	Fh(tl, 0, "static void *VGC_vmod_%.*s;\n", PF(mod));
+
+	Fi(tl, 0, "\tif (VRT_Vmod_Init(&VGC_vmod_%.*s,\n", PF(mod));
+	Fi(tl, 0, "\t    &Vmod_%.*s_Func,\n", PF(mod));
+	Fi(tl, 0, "\t    sizeof(Vmod_%.*s_Func),\n", PF(mod));
+	Fi(tl, 0, "\t    \"%.*s\",\n", PF(mod));
+	Fi(tl, 0, "\t    ");
+	EncString(tl->fi, fn, NULL, 0);
+	Fi(tl, 0, ",\n\t    ");
+	Fi(tl, 0, "cli))\n");
+	Fi(tl, 0, "\t\treturn(1);\n");
+
+	SkipToken(tl, ';');
+
+	hdl = dlopen(fn, RTLD_NOW | RTLD_LOCAL);
+	if (hdl == NULL) {
+		VSB_printf(tl->sb, "Could not load module %.*s\n\t%s\n\t%s\n",
+		    PF(mod), fn, dlerror());
+		vcc_ErrWhere(tl, mod);
+		return;
+	}
+
+	bprintf(buf, "Vmod_%.*s_Name", PF(mod));
+	modname = dlsym(hdl, buf);
+	if (modname == NULL) {
+		VSB_printf(tl->sb, "Could not load module %.*s\n\t%s\n\t%s\n",
+		    PF(mod), fn, "Symbol Vmod_Name not found");
+		vcc_ErrWhere(tl, mod);
+		return;
+	}
+	if (!vcc_IdIs(mod, modname)) {
+		VSB_printf(tl->sb, "Could not load module %.*s\n\t%s\n",
+		    PF(mod), fn);
+		VSB_printf(tl->sb, "\tModule has wrong name: <%s>\n", modname);
+		vcc_ErrWhere(tl, mod);
+		return;
+	}
+
+	bprintf(buf, "Vmod_%.*s_ABI", PF(mod));
+	abi = dlsym(hdl, buf);
+	if (abi == NULL || strcmp(abi, VMOD_ABI_Version) != 0) {
+		VSB_printf(tl->sb, "Could not load module %.*s\n\t%s\n",
+		    PF(mod), fn);
+		VSB_printf(tl->sb, "\tABI mismatch, expected <%s>, got <%s>\n",
+			   VMOD_ABI_Version, abi);
+		vcc_ErrWhere(tl, mod);
+		return;
+	}
+
+	bprintf(buf, "Vmod_%.*s_Proto", PF(mod));
+	proto = dlsym(hdl, buf);
+	if (proto == NULL) {
+		VSB_printf(tl->sb, "Could not load module %.*s\n\t%s\n\t%s\n",
+		    PF(mod), fn, "Symbol Vmod_Proto not found");
+		vcc_ErrWhere(tl, mod);
+		return;
+	}
+	bprintf(buf, "Vmod_%.*s_Spec", PF(mod));
+	spec = dlsym(hdl, buf);
+	if (spec == NULL) {
+		VSB_printf(tl->sb, "Could not load module %.*s\n\t%s\n\t%s\n",
+		    PF(mod), fn, "Symbol Vmod_Spec not found");
+		vcc_ErrWhere(tl, mod);
+		return;
+	}
+	Fh(tl, 0, "static struct vmod_priv vmod_priv_%.*s;\n", PF(mod));
+	for (; *spec != NULL; spec++) {
+		p = *spec;
+		if (!strcmp(p, "OBJ")) {
+			p += strlen(p) + 1;
+			sym = VCC_AddSymbolStr(tl, p, SYM_OBJECT);
+			XXXAN(sym);
+			sym->args = p;
+		} else if (!strcmp(p, "INIT")) {
+			p += strlen(p) + 1;
+			Fi(tl, 0, "\t%s(&vmod_priv_%.*s, &VCL_conf);\n",
+			    p, PF(mod));
+		} else {
+			sym = VCC_AddSymbolStr(tl, p, SYM_FUNC);
+			ERRCHK(tl);
+			AN(sym);
+			sym->eval = vcc_Eval_SymFunc;
+			p += strlen(p) + 1;
+			sym->cfunc = p;
+			p += strlen(p) + 1;
+			sym->args = p;
+
+			/* Functions which return VOID are procedures */
+			if (!memcmp(p, "VOID\0", 5))
+				sym->kind = SYM_PROC;
+		}
+	}
+	Fh(tl, 0, "\n%s\n", proto);
+
+	/* XXX: zero the function pointer structure ?*/
+	Ff(tl, 0, "\tvmod_priv_fini(&vmod_priv_%.*s);\n", PF(mod));
+	Ff(tl, 0, "\tVRT_Vmod_Fini(&VGC_vmod_%.*s);\n", PF(mod));
+}
diff --git a/lib/libvcc/vcc_xref.c b/lib/libvcc/vcc_xref.c
new file mode 100644
index 0000000..c3ef375
--- /dev/null
+++ b/lib/libvcc/vcc_xref.c
@@ -0,0 +1,388 @@
+/*-
+ * Copyright (c) 2006 Verdens Gang AS
+ * Copyright (c) 2006-2011 Varnish Software AS
+ * All rights reserved.
+ *
+ * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file contains code for two cross-reference or consistency checks.
+ *
+ * The first check is simply that all subroutine, acls and backends are
+ * both defined and referenced.  Complaints about referenced but undefined
+ * or defined but unreferenced objects will be emitted.
+ *
+ * The second check recursively decends through subroutine calls to make
+ * sure that action actions are correct for the methods through which
+ * they are called.
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+
+#include "vcc_compile.h"
+
+/*--------------------------------------------------------------------*/
+
+struct proccall {
+	VTAILQ_ENTRY(proccall)	list;
+	struct proc		*p;
+	struct token		*t;
+};
+
+struct procuse {
+	VTAILQ_ENTRY(procuse)	list;
+	const struct token	*t;
+	unsigned		mask;
+	const char		*use;
+};
+
+struct proc {
+	VTAILQ_HEAD(,proccall)	calls;
+	VTAILQ_HEAD(,procuse)	uses;
+	struct token		*name;
+	unsigned		ret_bitmap;
+	unsigned		exists;
+	unsigned		called;
+	unsigned		active;
+	struct token		*return_tok[VCL_RET_MAX];
+};
+
+/*--------------------------------------------------------------------
+ * Keep track of definitions and references
+ */
+
+void
+vcc_AddRef(struct vcc *tl, const struct token *t, enum symkind kind)
+{
+	struct symbol *sym;
+
+	sym = VCC_GetSymbolTok(tl, t, kind);
+	AN(sym);
+	sym->nref++;
+}
+
+int
+vcc_AddDef(struct vcc *tl, const struct token *t, enum symkind kind)
+{
+	struct symbol *sym;
+
+	sym = VCC_GetSymbolTok(tl, t, kind);
+	AN(sym);
+	sym->ndef++;
+	return (sym->ndef);
+}
+
+/*--------------------------------------------------------------------*/
+
+static void
+vcc_checkref(struct vcc *tl, const struct symbol *sym)
+{
+
+	if (sym->ndef == 0 && sym->nref != 0) {
+		VSB_printf(tl->sb, "Undefined %s %.*s, first reference:\n",
+		    VCC_SymKind(tl, sym), PF(sym->def_b));
+		vcc_ErrWhere(tl, sym->def_b);
+	} else if (sym->ndef != 0 && sym->nref == 0) {
+		VSB_printf(tl->sb, "Unused %s %.*s, defined:\n",
+		    VCC_SymKind(tl, sym), PF(sym->def_b));
+		vcc_ErrWhere(tl, sym->def_b);
+		if (!tl->err_unref) {
+			VSB_printf(tl->sb, "(That was just a warning)\n");
+			tl->err = 0;
+		}
+	}
+}
+
+int
+vcc_CheckReferences(struct vcc *tl)
+{
+
+	VCC_WalkSymbols(tl, vcc_checkref, SYM_NONE);
+	return (tl->err);
+}
+
+/*--------------------------------------------------------------------
+ * Returns checks
+ */
+
+static struct proc *
+vcc_findproc(struct vcc *tl, struct token *t)
+{
+	struct symbol *sym;
+	struct proc *p;
+
+
+	sym = VCC_GetSymbolTok(tl, t, SYM_SUB);
+	AN(sym);
+	if (sym->proc != NULL)
+		return (sym->proc);
+
+	p = TlAlloc(tl, sizeof *p);
+	assert(p != NULL);
+	VTAILQ_INIT(&p->calls);
+	VTAILQ_INIT(&p->uses);
+	p->name = t;
+	sym->proc = p;
+	return (p);
+}
+
+struct proc *
+vcc_AddProc(struct vcc *tl, struct token *t)
+{
+	struct proc *p;
+
+	p = vcc_findproc(tl, t);
+	p->name = t;	/* make sure the name matches the definition */
+	p->exists++;
+	return (p);
+}
+
+void
+vcc_AddUses(struct vcc *tl, const struct token *t, unsigned mask,
+    const char *use)
+{
+	struct procuse *pu;
+
+	if (tl->curproc == NULL)	/* backend */
+		return;
+	pu = TlAlloc(tl, sizeof *pu);
+	assert(pu != NULL);
+	pu->t = t;
+	pu->mask = mask;
+	pu->use = use;
+	VTAILQ_INSERT_TAIL(&tl->curproc->uses, pu, list);
+}
+
+void
+vcc_AddCall(struct vcc *tl, struct token *t)
+{
+	struct proccall *pc;
+	struct proc *p;
+
+	p = vcc_findproc(tl, t);
+	pc = TlAlloc(tl, sizeof *pc);
+	assert(pc != NULL);
+	pc->p = p;
+	pc->t = t;
+	VTAILQ_INSERT_TAIL(&tl->curproc->calls, pc, list);
+}
+
+void
+vcc_ProcAction(struct proc *p, unsigned returns, struct token *t)
+{
+
+	assert(returns < VCL_RET_MAX);
+	p->ret_bitmap |= (1U << returns);
+	/* Record the first instance of this return */
+	if (p->return_tok[returns] == NULL)
+		p->return_tok[returns] = t;
+}
+
+static int
+vcc_CheckActionRecurse(struct vcc *tl, struct proc *p, unsigned bitmap)
+{
+	unsigned u;
+	struct proccall *pc;
+
+	if (!p->exists) {
+		VSB_printf(tl->sb, "Function %.*s does not exist\n",
+		    PF(p->name));
+		return (1);
+	}
+	if (p->active) {
+		VSB_printf(tl->sb, "Function recurses on\n");
+		vcc_ErrWhere(tl, p->name);
+		return (1);
+	}
+	u = p->ret_bitmap & ~bitmap;
+	if (u) {
+
+#define VCL_RET_MAC(l, U, B)						\
+		if (u & (1 << (VCL_RET_##U))) {				\
+			VSB_printf(tl->sb, "Invalid return \"" #l "\"\n");\
+			vcc_ErrWhere(tl, p->return_tok[VCL_RET_##U]);	\
+		}
+#include "tbl/vcl_returns.h"
+#undef VCL_RET_MAC
+
+		VSB_printf(tl->sb, "\n...in subroutine \"%.*s\"\n",
+		    PF(p->name));
+		vcc_ErrWhere(tl, p->name);
+		return (1);
+	}
+	p->active = 1;
+	VTAILQ_FOREACH(pc, &p->calls, list) {
+		if (vcc_CheckActionRecurse(tl, pc->p, bitmap)) {
+			VSB_printf(tl->sb, "\n...called from \"%.*s\"\n",
+			    PF(p->name));
+			vcc_ErrWhere(tl, pc->t);
+			return (1);
+		}
+	}
+	p->active = 0;
+	p->called++;
+	return (0);
+}
+
+/*--------------------------------------------------------------------*/
+
+static void
+vcc_checkaction1(struct vcc *tl, const struct symbol *sym)
+{
+	struct proc *p;
+	struct method *m;
+	int i;
+
+	p = sym->proc;
+	AN(p);
+	i = IsMethod(p->name);
+	if (i < 0)
+		return;
+	m = method_tab + i;
+	if (vcc_CheckActionRecurse(tl, p, m->ret_bitmap)) {
+		VSB_printf(tl->sb,
+		    "\n...which is the \"%s\" method\n", m->name);
+		VSB_printf(tl->sb, "Legal returns are:");
+#define VCL_RET_MAC(l, U, B)						\
+		if (m->ret_bitmap & ((1 << VCL_RET_##U)))	\
+			VSB_printf(tl->sb, " \"%s\"", #l);
+
+#include "tbl/vcl_returns.h"
+#undef VCL_RET_MAC
+		VSB_printf(tl->sb, "\n");
+		tl->err = 1;
+	}
+
+}
+
+static void
+vcc_checkaction2(struct vcc *tl, const struct symbol *sym)
+{
+	struct proc *p;
+
+	p = sym->proc;
+	AN(p);
+
+	if (p->called)
+		return;
+	VSB_printf(tl->sb, "Function unused\n");
+	vcc_ErrWhere(tl, p->name);
+	if (!tl->err_unref) {
+		VSB_printf(tl->sb, "(That was just a warning)\n");
+		tl->err = 0;
+	}
+}
+
+int
+vcc_CheckAction(struct vcc *tl)
+{
+
+	VCC_WalkSymbols(tl, vcc_checkaction1, SYM_SUB);
+	if (tl->err)
+		return (tl->err);
+	VCC_WalkSymbols(tl, vcc_checkaction2, SYM_SUB);
+	return (tl->err);
+}
+
+/*--------------------------------------------------------------------*/
+
+static struct procuse *
+vcc_FindIllegalUse(const struct proc *p, const struct method *m)
+{
+	struct procuse *pu;
+
+	VTAILQ_FOREACH(pu, &p->uses, list)
+		if (!(pu->mask & m->bitval))
+			return (pu);
+	return (NULL);
+}
+
+static int
+vcc_CheckUseRecurse(struct vcc *tl, const struct proc *p,
+    struct method *m)
+{
+	struct proccall *pc;
+	struct procuse *pu;
+
+	pu = vcc_FindIllegalUse(p, m);
+	if (pu != NULL) {
+		VSB_printf(tl->sb,
+		    "'%.*s': %s from method '%.*s'.\n",
+		    PF(pu->t), pu->use, PF(p->name));
+		vcc_ErrWhere(tl, pu->t);
+		VSB_printf(tl->sb, "\n...in subroutine \"%.*s\"\n",
+		    PF(p->name));
+		vcc_ErrWhere(tl, p->name);
+		return (1);
+	}
+	VTAILQ_FOREACH(pc, &p->calls, list) {
+		if (vcc_CheckUseRecurse(tl, pc->p, m)) {
+			VSB_printf(tl->sb, "\n...called from \"%.*s\"\n",
+			    PF(p->name));
+			vcc_ErrWhere(tl, pc->t);
+			return (1);
+		}
+	}
+	return (0);
+}
+
+static void
+vcc_checkuses(struct vcc *tl, const struct symbol *sym)
+{
+	struct proc *p;
+	struct method *m;
+	struct procuse *pu;
+	int i;
+
+	p = sym->proc;
+	AN(p);
+
+	i = IsMethod(p->name);
+	if (i < 0)
+		return;
+	m = method_tab + i;
+	pu = vcc_FindIllegalUse(p, m);
+	if (pu != NULL) {
+		VSB_printf(tl->sb,
+		    "'%.*s': %s in method '%.*s'.",
+		    PF(pu->t), pu->use, PF(p->name));
+		VSB_cat(tl->sb, "\nAt: ");
+		vcc_ErrWhere(tl, pu->t);
+		return;
+	}
+	if (vcc_CheckUseRecurse(tl, p, m)) {
+		VSB_printf(tl->sb,
+		    "\n...which is the \"%s\" method\n", m->name);
+		return;
+	}
+}
+
+int
+vcc_CheckUses(struct vcc *tl)
+{
+
+	VCC_WalkSymbols(tl, vcc_checkuses, SYM_SUB);
+	return (tl->err);
+}
diff --git a/lib/libvcc/vmodtool.py b/lib/libvcc/vmodtool.py
new file mode 100755
index 0000000..2b6db42
--- /dev/null
+++ b/lib/libvcc/vmodtool.py
@@ -0,0 +1,553 @@
+#!/usr/bin/env python
+#-
+# Copyright (c) 2010-2013 Varnish Software AS
+# All rights reserved.
+#
+# Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+#    notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+#    notice, this list of conditions and the following disclaimer in the
+#    documentation and/or other materials provided with the distribution.
+#
+# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+# SUCH DAMAGE.
+#
+# Read the vmod.spec file and produce the vmod.h and vmod.c files.
+#
+# vmod.h contains the prototypes for the published functions, the module
+# C-code should include this file to ensure type-consistency.
+#
+# vmod.c contains the symbols which VCC and varnishd will use to access
+# the module:  A structure of properly typed function pointers, the
+# size of this structure in bytes, and the definition of the structure
+# as a string, suitable for inclusion in the C-source of the compile VCL
+# program.
+
+import sys
+import re
+
+if len(sys.argv) == 2:
+	specfile = sys.argv[1]
+else:
+	specfile = "vmod.vcc"
+
+ctypes = {
+	'BACKEND':	"VCL_BACKEND",
+	'BOOL':		"VCL_BOOL",
+	'DURATION':	"VCL_DURATION",
+	'ENUM':		"VCL_ENUM",
+	'HEADER':	"const struct gethdr_s *",
+	'INT':		"VCL_INT",
+	'IP':		"VCL_IP",
+	'PRIV_CALL':	"struct vmod_priv *",
+	'PRIV_VCL':	"struct vmod_priv *",
+	'REAL':		"VCL_REAL",
+	'STRING':	"VCL_STRING",
+	'STRING_LIST':	"const char *, ...",
+	'TIME':		"VCL_TIME",
+	'VOID':		"VCL_VOID",
+}
+
+#######################################################################
+
+def file_header(fo):
+        fo.write("""/*
+ * NB:  This file is machine generated, DO NOT EDIT!
+ *
+ * Edit vmod.vcc and run vmod.py instead
+ */
+
+""")
+
+#######################################################################
+
+def is_c_name(s):
+	return None != re.match("^[a-z][a-z0-9_]*$", s)
+
+#######################################################################
+
+class token(object):
+	def __init__(self, ln, ch, str):
+		self.ln = ln
+		self.ch = ch
+		self.str = str
+
+	def __repr__(self):
+		return "<@%d \"%s\">" % (self.ln, self.str)
+
+#######################################################################
+
+class vmod(object):
+	def __init__(self, nam):
+		if not is_c_name(nam):
+			raise Exception("Module name '%s' is illegal" % nam)
+		self.nam = nam
+		self.init = None
+		self.funcs = list()
+		self.objs = list()
+
+	def set_init(self, nam):
+		if self.init != None:
+			raise Exception("Module %s already has Init" % self.nam)
+		if not is_c_name(nam):
+			raise Exception("Init name '%s' is illegal" % nam)
+		self.init = nam
+
+	def add_func(self, fn):
+		self.funcs.append(fn)
+
+	def add_obj(self, obj):
+		self.objs.append(obj)
+		obj.set_modnam(self.nam)
+
+	def c_proto(self, fo):
+		for o in self.objs:
+			o.c_proto(fo)
+			fo.write("\n")
+		for f in self.funcs:
+			f.c_proto(fo)
+		if self.init != None:
+			fo.write("\n")
+			fo.write("int " + self.init)
+			fo.write(
+			    "(struct vmod_priv *, const struct VCL_conf *);\n")
+		#fo.write("\n")
+		#fo.write("extern const void * const Vmod_" + self.nam + "_Id;\n")
+
+	def c_typedefs_(self):
+		l = list()
+		for o in self.objs:
+			for t in o.c_typedefs(self.nam):
+				l.append(t)
+			l.append("")
+		l.append("/* Functions */")
+		for f in self.funcs:
+			l.append(f.c_typedef(self.nam))
+		l.append("")
+		return l
+
+	def c_typedefs(self, fo):
+		for i in self.c_typedefs_():
+			fo.write(i + "\n")
+
+	def c_vmod(self, fo):
+		fo.write('const char Vmod_' + self.nam + '_Name[] =')
+		fo.write(' \"' + self.nam + '";\n')
+		fo.write("\n")
+
+		cs = self.c_struct()
+		fo.write("const " + cs + ' Vmod_' + self.nam + '_Func = ')
+		fo.write(self.c_initializer())
+		fo.write("\n")
+
+		fo.write("\n")
+		fo.write("const int Vmod_" + self.nam + '_Len =')
+		fo.write(" sizeof(Vmod_" + self.nam + "_Func);\n")
+		fo.write("\n")
+
+		fo.write("const char Vmod_" + self.nam + "_Proto[] =\n")
+		for t in self.c_typedefs_():
+			fo.write('\t"' + t + '\\n"\n')
+		fo.write('\t"\\n"\n')
+		for i in (cs + " Vmod_" + self.nam + '_Func;').split("\n"):
+			fo.write('\n\t"' + i + '\\n"')
+		fo.write(";\n\n")
+
+		fo.write(self.c_strspec())
+
+		fo.write("\n")
+		fo.write('const char Vmod_' + self.nam + '_ABI[] =')
+		fo.write(' VMOD_ABI_Version;\n')
+		#fo.write("\n")
+		#fo.write('const void * const Vmod_' + self.nam + '_Id =')
+		#fo.write(' &Vmod_' + self.nam + '_Id;\n')
+
+	def c_initializer(self):
+		s = '{\n'
+		for o in self.objs:
+			s += o.c_initializer()
+
+		s += "\n\t/* Functions */\n"
+		for f in self.funcs:
+			s += f.c_initializer()
+
+		s += "\n\t/* Init/Fini */\n"
+		if self.init != None:
+			s += "\t" + self.init + ",\n"
+		s += "};"
+
+		return s
+
+	def c_struct(self):
+		s = 'struct Vmod_' + self.nam + '_Func {\n'
+		for o in self.objs:
+			s += o.c_struct(self.nam)
+
+		s += "\n\t/* Functions */\n"
+		for f in self.funcs:
+			s += f.c_struct(self.nam)
+
+		s += "\n\t/* Init/Fini */\n"
+		if self.init != None:
+			s += "\tvmod_init_f\t*_init;\n"
+		s += '}'
+		return s
+
+	def c_strspec(self):
+		s = "const char * const Vmod_" + self.nam + "_Spec[] = {\n"
+
+		for o in self.objs:
+			s += o.c_strspec(self.nam)
+
+		s += "\n\t/* Functions */\n"
+		for f in self.funcs:
+			s += '\t"' + f.c_strspec(self.nam) + '",\n'
+
+		s += "\n\t/* Init/Fini */\n"
+		if self.init != None:
+			s += '\t"INIT\\0Vmod_' + self.nam + '_Func._init",\n'
+
+		s += "\t0\n"
+		s += "};\n"
+		return s
+
+#######################################################################
+
+class func(object):
+	def __init__(self, nam, retval, al):
+		#if not is_c_name(nam):
+		#	raise Exception("Func name '%s' is illegal" % nam)
+		if retval not in ctypes:
+			raise Exception(
+			    "Return type '%s' not a valid type" % retval)
+		self.nam = nam
+		self.cnam = nam.replace(".", "_")
+		self.al = al
+		self.retval = retval
+		self.pfx = None
+
+	def __repr__(self):
+		return "<FUNC %s %s>" % (self.retval, self.nam)
+
+	def set_pfx(self, s):
+		self.pfx = s
+
+	def c_proto(self, fo, fini=False):
+		fo.write(ctypes[self.retval])
+		fo.write(" vmod_" + self.cnam + "(")
+		p = ""
+		if not fini:
+			fo.write("const struct vrt_ctx *")
+			p = ", "
+		if self.pfx != None:
+			fo.write(p + self.pfx)
+			p = ", "
+		for a in self.al:
+			fo.write(p + ctypes[a.typ])
+			p = ", "
+			if a.nam != None:
+				fo.write(" " + a.nam)
+		fo.write(");\n")
+
+	def c_typedef(self, modname, fini=False):
+		s = "typedef "
+		s += ctypes[self.retval]
+		s += " td_" + modname + "_" + self.cnam + "("
+		p = ""
+		if not fini:
+			s += "const struct vrt_ctx *"
+			p = ", "
+		if self.pfx != None:
+			s += p + self.pfx
+			p = ", "
+		for a in self.al:
+			s += p + ctypes[a.typ]
+			p = ", "
+		s += ");"
+		return s
+
+	def c_struct(self, modname):
+		s = '\ttd_' + modname + "_" + self.cnam
+		while len(s.expandtabs()) < 40:
+			s += "\t"
+		s += "*" + self.cnam + ";\n"
+		return s
+
+	def c_initializer(self):
+		return "\tvmod_" + self.cnam + ",\n"
+
+	def c_strspec(self, modnam):
+		s = modnam + "." + self.nam
+		s += "\\0"
+		s += "Vmod_" + modnam + "_Func." + self.cnam + "\\0"
+		s += self.retval + "\\0"
+		for a in self.al:
+			s += a.c_strspec()
+		return s
+
+#######################################################################
+
+class obj(object):
+	def __init__(self, nam):
+		self.nam = nam
+		self.init = None
+		self.fini = None
+		self.methods = list()
+
+	def set_modnam(self, modnam):
+		self.st = "struct vmod_" + modnam + "_" + self.nam
+		self.init.set_pfx(self.st + " **, const char *")
+		self.fini.set_pfx(self.st + " **")
+		for m in self.methods:
+			m.set_pfx(self.st + " *")
+
+	def set_init(self, f):
+		self.init = f
+		self.fini = func(f.nam, "VOID", [])
+		self.init.cnam += "__init"
+		self.fini.cnam += "__fini"
+
+	def add_method(self, m):
+		self.methods.append(m)
+
+	def c_typedefs(self, modnam):
+		l = list()
+		l.append("/* Object " + self.nam + " */")
+		l.append(self.st + ";")
+		l.append(self.init.c_typedef(modnam) + "")
+		l.append(self.fini.c_typedef(modnam, fini=True) + "")
+		for m in self.methods:
+			l.append(m.c_typedef(modnam) + "")
+		return l
+
+	def c_proto(self, fo):
+		fo.write(self.st + ";\n")
+		self.init.c_proto(fo)
+		self.fini.c_proto(fo, fini = True)
+		for m in self.methods:
+			m.c_proto(fo)
+
+	def c_struct(self, modnam):
+		s = "\t/* Object " + self.nam + " */\n"
+		s += self.init.c_struct(modnam)
+		s += self.fini.c_struct(modnam)
+		for m in self.methods:
+			s += m.c_struct(modnam)
+		return s
+
+	def c_initializer(self):
+		s = "\t/* Object " + self.nam + " */\n"
+		s += self.init.c_initializer()
+		s += self.fini.c_initializer()
+		for m in self.methods:
+			s += m.c_initializer()
+		return s
+
+	def c_strspec(self, modnam):
+		s = "\t/* Object " + self.nam + " */\n"
+		s += '\t"OBJ\\0"\n'
+		s += '\t\t"' + self.init.c_strspec(modnam) + '\\0"\n'
+		s += '\t\t"' + self.st + '\\0"\n'
+		s += '\t\t"' + self.fini.c_strspec(modnam) + '\\0"\n'
+		for m in self.methods:
+			s += '\t\t"' + m.c_strspec(modnam) + '\\0"\n'
+		s += '\t\t"\\0",\n'
+		return s
+
+#######################################################################
+
+class arg(object):
+	def __init__(self, typ, nam = None, det = None):
+		self.nam = nam
+		self.typ = typ
+		self.det = det
+
+	def __repr__(self):
+		return "<ARG %s %s %s>" % (self.nam, self.typ, str(self.det))
+
+	def c_strspec(self):
+		if self.det == None:
+			return self.typ + "\\0"
+		else:
+			return self.det
+		return "??"
+
+#######################################################################
+
+f = open(specfile, "r")
+tl = list()
+lines = list()
+ln = 0
+for l in f:
+	ln += 1
+	lines.append(l)
+	if l == "":
+		continue
+	l = re.sub("[ \t]*#.*$", "", l)
+	l = re.sub("[ \t]*\n", "", l)
+	l = re.sub("([(){},])", r' \1 ', l)
+	if l == "":
+		continue
+	for j in l.split():
+		tl.append(token(ln, 0, j))
+f.close()
+
+#######################################################################
+#
+#
+def parse_enum2(tl):
+	t = tl.pop(0)
+	if t.str != "{":
+		raise Exception("expected \"{\"")
+	s = "ENUM\\0"
+	while True:
+		t = tl.pop(0)
+		if t.str == "}":
+			break
+		s += t.str + "\\0"
+		if tl[0].str == ",":
+			tl.pop(0)
+		elif tl[0].str != "}":
+			raise Exception("Expceted \"}\" or \",\"")
+	s += "\\0"
+	return arg("ENUM", det=s)
+
+#######################################################################
+#
+#
+
+def parse_func(tl, rt_type = None, obj=None):
+	al = list()
+	if rt_type == None:
+		t = tl.pop(0)
+		rt_type = t.str
+	if rt_type not in ctypes:
+		raise Exception(
+		    "Return type '%s' not a valid type" % rt_type)
+
+	t = tl.pop(0)
+	fname = t.str
+	if obj != None and fname[0] == "." and is_c_name(fname[1:]):
+		fname = obj + fname
+	elif not is_c_name(fname):
+		raise Exception("Function name '%s' is illegal" % fname)
+
+	t = tl.pop(0)
+	if t.str != "(":
+		raise Exception("Expected \"(\" got \"%s\"", t.str)
+
+	while True:
+		t = tl.pop(0)
+		if t.str == ")":
+			break
+		if t.str == "ENUM":
+			al.append(parse_enum2(tl))
+		elif t.str in ctypes:
+			al.append(arg(t.str))
+		else:
+			raise Exception("ARG? %s" % t.str)
+		if is_c_name(tl[0].str):
+			al[-1].nam = tl[0].str
+			t = tl.pop(0)
+		if tl[0].str == ",":
+			tl.pop(0)
+		elif tl[0].str != ")":
+			raise Exception("Expceted \")\" or \",\"")
+	if t.str != ")":
+		raise Exception("End Of Input looking for ')'")
+	f = func(fname, rt_type, al)
+	return f
+
+#######################################################################
+#
+#
+
+def parse_obj(tl):
+	o = obj(tl[0].str)
+	f = parse_func(tl, "VOID")
+	o.set_init(f)
+	t = tl.pop(0)
+	assert t.str == "{"
+	while True:
+		t = tl.pop(0)
+		if t.str == "}":
+			break
+		assert t.str == "Method"
+		f = parse_func(tl, obj=o.nam)
+		o.add_method(f)
+	return o
+
+#######################################################################
+# The first thing in the file must be the Module declaration
+#
+
+t = tl.pop(0)
+if t.str != "Module":
+	raise Exception("\"Module\" must be first in file")
+t = tl.pop(0)
+vmod = vmod(t.str)
+
+#######################################################################
+# Parse the rest of the file
+#
+
+while len(tl) > 0:
+	t = tl.pop(0)
+
+	if t.str == "Init":
+		t = tl.pop(0)
+		vmod.set_init(t.str)
+	elif t.str == "Function":
+		f = parse_func(tl)
+		vmod.add_func(f)
+	elif t.str == "Object":
+		o = parse_obj(tl)
+		vmod.add_obj(o)
+	else:
+		raise Exception("Expected \"Init\", \"Fini\" or \"Function\"")
+
+#######################################################################
+# Parsing done, now process
+#
+
+fc = open("vcc_if.c", "w")
+fh = open("vcc_if.h", "w")
+
+file_header(fc)
+file_header(fh)
+
+fh.write('struct vrt_ctx;\n')
+fh.write('struct VCL_conf;\n')
+fh.write('struct vmod_priv;\n')
+fh.write("\n");
+
+vmod.c_proto(fh)
+
+fc.write("""#include "config.h"
+
+#include "vrt.h"
+#include "vcc_if.h"
+#include "vmod_abi.h"
+
+
+""")
+
+vmod.c_typedefs(fc)
+vmod.c_vmod(fc)
+
+fc.close()
+fh.close()
diff --git a/lib/libvcl/Makefile.am b/lib/libvcl/Makefile.am
deleted file mode 100644
index 91bc0d3..0000000
--- a/lib/libvcl/Makefile.am
+++ /dev/null
@@ -1,44 +0,0 @@
-#
-
-AM_LDFLAGS  = $(AM_LT_LDFLAGS)
-
-AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_builddir)/include
-
-pkglib_LTLIBRARIES = libvcl.la
-
-libvcl_la_LDFLAGS = $(AM_LDFLAGS) -avoid-version
-
-libvcl_la_SOURCES = \
-	vcc_compile.h \
-	vcc_token_defs.h \
-	\
-	vcc_acl.c \
-	vcc_action.c \
-	vcc_backend.c \
-	vcc_backend_util.c \
-	vcc_compile.c \
-	vcc_expr.c \
-	vcc_parse.c \
-	vcc_fixed_token.c \
-	vcc_obj.c \
-	vcc_storage.c \
-	vcc_utils.c \
-	vcc_symb.c \
-	vcc_token.c \
-	vcc_var.c \
-	vcc_vmod.c \
-	vcc_xref.c
-
-EXTRA_DIST = \
-	generate.py
-
-dist_pkgdata_SCRIPTS = \
-	vmodtool.py
-
-vcc_obj.c vcc_fixed_token.c vcc_token_defs.h: \
-	$(srcdir)/generate.py $(top_srcdir)/include/vrt.h
-	@PYTHON@ $(srcdir)/generate.py $(srcdir) $(top_builddir)
-
-CLEANFILES = $(builddir)/vcc_token_defs.h \
-	$(builddir)/vcc_fixed_token.c \
-	$(builddir)/vcc_obj.c
diff --git a/lib/libvcl/flint.lnt b/lib/libvcl/flint.lnt
deleted file mode 100644
index 60b3850..0000000
--- a/lib/libvcl/flint.lnt
+++ /dev/null
@@ -1,46 +0,0 @@
--passes=3
-
-// Review all below this line
-
--printf_code( H, void *, unsigned)
--printf_code( ju, long long unsigned)
--printf_code( jx, long long unsigned)
-
-+libh ../../config.h
--header(../../config.h)
--sem(lbv_assert, r_no)
--sem(strchr, 1p, type(1), 2n == 0 ? (@p < 1p) : (@p < 1p || @p == 0 ))
--sem(vcc_new_source, custodial(1))
-
--emacro((???),va_arg)	// the va_arg() macro can yield 415, 416, 661, 662
-			// 796 and 797 (out-of-bounds errors).
-
-
--emacro(413, offsetof)	// likely null pointer
-
-// -ffc    // No automatic custody
-
--esym(534, vsb_printf)	// Ignoring return value of function
--esym(534, vsb_cat)	// Ignoring return value of function
--esym(534, vsb_bcat)	// Ignoring return value of function
--esym(534, vsb_vprintf)	// Ignoring return value of function
--esym(534, memset)	// Ignoring return value of function
--e788			// enum constant 'HND_Unclass' not used within defaulted switch
--e716			// while(1) ... 
--e786			// String concatenation within initializer
--e732			// Loss of sign (arg. no. 2) (int to unsigned int)
-
-
--e763	// Redundant declaration for symbol '...' previously declared
-
-
--e737	// Loss of sign in promotion from int to unsigned int
--e534	// Ignoring return value of function
--e506	// Constant value boolean
--e774	// Boolean within 'if' always evaluates to False
--e713	// Loss of precision (assignment) (unsigned long long to long long)
--e574	// Signed-unsigned mix with relational
--e539	// Did not expect positive indentation
--e734	// Loss of precision (assignment) (31 bits to 8 bits)
--e747	// Significant prototype coercion (arg. no. 2) long
--e712	// Loss of precision (assignment) (long long to
diff --git a/lib/libvcl/flint.sh b/lib/libvcl/flint.sh
deleted file mode 100755
index 3bb465a..0000000
--- a/lib/libvcl/flint.sh
+++ /dev/null
@@ -1,10 +0,0 @@
-#!/bin/sh
-
-flexelint \
-	-I/usr/include \
-	-I. \
-	-I../.. \
-	-I../../include \
-	-I../../contrib/libevent \
-	flint.lnt \
-	*.c
diff --git a/lib/libvcl/generate.py b/lib/libvcl/generate.py
deleted file mode 100755
index 012098a..0000000
--- a/lib/libvcl/generate.py
+++ /dev/null
@@ -1,952 +0,0 @@
-#!/usr/local/bin/python3.1
-#-
-# Copyright (c) 2006 Verdens Gang AS
-# Copyright (c) 2006-2013 Varnish Software AS
-# All rights reserved.
-#
-# Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-#    notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-#    notice, this list of conditions and the following disclaimer in the
-#    documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
-# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-# SUCH DAMAGE.
-#
-# Generate various .c and .h files for the VCL compiler and the interfaces
-# for it.
-
-#######################################################################
-# These are our tokens
-
-# We could drop all words such as "include", "if" etc, and use the
-# ID type instead, but declaring them tokens makes them reserved words
-# which hopefully makes for better error messages.
-# XXX: does it actually do that ?
-
-import sys
-
-srcroot = "../.."
-buildroot = "../.."
-if len(sys.argv) == 3:
-	srcroot = sys.argv[1]
-	buildroot = sys.argv[2]
-
-tokens = {
-	"T_INC":	"++",
-	"T_DEC":	"--",
-	"T_CAND":	"&&",
-	"T_COR":	"||",
-	"T_LEQ":	"<=",
-	"T_EQ":		"==",
-	"T_NEQ":	"!=",
-	"T_GEQ":	">=",
-	"T_SHR":	">>",
-	"T_SHL":	"<<",
-	"T_INCR":	"+=",
-	"T_DECR":	"-=",
-	"T_MUL":	"*=",
-	"T_DIV":	"/=",
-	"T_NOMATCH":	"!~",
-
-	# Single char tokens, for convenience on one line
-	None:		"{}()*+-/%><=;!&.|~,",
-
-	# These have handwritten recognizers
-	"ID":		None,
-	"CNUM":		None,
-	"CSTR":		None,
-	"EOI":		None,
-	"CSRC":		None,
-}
-
-#######################################################################
-# Our methods and actions
-
-returns =(
-	('recv',		"C", ('error', 'pass', 'pipe', 'hash', 'purge',)),
-	('pipe',		"C", ('error', 'pipe',)),
-	('pass',		"C", ('error', 'restart', 'fetch',)),
-	('hash',		"C", ('lookup',)),
-	('purge',		"C", ('error', 'fetch',)),
-	('miss',		"C", ('error', 'restart', 'pass', 'fetch',)),
-	('hit',			"C", ('error', 'restart', 'pass', 'fetch', 'deliver',)),
-	('backend_fetch',	"B", ('fetch', 'abandon')),
-	('backend_response',	"B", ('deliver', 'retry', 'abandon')),
-	('deliver',		"C", ('restart', 'deliver',)),
-	('error',		"C", ('restart', 'deliver',)),
-	('init',		"", ('ok',)),
-	('fini',		"", ('ok',)),
-)
-
-#######################################################################
-# Variables available in sessions
-#
-# 'all' means all methods
-# 'client' means all methods tagged "C"
-# 'backend' means all methods tagged "B"
-# 'both' means all methods tagged "B" or "C"
-
-sp_variables = [
-	('client.ip',
-		'IP',
-		( 'both',),
-		( ),
-	),
-	('client.identity',
-		'STRING',
-		( 'both',),
-		( 'both',),
-	),
-	('server.ip',
-		'IP',
-		( 'client',),
-		( ),
-	),
-	('server.hostname',
-		'STRING',
-		( 'client',),
-		( ),
-	),
-	('server.identity',
-		'STRING',
-		( 'client',),
-		( ),
-	),
-	('server.port',
-		'INT',
-		( 'client',),
-		( ),
-	),
-	('req.method',
-		'STRING',
-		( 'client',),
-		( 'client',),
-	),
-	('req.request',
-		'STRING',
-		( 'client',),
-		( 'client',),
-	),
-	('req.url',
-		'STRING',
-		( 'client',),
-		( 'client',),
-	),
-	('req.proto',
-		'STRING',
-		( 'client',),
-		( 'client',),
-	),
-	('req.http.',
-		'HEADER',
-		( 'client',),
-		( 'client',),
-	),
-	('req.restarts',
-		'INT',
-		( 'client',),
-		( ),
-	),
-	('req.esi_level',
-		'INT',
-		( 'client',),
-		( ),
-	),
-	('req.ttl',
-		'DURATION',
-		( 'client',),
-		( 'client',),
-	),
-	('req.grace',
-		'DURATION',
-		( 'client',),
-		( 'client',),
-	),
-	('req.keep',
-		'DURATION',
-		( 'client',),
-		( 'client',),
-	),
-	('req.xid',
-		'STRING',
-		( 'client',),
-		( ),
-	),
-	('req.esi',
-		'BOOL',
-		( 'recv', 'backend_response', 'deliver', 'error',),
-		( 'recv', 'backend_response', 'deliver', 'error',),
-	),
-	('req.can_gzip',
-		'BOOL',
-		( 'client',),
-		( ),
-	),
-	('req.backend',
-		'BACKEND',
-		( 'client',),
-		( 'client',),
-	),
-	('req.backend.healthy',
-		'BOOL',
-		( 'client',),
-		( ),
-	),
-	('req.hash_ignore_busy',
-		'BOOL',
-		( 'recv',),
-		( 'recv',),
-	),
-	('req.hash_always_miss',
-		'BOOL',
-		( 'recv',),
-		( 'recv',),
-	),
-	('bereq.retries',
-		'INT',
-		( 'backend',),
-		( ),
-	),
-	('bereq.backend',
-		'BACKEND',
-		( 'pipe', 'backend', ),
-		( 'pipe', 'backend', ),
-	),
-	('bereq.backend.healthy',
-		'BOOL',
-		( 'pipe', 'backend', ),
-		( ),
-	),
-	('bereq.method',
-		'STRING',
-		( 'pipe', 'backend', ),
-		( 'pipe', 'backend', ),
-	),
-	('bereq.request',
-		'STRING',
-		( 'pipe', 'backend', ),
-		( 'pipe', 'backend', ),
-	),
-	('bereq.url',
-		'STRING',
-		( 'pipe', 'backend', ),
-		( 'pipe', 'backend', ),
-	),
-	('bereq.proto',
-		'STRING',
-		( 'pipe', 'backend', ),
-		( 'pipe', 'backend', ),
-	),
-	('bereq.http.',
-		'HEADER',
-		( 'pipe', 'backend', ),
-		( 'pipe', 'backend', ),
-	),
-	('bereq.uncacheable',
-		'BOOL',
-		( 'backend', ),
-		( 'backend', ),
-	),
-	('bereq.connect_timeout',
-		'DURATION',
-		( 'pipe', 'backend', ),
-		( 'pipe', 'backend', ),
-	),
-	('bereq.first_byte_timeout',
-		'DURATION',
-		( 'pipe', 'backend', ),
-		( 'pipe', 'backend', ),
-	),
-	('bereq.between_bytes_timeout',
-		'DURATION',
-		( 'pipe', 'backend', ),
-		( 'pipe', 'backend', ),
-	),
-	('beresp.proto',
-		'STRING',
-		( 'backend_response',),
-		( 'backend_response',),
-	),
-	('beresp.status',
-		'INT',
-		( 'backend_response',),
-		( 'backend_response',),
-	),
-	('beresp.response',
-		'STRING',
-		( 'backend_response',),
-		( 'backend_response',),
-	),
-	('beresp.http.',
-		'HEADER',
-		( 'backend_response',),
-		( 'backend_response',),
-	),
-	('beresp.do_esi',
-		'BOOL',
-		( 'backend_response',),
-		( 'backend_response',),
-	),
-	('beresp.do_stream',
-		'BOOL',
-		( 'backend_response',),
-		( 'backend_response',),
-	),
-	('beresp.do_gzip',
-		'BOOL',
-		( 'backend_response',),
-		( 'backend_response',),
-	),
-	('beresp.do_gunzip',
-		'BOOL',
-		( 'backend_response',),
-		( 'backend_response',),
-	),
-	('beresp.uncacheable',
-		'BOOL',
-		( 'backend_response',),
-		( 'backend_response',),
-	),
-	('beresp.ttl',
-		'DURATION',
-		( 'backend_response',),
-		( 'backend_response',),
-	),
-	('beresp.grace',
-		'DURATION',
-		( 'backend_response',),
-		( 'backend_response',),
-	),
-	('beresp.keep',
-		'DURATION',
-		( 'backend_response',),
-		( 'backend_response',),
-	),
-	('beresp.backend.name',
-		'STRING',
-		( 'backend_response',),
-		( ),
-	),
-	('beresp.backend.ip',
-		'IP',
-		( 'backend_response',),
-		( ),
-	),
-	('beresp.backend.port',
-		'INT',
-		( 'backend_response',),
-		( ),
-	),
-	('beresp.storage',
-		'STRING',
-		( 'backend_response',),
-		( 'backend_response',),
-	),
-	('obj.proto',
-		'STRING',
-		( 'hit', 'error',),
-		( 'hit', 'error',),
-	),
-	('obj.status',
-		'INT',
-		( 'error',),
-		( 'error',),
-	),
-	('obj.response',
-		'STRING',
-		( 'error',),
-		( 'error',),
-	),
-	('obj.hits',
-		'INT',
-		( 'hit', 'deliver',),
-		( 'hit', 'deliver',),
-	),
-	('obj.http.',
-		'HEADER',
-		( 'hit', 'error',),
-		( 'error',),		# XXX ?
-	),
-	('obj.ttl',
-		'DURATION',
-		( 'hit', 'error',),
-		( 'hit', 'error',),
-	),
-	('obj.grace',
-		'DURATION',
-		( 'hit', 'error',),
-		( 'hit', 'error',),
-	),
-	('obj.keep',
-		'DURATION',
-		( 'hit', 'error',),
-		( 'hit', 'error',),
-	),
-	('obj.last_use',
-		'TIME',
-		( 'hit', 'deliver',),
-		( 'hit', 'deliver',),
-	),
-	('obj.uncacheable',
-		'BOOL',
-		( 'hit', 'deliver', 'error',),
-		( ),
-	),
-	('resp.proto',
-		'STRING',
-		( 'deliver',),
-		( 'deliver',),
-	),
-	('resp.status',
-		'INT',
-		( 'deliver',),
-		( 'deliver',),
-	),
-	('resp.response',
-		'STRING',
-		( 'deliver',),
-		( 'deliver',),
-	),
-	('resp.http.',
-		'HEADER',
-		( 'deliver',),
-		( 'deliver',),
-	),
-	('now',
-		'TIME',
-		( 'all',),
-		( ),
-	),
-]
-
-stv_variables = (
-	('free_space',	'BYTES',	"0."),
-	('used_space',	'BYTES',	"0."),
-	('happy',	'BOOL',		"0"),
-)
-
-#######################################################################
-# VCL to C type conversion
-
-vcltypes = {
-	'STRING_LIST':	"void*",
-}
-
-fi = open(srcroot + "/include/vrt.h")
-
-for i in fi:
-	j = i.split();
-	if len(j) < 3:
-		continue
-	if j[0] != "typedef":
-		continue
-	if j[-1][-1] != ";":
-		continue
-	if j[-1][:4] != "VCL_":
-		continue
-	d = " ".join(j[1:-1])
-	vcltypes[j[-1][4:-1]] = d
-fi.close()
-
-#######################################################################
-# Nothing is easily configurable below this line.
-#######################################################################
-
-import sys
-import copy
-
-#######################################################################
-# Emit a function to recognize tokens in a string
-
-def emit_vcl_fixed_token(fo, tokens):
-
-	recog = list()
-	emit = dict()
-	for i in tokens:
-		j = tokens[i]
-		if (j != None):
-			recog.append(j)
-			emit[j] = i
-
-	recog.sort()
-	rrecog = copy.copy(recog)
-	rrecog.sort(key = lambda x: -len(x))
-
-	fo.write("""
-#define M1()\tdo {*q = p + 1; return (p[0]); } while (0)
-#define M2(c,t)\tdo {if (p[1] == (c)) { *q = p + 2; return (t); }} while (0)
-
-unsigned
-vcl_fixed_token(const char *p, const char **q)
-{
-
-\tswitch (p[0]) {
-""")
-	last_initial = None
-	for i in recog:
-		if (i[0] == last_initial):
-			continue
-		last_initial = i[0]
-		fo.write("\tcase '%s':\n" % last_initial)
-		need_ret = True
-		for j in rrecog:
-			if (j[0] != last_initial):
-				continue
-			if len(j) == 2:
-				fo.write("\t\tM2('%s', %s);\n" %
-				    (j[1], emit[j]))
-			elif len(j) == 1:
-				fo.write("\t\tM1();\n")
-				need_ret = False
-			else:
-				fo.write("\t\tif (")
-				k = 1
-				l = len(j)
-				while (k < l):
-					fo.write("p[%d] == '%s'" % (k, j[k]))
-					fo.write(" &&")
-					if (k % 3) == 0:
-						fo.write("\n\t\t    ")
-					else:
-						fo.write(" ")
-					k += 1
-				fo.write("!isvar(p[%d])) {\n" % l)
-				fo.write("\t\t\t*q = p + %d;\n" % l)
-				fo.write("\t\t\treturn (%s);\n" % emit[j])
-				fo.write("\t\t}\n")
-		if need_ret:
-			fo.write("\t\treturn (0);\n")
-	fo.write("\tdefault:\n\t\treturn (0);\n\t}\n}\n")
-
-#######################################################################
-# Emit the vcl_tnames (token->string) conversion array
-
-def emit_vcl_tnames(fo, tokens):
-	fo.write("\nconst char * const vcl_tnames[256] = {\n")
-	l = list(tokens.keys())
-	l.sort()
-	for i in l:
-		j = tokens[i]
-		if j == None:
-			j = i
-		if i[0] == "'":
-			j = i
-		fo.write("\t[%s] = \"%s\",\n" % (i, j))
-	fo.write("};\n")
-
-#######################################################################
-# Read a C-source file and spit out code that outputs it with VSB_cat()
-
-def emit_file(fo, fn):
-	fi = open(fn)
-	fc = fi.read()
-	fi.close()
-
-	w = 66		# Width of lines, after white space prefix
-	maxlen = 10240	# Max length of string literal
-
-	x = 0
-	l = 0
-	fo.write("\n\t/* %s */\n\n" % fn)
-	for c in fc:
-		if l == 0:
-			fo.write("\tVSB_cat(sb, \"")
-			l += 12
-			x += 12
-		if x == 0:
-			fo.write("\t    \"")
-		d = c
-		if c == '\n':
-			d = "\\n"
-		elif c == '\t':
-			d = "\\t"
-		elif c == '"':
-			d = "\\\""
-		elif c == '\\':
-			d = "\\\\"
-
-		if c == '\n' and x > w - 20:
-			fo.write(d + "\"\n")
-			x = 0
-			continue
-		if c.isspace() and x > w - 10:
-			fo.write(d + "\"\n")
-			x = 0
-			continue
-
-		fo.write(d)
-		x += len(d)
-		l += len(d)
-		if l > maxlen:
-			fo.write("\");\n")
-			l = 0;
-			x = 0
-		if x > w - 3:
-			fo.write("\"\n")
-			x = 0
-	if x != 0:
-		fo.write("\"")
-	if l != 0:
-		fo.write("\t);\n")
-
-#######################################################################
-
-def polish_tokens(tokens):
-	# Expand single char tokens
-	st = tokens[None]
-	del tokens[None]
-
-	for i in st:
-		tokens["'" + i + "'"] = i
-#######################################################################
-
-def file_header(fo):
-	fo.write("""/*
- * NB:  This file is machine generated, DO NOT EDIT!
- *
- * Edit and run generate.py instead
- */
-""")
-
-#######################################################################
-
-polish_tokens(tokens)
-
-fo = open(buildroot + "/lib/libvcl/vcc_token_defs.h", "w")
-
-file_header(fo)
-
-j = 128
-l = list(tokens.keys())
-l.sort()
-for i in l:
-	if i[0] == "'":
-		continue
-	fo.write("#define\t%s %d\n" % (i, j))
-	j += 1
-	assert j < 256
-
-fo.close()
-
-#######################################################################
-
-rets = dict()
-vcls = list()
-vcls_client = list()
-vcls_backend = list()
-for i in returns:
-	vcls.append(i[0])
-	for j in i[1]:
-		if j == "B":
-			vcls_backend.append(i[0])
-		elif j == "C":
-			vcls_client.append(i[0])
-	for j in i[2]:
-		rets[j] = True
-
-#######################################################################
-
-fo = open(buildroot + "/include/tbl/vcl_returns.h", "w")
-
-file_header(fo)
-
-fo.write("\n/*lint -save -e525 -e539 */\n")
-
-fo.write("\n#ifdef VCL_RET_MAC\n")
-l = list(rets.keys())
-l.sort()
-for i in l:
-	fo.write("VCL_RET_MAC(%s, %s" % (i.lower(), i.upper()))
-	s=", "
-	for j in returns:
-		if i in j[2]:
-			fo.write("%sVCL_MET_%s" % (s, j[0].upper()))
-			s = " | "
-	fo.write(")\n")
-fo.write("#endif\n")
-
-fo.write("\n#ifdef VCL_MET_MAC\n")
-for i in returns:
-	fo.write("VCL_MET_MAC(%s,%s,\n" % (i[0].lower(), i[0].upper()))
-	p = " ("
-	for j in i[2]:
-		fo.write("    %s(1U << VCL_RET_%s)\n" % (p, j.upper()))
-		p = "| "
-	fo.write("))\n")
-fo.write("#endif\n")
-fo.write("\n/*lint -restore */\n")
-fo.close()
-
-#######################################################################
-
-fo = open(buildroot + "/include/vcl.h", "w")
-
-file_header(fo)
-
-fo.write("""
-struct vrt_ctx;
-struct req;
-struct busyobj;
-struct ws;
-struct cli;
-struct worker;
-
-typedef int vcl_init_f(struct cli *);
-typedef void vcl_fini_f(struct cli *);
-typedef int vcl_func_f(const struct vrt_ctx *ctx);
-""")
-
-
-fo.write("\n/* VCL Methods */\n")
-n = 0
-for i in returns:
-	fo.write("#define VCL_MET_%s\t\t(1U << %d)\n" % (i[0].upper(), n))
-	n += 1
-
-fo.write("\n#define VCL_MET_MAX\t\t%d\n" % n)
-fo.write("\n#define VCL_MET_MASK\t\t0x%x\n" % ((1 << n) - 1))
-
-
-fo.write("\n/* VCL Returns */\n")
-n = 0
-l = list(rets.keys())
-l.sort()
-for i in l:
-	fo.write("#define VCL_RET_%s\t\t%d\n" % (i.upper(), n))
-	n += 1
-
-fo.write("\n#define VCL_RET_MAX\t\t%d\n" % n)
-
-
-fo.write("""
-struct VCL_conf {
-	unsigned	magic;
-#define VCL_CONF_MAGIC	0x7406c509	/* from /dev/random */
-
-	struct director	**director;
-	unsigned	ndirector;
-	struct vrt_ref	*ref;
-	unsigned	nref;
-	unsigned	busy;
-	unsigned	discard;
-
-	unsigned	nsrc;
-	const char	**srcname;
-	const char	**srcbody;
-
-	vcl_init_f	*init_vcl;
-	vcl_fini_f	*fini_vcl;
-""")
-
-for i in returns:
-	fo.write("\tvcl_func_f\t*" + i[0] + "_func;\n")
-
-fo.write("""
-};
-""")
-
-fo.close()
-
-#######################################################################
-
-def restrict(fo, spec):
-	d = dict()
-	for j in spec:
-		if j == 'all':
-			for i in vcls:
-				d[i] = True
-		elif j == 'backend':
-			for i in vcls_backend:
-				d[i] = True
-		elif j == 'client':
-			for i in vcls_client:
-				d[i] = True
-		elif j == 'both':
-			for i in vcls_client:
-				d[i] = True
-			for i in vcls_backend:
-				d[i] = True
-		else:
-			assert j in vcls
-			d[j] = True
-	p = ""
-	n = 0
-	l = list(d.keys())
-	l.sort()
-	w = 0
-	fo.write("\t\t")
-	for j in l:
-		x = p + "VCL_MET_" + j.upper()
-		if w + len(x) > 60:
-			fo.write("\n\t\t")
-			w = 0
-		fo.write(x)
-		w += len(x)
-		p = " | "
-	if len(d) == 0:
-		fo.write("0")
-	fo.write(",\n")
-
-#######################################################################
-
-fh = open(buildroot + "/include/vrt_obj.h", "w")
-file_header(fh)
-
-fo = open(buildroot + "/lib/libvcl/vcc_obj.c", "w")
-file_header(fo)
-
-fo.write("""
-#include "config.h"
-
-#include <stdio.h>
-
-#include "vcc_compile.h"
-
-const struct var vcc_vars[] = {
-""")
-
-sp_variables.sort()
-for i in sp_variables:
-	typ = i[1]
-	cnam = i[0].replace(".", "_")
-	ctyp = vcltypes[typ]
-
-	fo.write("\t{ \"%s\", %s, %d,\n" % (i[0], typ, len(i[0])))
-
-	if len(i[2]) == 0:
-		fo.write('\t    NULL,\t/* No reads allowed */\n')
-	elif typ == "HEADER":
-		fo.write('\t    "HDR_')
-		fo.write(i[0].split(".")[0].upper())
-		fo.write('",\n')
-	else:
-		fo.write('\t    "VRT_r_%s(ctx)",\n' % cnam)
-		fh.write(ctyp + " VRT_r_%s(const struct vrt_ctx *);\n" % cnam )
-	restrict(fo, i[2])
-
-	if len(i[3]) == 0:
-		fo.write('\t    NULL,\t/* No writes allowed */\n')
-	elif typ == "HEADER":
-		fo.write('\t    "HDR_')
-		fo.write(i[0].split(".")[0].upper())
-		fo.write('",\n')
-	else:
-		fo.write('\t    "VRT_l_%s(ctx, ",\n' % cnam)
-		fh.write("void VRT_l_%s(const struct vrt_ctx *, " % cnam)
-		if typ != "STRING":
-			fh.write(ctyp + ");\n")
-		else:
-			fh.write(ctyp + ", ...);\n")
-	restrict(fo, i[3])
-
-	fo.write("\t},\n")
-
-fo.write("\t{ NULL }\n};\n")
-
-for i in stv_variables:
-	fh.write(vcltypes[i[1]] + " VRT_Stv_" + i[0] + "(const char *);\n")
-
-fo.close()
-fh.close()
-
-#######################################################################
-
-fo = open(buildroot + "/lib/libvcl/vcc_fixed_token.c", "w")
-
-file_header(fo)
-fo.write("""
-
-#include "config.h"
-
-#include <ctype.h>
-#include <stdio.h>
-
-#include "vcc_compile.h"
-""")
-
-emit_vcl_fixed_token(fo, tokens)
-emit_vcl_tnames(fo, tokens)
-
-fo.write("""
-void
-vcl_output_lang_h(struct vsb *sb)
-{
-""")
-
-emit_file(fo, buildroot + "/include/vcl.h")
-emit_file(fo, srcroot + "/include/vrt.h")
-emit_file(fo, buildroot + "/include/vrt_obj.h")
-
-fo.write("""
-}
-""")
-
-fo.close()
-
-#######################################################################
-ft = open(buildroot + "/include/tbl/vcc_types.h", "w")
-file_header(ft)
-
-ft.write("/*lint -save -e525 -e539 */\n")
-
-i = list(vcltypes.keys())
-i.sort()
-for j in i:
-	ft.write("VCC_TYPE(" + j + ")\n")
-ft.write("/*lint -restore */\n")
-ft.close()
-
-#######################################################################
-
-fo = open(buildroot + "/include/tbl/vrt_stv_var.h", "w")
-
-file_header(fo)
-
-fo.write("""
-#ifndef VRTSTVTYPE
-#define VRTSTVTYPE(ct)
-#define VRTSTVTYPEX
-#endif
-#ifndef VRTSTVVAR
-#define VRTSTVVAR(nm, vtype, ctype, dval)
-#define VRTSTVVARX
-#endif
-""")
-
-x=dict()
-for i in stv_variables:
-	ct = vcltypes[i[1]]
-	if not ct in x:
-		fo.write("VRTSTVTYPE(" + ct + ")\n")
-		x[ct] = 1
-	fo.write("VRTSTVVAR(" + i[0] + ",\t" + i[1] + ",\t")
-	fo.write(ct + ",\t" + i[2] + ")")
-	fo.write("\n")
-
-fo.write("""
-#ifdef VRTSTVTYPEX
-#undef VRTSTVTYPEX
-#undef VRTSTVTYPE
-#endif
-#ifdef VRTSTVVARX
-#undef VRTSTVVARX
-#undef VRTSTVVAR
-#endif
-""")
-
-fo.close
diff --git a/lib/libvcl/vcc_acl.c b/lib/libvcl/vcc_acl.c
deleted file mode 100644
index fa8a7d7..0000000
--- a/lib/libvcl/vcc_acl.c
+++ /dev/null
@@ -1,502 +0,0 @@
-/*-
- * Copyright (c) 2006 Verdens Gang AS
- * Copyright (c) 2006-2010 Varnish Software AS
- * All rights reserved.
- *
- * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#include <sys/types.h>
-#include <sys/socket.h>
-
-#include <netinet/in.h>
-
-#include <netdb.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "vcc_compile.h"
-
-#include "vrt.h"
-
-struct acl_e {
-	VTAILQ_ENTRY(acl_e)	list;
-	unsigned char		data[VRT_ACL_MAXADDR + 1];
-	unsigned		mask;
-	unsigned		not;
-	unsigned		para;
-	struct token		*t_addr;
-	struct token		*t_mask;
-};
-
-/* Compare two acl rules for ordering */
-
-#define CMP(a, b)							\
-	do {								\
-		if ((a) < (b))						\
-			return (-1);					\
-		else if ((b) < (a))					\
-			return (1);					\
-	} while (0)
-
-static int
-vcl_acl_cmp(struct acl_e *ae1, struct acl_e *ae2)
-{
-	unsigned char *p1, *p2;
-	unsigned m;
-
-	p1 = ae1->data;
-	p2 = ae2->data;
-	m = ae1->mask;
-	if (ae2->mask < m)
-		m = ae2->mask;
-	for (; m >= 8; m -= 8) {
-		CMP(*p1, *p2);
-		p1++;
-		p2++;
-	}
-	if (m) {
-		m = 0xff00 >> m;
-		m &= 0xff;
-		CMP(*p1 & m, *p2 & m);
-	}
-	/* Long mask is less than short mask */
-	CMP(ae2->mask, ae1->mask);
-
-	return (0);
-}
-
-
-static void
-vcc_acl_add_entry(struct vcc *tl, const struct acl_e *ae, int l,
-    const unsigned char *u, int fam)
-{
-	struct acl_e *ae2, *aen;
-	int i;
-
-	if (fam == PF_INET && ae->mask > 32) {
-		VSB_printf(tl->sb,
-		    "Too wide mask (%u) for IPv4 address\n", ae->mask);
-		if (ae->t_mask != NULL)
-			vcc_ErrWhere(tl, ae->t_mask);
-		else
-			vcc_ErrWhere(tl, ae->t_addr);
-		return;
-	}
-	if (fam == PF_INET6 && ae->mask > 128) {
-		VSB_printf(tl->sb,
-		    "Too wide mask (%u) for IPv6 address\n", ae->mask);
-		vcc_ErrWhere(tl, ae->t_mask);
-		return;
-	}
-
-	/* Make a copy from the template */
-	aen = TlAlloc(tl, sizeof *ae2);
-	AN(aen);
-	*aen = *ae;
-
-	/* We treat family as part of address, it saves code */
-	assert(fam <= 0xff);
-	aen->data[0] = fam & 0xff;
-	aen->mask += 8;
-
-	memcpy(aen->data + 1, u, l);
-
-	VTAILQ_FOREACH(ae2, &tl->acl, list) {
-		i = vcl_acl_cmp(aen, ae2);
-		if (i == 0) {
-			/*
-			 * If the two rules agree, silently ignore it
-			 * XXX: is that counter intuitive ?
-			 */
-			if (aen->not == ae2->not)
-				return;
-			VSB_printf(tl->sb, "Conflicting ACL entries:\n");
-			vcc_ErrWhere(tl, ae2->t_addr);
-			VSB_printf(tl->sb, "vs:\n");
-			vcc_ErrWhere(tl, aen->t_addr);
-			return;
-		}
-		/*
-		 * We could eliminate pointless rules here, for instance in:
-		 *	"10.1.0.1";
-		 *	"10.1";
-		 * The first rule is clearly pointless, as the second one
-		 * covers it.
-		 *
-		 * We do not do this however, because the shmlog may
-		 * be used to gather statistics.
-		 */
-		if (i < 0) {
-			VTAILQ_INSERT_BEFORE(ae2, aen, list);
-			return;
-		}
-	}
-	VTAILQ_INSERT_TAIL(&tl->acl, aen, list);
-}
-
-static void
-vcc_acl_try_getaddrinfo(struct vcc *tl, struct acl_e *ae)
-{
-	struct addrinfo *res0, *res, hint;
-	struct sockaddr_in *sin4;
-	struct sockaddr_in6 *sin6;
-	unsigned char *u, i4, i6;
-	int error;
-
-	memset(&hint, 0, sizeof hint);
-	hint.ai_family = PF_UNSPEC;
-	hint.ai_socktype = SOCK_STREAM;
-	error = getaddrinfo(ae->t_addr->dec, "0", &hint, &res0);
-	if (error) {
-		if (ae->para) {
-			VSB_printf(tl->sb,
-			    "Warning: %s ignored\n  -- %s\n",
-			    ae->t_addr->dec, gai_strerror(error));
-			Fh(tl, 1, "/* Ignored ACL entry: %s%s",
-			    ae->para ? "\"(\" " : "", ae->not ? "\"!\" " : "");
-			EncToken(tl->fh, ae->t_addr);
-			if (ae->t_mask)
-				Fh(tl, 0, "/%u", ae->mask);
-			Fh(tl, 0, "%s\n", ae->para ? " \")\"" : "");
-			Fh(tl, 1, " * getaddrinfo:  %s */\n",
-			     gai_strerror(error));
-		} else {
-			VSB_printf(tl->sb,
-			    "DNS lookup(%s): %s\n",
-			    ae->t_addr->dec, gai_strerror(error));
-			vcc_ErrWhere(tl, ae->t_addr);
-		}
-		return;
-	}
-
-	i4 = i6 = 0;
-	for(res = res0; res != NULL; res = res->ai_next) {
-		switch(res->ai_family) {
-		case PF_INET:
-			assert(PF_INET < 256);
-			sin4 = (void*)res->ai_addr;
-			assert(sizeof(sin4->sin_addr) == 4);
-			u = (void*)&sin4->sin_addr;
-			if (ae->t_mask == NULL)
-				ae->mask = 32;
-			i4++;
-			vcc_acl_add_entry(tl, ae, 4, u, res->ai_family);
-			break;
-		case PF_INET6:
-			assert(PF_INET6 < 256);
-			sin6 = (void*)res->ai_addr;
-			assert(sizeof(sin6->sin6_addr) == 16);
-			u = (void*)&sin6->sin6_addr;
-			if (ae->t_mask == NULL)
-				ae->mask = 128;
-			i6++;
-			vcc_acl_add_entry(tl, ae, 16, u, res->ai_family);
-			break;
-		default:
-			VSB_printf(tl->sb,
-			    "Ignoring unknown protocol family (%d) for %.*s\n",
-				res->ai_family, PF(ae->t_addr));
-			continue;
-		}
-		ERRCHK(tl);
-	}
-	freeaddrinfo(res0);
-
-	if (ae->t_mask != NULL && i4 > 0 && i6 > 0) {
-		VSB_printf(tl->sb,
-		    "Mask (%u) specified, but string resolves to"
-		    " both IPv4 and IPv6 addresses.\n", ae->mask);
-		vcc_ErrWhere(tl, ae->t_mask);
-		return;
-	}
-}
-
-/*--------------------------------------------------------------------
- * Ancient stupidity on the part of X/Open and other standards orgs
- * dictate that "192.168" be translated to 192.0.0.168.  Ever since
- * CIDR happened, "192.168/16" notation has been used, but appearantly
- * no API supports parsing this, so roll our own.
- */
-
-static int
-vcc_acl_try_netnotation(struct vcc *tl, struct acl_e *ae)
-{
-	unsigned char b[4];
-	int i, j, k;
-	unsigned u;
-	const char *p;
-
-	memset(b, 0, sizeof b);
-	p = ae->t_addr->dec;
-	for (i = 0; i < 4; i++) {
-		j = sscanf(p, "%u%n", &u, &k);
-		if (j != 1)
-			return (0);
-		if (u & ~0xff)
-			return (0);
-		b[i] = (unsigned char)u;
-		if (p[k] == '\0')
-			break;
-		if (p[k] != '.')
-			return (0);
-		p += k + 1;
-	}
-	if (ae->t_mask == NULL)
-		ae->mask = 8 + 8 * i;
-	vcc_acl_add_entry(tl, ae, 4, b, AF_INET);
-	return (1);
-}
-
-static void
-vcc_acl_entry(struct vcc *tl)
-{
-	struct acl_e *ae;
-
-	ae = TlAlloc(tl, sizeof *ae);
-	AN(ae);
-
-	if (tl->t->tok == '!') {
-		ae->not = 1;
-		vcc_NextToken(tl);
-	}
-
-	if (tl->t->tok == '(') {
-		ae->para = 1;
-		vcc_NextToken(tl);
-	}
-
-	if (!ae->not && tl->t->tok == '!') {
-		ae->not = 1;
-		vcc_NextToken(tl);
-	}
-
-	ExpectErr(tl, CSTR);
-	ae->t_addr = tl->t;
-	vcc_NextToken(tl);
-
-	if (tl->t->tok == '/') {
-		vcc_NextToken(tl);
-		ae->t_mask = tl->t;
-		ExpectErr(tl, CNUM);
-		ae->mask = vcc_UintVal(tl);
-	}
-
-	if (ae->para)
-		SkipToken(tl, ')');
-
-	if (!vcc_acl_try_netnotation(tl, ae)) {
-		ERRCHK(tl);
-		vcc_acl_try_getaddrinfo(tl, ae);
-	}
-	ERRCHK(tl);
-}
-
-/*********************************************************************
- * Emit a function to match the ACL we have collected
- */
-
-/*
- * XXX: this is semi-silly.  We try really hard to not depend in the
- * XXX: systems include files while compiling VCL, but we need to know
- * XXX: the size of the sa_familiy member.
- * XXX: FlexeLint complains about these antics, so isolate it in a
- * XXX: separate function.
- */
-
-/*lint -save -e506 -e774 -e550 */
-static void
-c_is_a_silly_language(const struct vcc *tl)
-{
-	struct sockaddr sa;
-
-	assert(sizeof (unsigned char) == 1);
-	assert(sizeof (unsigned short) == 2);
-	assert(sizeof (unsigned int) == 4);
-	if (sizeof sa.sa_family == 1)
-		Fh(tl, 0, "\tunsigned char fam;\n");
-	else if (sizeof sa.sa_family == 2)
-		Fh(tl, 0, "\tunsigned short fam;\n");
-	else if (sizeof sa.sa_family == 4)
-		Fh(tl, 0, "\tunsigned int fam;\n");
-	else
-		assert(0 == __LINE__);
-}
-/*lint -restore */
-
-static void
-vcc_acl_emit(const struct vcc *tl, const char *acln, int anon)
-{
-	struct acl_e *ae;
-	int depth, l, m, i;
-	unsigned at[VRT_ACL_MAXADDR + 1];
-	const char *oc;
-
-	Fh(tl, 0, "\nstatic int\n");
-	Fh(tl, 0, "match_acl_%s_%s(const struct vrt_ctx *ctx, const void *p)\n",
-	    anon ? "anon" : "named", acln);
-	Fh(tl, 0, "{\n");
-	Fh(tl, 0, "\tconst unsigned char *a;\n");
-	c_is_a_silly_language(tl);
-
-	Fh(tl, 0, "\n");
-	Fh(tl, 0, "\ta = p;\n");
-	Fh(tl, 0, "\tVRT_memmove(&fam, a + %zd, sizeof fam);\n",
-	    offsetof(struct sockaddr, sa_family));
-	Fh(tl, 0, "\tif (fam == %d)\n", PF_INET);
-	Fh(tl, 0, "\t\ta += %zd;\n", offsetof(struct sockaddr_in, sin_addr));
-	Fh(tl, 0, "\telse if (fam == %d)\n", PF_INET6);
-	Fh(tl, 0, "\t\ta += %zd;\n", offsetof(struct sockaddr_in6, sin6_addr));
-	Fh(tl, 0, "\telse {\n");
-	Fh(tl, 0, "\t\tVRT_acl_log(ctx, \"NO_FAM %s\");\n", acln);
-	Fh(tl, 0, "\t\treturn(0);\n");
-	Fh(tl, 0, "\t}\n\n");
-	depth = -1;
-	oc = 0;
-	at[0] = 256;
-	VTAILQ_FOREACH(ae, &tl->acl, list) {
-
-		/* Find how much common prefix we have */
-		for (l = 0; l <= depth && l * 8 < ae->mask - 7; l++) {
-			assert(l >= 0);
-			if (ae->data[l] != at[l])
-				break;
-		}
-
-		/* Back down, if necessary */
-		oc = "";
-		while (l <= depth) {
-			Fh(tl, 0, "\t%*s}\n", -depth, "");
-			depth--;
-		}
-
-		m = ae->mask;
-		m -= l * 8;
-		assert(m >= 0);
-
-		/* Do whole byte compares */
-		for (i = l; m >= 8; m -= 8, i++) {
-			if (i == 0)
-				Fh(tl, 0, "\t%*s%sif (fam == %d) {\n",
-				    -i, "", oc, ae->data[i]);
-			else
-				Fh(tl, 0, "\t%*s%sif (a[%d] == %d) {\n",
-				    -i, "", oc, i - 1, ae->data[i]);
-			at[i] = ae->data[i];
-			depth = i;
-			oc = "";
-		}
-
-		if (m > 0) {
-			/* Do fractional byte compares */
-			Fh(tl, 0, "\t%*s%sif ((a[%d] & 0x%x) == %d) {\n",
-			    -i, "", oc, i - 1, (0xff00 >> m) & 0xff,
-			    ae->data[i] & ((0xff00 >> m) & 0xff));
-			at[i] = 256;
-			depth = i;
-			oc = "";
-		}
-
-		i = (ae->mask + 7) / 8;
-
-		if (!anon) {
-			Fh(tl, 0, "\t%*sVRT_acl_log(ctx, \"%sMATCH %s \" ",
-			    -i, "", ae->not ? "NEG_" : "", acln);
-			EncToken(tl->fh, ae->t_addr);
-			if (ae->t_mask != NULL)
-				Fh(tl, 0, " \"/%.*s\" ", PF(ae->t_mask));
-			Fh(tl, 0, ");\n");
-		}
-
-		Fh(tl, 0, "\t%*sreturn (%d);\n", -i, "", ae->not ? 0 : 1);
-	}
-
-	/* Unwind */
-	for (; 0 <= depth; depth--)
-		Fh(tl, 0, "\t%*.*s}\n", depth, depth, "");
-
-	/* Deny by default */
-	if (!anon)
-		Fh(tl, 0, "\tVRT_acl_log(ctx, \"NO_MATCH %s\");\n", acln);
-	Fh(tl, 0, "\treturn (0);\n}\n");
-}
-
-void
-vcc_Acl_Hack(struct vcc *tl, char *b)
-{
-	char acln[32];
-	unsigned tcond;
-
-	VTAILQ_INIT(&tl->acl);
-	tcond = tl->t->tok;
-	vcc_NextToken(tl);
-	bprintf(acln, "%u", tl->unique++);
-	vcc_acl_entry(tl);
-	vcc_acl_emit(tl, acln, 1);
-	sprintf(b, "%smatch_acl_anon_%s(ctx, \v1)",
-	    (tcond == T_NEQ ? "!" : ""), acln);
-}
-
-void
-vcc_Acl(struct vcc *tl)
-{
-	struct token *an;
-	int i;
-	char acln[1024];
-
-	vcc_NextToken(tl);
-	VTAILQ_INIT(&tl->acl);
-
-	ExpectErr(tl, ID);
-	if (!vcc_isCid(tl->t)) {
-		VSB_printf(tl->sb,
-		    "Names of VCL acl's cannot contain '-'\n");
-		vcc_ErrWhere(tl, tl->t);
-		return;
-	}
-	an = tl->t;
-	vcc_NextToken(tl);
-
-	i = vcc_AddDef(tl, an, SYM_ACL);
-	if (i > 1) {
-		VSB_printf(tl->sb, "ACL %.*s redefined\n", PF(an));
-		vcc_ErrWhere(tl, an);
-		return;
-	}
-	bprintf(acln, "%.*s", PF(an));
-
-	SkipToken(tl, '{');
-
-	while (tl->t->tok != '}') {
-		vcc_acl_entry(tl);
-		ERRCHK(tl);
-		SkipToken(tl, ';');
-	}
-	SkipToken(tl, '}');
-
-	vcc_acl_emit(tl, acln, 0);
-}
diff --git a/lib/libvcl/vcc_action.c b/lib/libvcl/vcc_action.c
deleted file mode 100644
index 4e441d2..0000000
--- a/lib/libvcl/vcc_action.c
+++ /dev/null
@@ -1,445 +0,0 @@
-/*-
- * Copyright (c) 2006 Verdens Gang AS
- * Copyright (c) 2006-2013 Varnish Software AS
- * All rights reserved.
- *
- * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * This file parses the real action of the VCL code, the procedure
- * statements which do the actual work.
- */
-
-#include "config.h"
-
-#include <string.h>
-
-#include "vcc_compile.h"
-
-/*--------------------------------------------------------------------*/
-
-static void
-parse_call(struct vcc *tl)
-{
-
-	vcc_NextToken(tl);
-	ExpectErr(tl, ID);
-	vcc_AddCall(tl, tl->t);
-	vcc_AddRef(tl, tl->t, SYM_SUB);
-	Fb(tl, 1, "if (VGC_function_%.*s(ctx))\n", PF(tl->t));
-	Fb(tl, 1, "\treturn (1);\n");
-	vcc_NextToken(tl);
-	return;
-}
-
-/*--------------------------------------------------------------------*/
-
-static void
-parse_error(struct vcc *tl)
-{
-
-	VSB_printf(tl->sb,
-	    "Syntax has changed, use:\n"
-	    "\treturn(error(999));\n"
-	    "or\n"
-	    "\treturn(error(999, \"Response text\"));\n");
-	vcc_ErrWhere(tl, tl->t);
-	return;
-}
-
-/*--------------------------------------------------------------------*/
-
-static const struct arith {
-	enum var_type		type;
-	unsigned		oper;
-	enum var_type		want;
-} arith[] = {
-	{ INT,		T_INCR,		INT },
-	{ INT,		T_DECR,		INT },
-	{ INT,		T_MUL,		INT },
-	{ INT,		T_DIV,		INT },
-	{ INT,		'=',		INT },
-	{ INT,		0,		INT },
-	{ TIME,		T_INCR,		DURATION },
-	{ TIME,		T_DECR,		DURATION },
-	{ TIME,		T_MUL,		REAL },
-	{ TIME,		T_DIV,		REAL },
-	{ TIME,		'=',		TIME },
-	{ TIME,		0,		TIME },
-	{ DURATION,	T_INCR,		DURATION },
-	{ DURATION,	T_DECR,		DURATION },
-	{ DURATION,	T_MUL,		REAL },
-	{ DURATION,	T_DIV,		REAL },
-	{ DURATION,	'=',		DURATION },
-	{ DURATION,	0,		DURATION },
-	{ VOID,		'=',		VOID }
-};
-
-static void
-parse_set(struct vcc *tl)
-{
-	const struct var *vp;
-	const struct arith *ap;
-	enum var_type fmt;
-
-	vcc_NextToken(tl);
-	ExpectErr(tl, ID);
-	vp = vcc_FindVar(tl, tl->t, 1, "cannot be set");
-	ERRCHK(tl);
-	assert(vp != NULL);
-	Fb(tl, 1, "%s\n", vp->lname);
-	tl->indent += INDENT;
-	vcc_NextToken(tl);
-	fmt = vp->fmt;
-	for (ap = arith; ap->type != VOID; ap++) {
-		if (ap->type != fmt)
-			continue;
-		if (ap->oper != tl->t->tok)
-			continue;
-		if (ap->oper != '=')
-			Fb(tl, 1, "%s %c ", vp->rname, *tl->t->b);
-		vcc_NextToken(tl);
-		fmt = ap->want;
-		break;
-	}
-	if (ap->type == VOID)
-		SkipToken(tl, ap->oper);
-	if (fmt == HEADER) {
-		vcc_Expr(tl, STRING_LIST);
-	} else if (fmt == STRING) {
-		vcc_Expr(tl, STRING_LIST);
-	} else {
-		vcc_Expr(tl, fmt);
-	}
-	tl->indent -= INDENT;
-	Fb(tl, 1, ");\n");
-}
-
-/*--------------------------------------------------------------------*/
-
-static void
-parse_unset(struct vcc *tl)
-{
-	const struct var *vp;
-
-	/* XXX: Wrong, should use VCC_Expr(HEADER) */
-	vcc_NextToken(tl);
-	ExpectErr(tl, ID);
-	vp = vcc_FindVar(tl, tl->t, 1, "cannot be unset");
-	ERRCHK(tl);
-	assert(vp != NULL);
-	if (vp->fmt != HEADER) {
-		VSB_printf(tl->sb,
-		    "Only http header variables can be unset.\n");
-		vcc_ErrWhere(tl, tl->t);
-		return;
-	}
-	ERRCHK(tl);
-	Fb(tl, 1, "%svrt_magic_string_unset);\n", vp->lname);
-	vcc_NextToken(tl);
-}
-
-/*--------------------------------------------------------------------*/
-
-static void
-parse_new(struct vcc *tl)
-{
-	struct symbol *sy1, *sy2, *sy3;
-	const char *p, *s_obj, *s_init, *s_struct, *s_fini;
-	char buf1[128];
-	char buf2[128];
-
-	vcc_NextToken(tl);
-	ExpectErr(tl, ID);
-	if (!vcc_isCid(tl->t)) {
-		VSB_printf(tl->sb,
-		    "Names of VCL objects cannot contain '-'\n");
-		vcc_ErrWhere(tl, tl->t);
-		return;
-	}
-	sy1 = VCC_FindSymbol(tl, tl->t, SYM_NONE);
-	XXXAZ(sy1);
-
-	sy1 = VCC_AddSymbolTok(tl, tl->t, SYM_NONE);	// XXX: NONE ?
-	XXXAN(sy1);
-	vcc_NextToken(tl);
-
-	ExpectErr(tl, '=');
-	vcc_NextToken(tl);
-
-	ExpectErr(tl, ID);
-	sy2 = VCC_FindSymbol(tl, tl->t, SYM_OBJECT);
-	XXXAN(sy2);
-
-	/*lint -save -e448 */
-	/* Split the first three args */
-	p = sy2->args;
-	s_obj = p;
-	p += strlen(p) + 1;
-	s_init = p;
-	while (p[0] != '\0' || p[1] != '\0')
-		p++;
-	p += 2;
-	s_struct = p;
-	p += strlen(p) + 1;
-	s_fini = p + strlen(p) + 1;
-	while (p[0] != '\0' || p[1] != '\0')
-		p++;
-	p += 2;
-
-	Fh(tl, 0, "static %s *%s;\n\n", s_struct, sy1->name);
-
-	vcc_NextToken(tl);
-
-	bprintf(buf1, ", &%s, \"%s\"", sy1->name, sy1->name);
-	vcc_Eval_Func(tl, s_init, buf1, "ASDF", s_init + strlen(s_init) + 1);
-	Fd(tl, 0, "\t%s(&%s);\n", s_fini, sy1->name);
-	ExpectErr(tl, ';');
-
-	bprintf(buf1, ", %s", sy1->name);
-	/* Split the methods from the args */
-	while (*p != '\0') {
-		p += strlen(s_obj);
-		bprintf(buf2, "%s%s", sy1->name, p);
-		sy3 = VCC_AddSymbolStr(tl, buf2, SYM_FUNC);
-		AN(sy3);
-		sy3->eval = vcc_Eval_SymFunc;
-		p += strlen(p) + 1;
-		sy3->cfunc = p;
-		p += strlen(p) + 1;
-
-		/* Functions which return VOID are procedures */
-		if (!memcmp(p, "VOID\0", 5))
-			sy3->kind = SYM_PROC;
-
-		sy3->args = p;
-		sy3->extra = TlDup(tl, buf1);
-		while (p[0] != '\0' || p[1] != '\0') {
-			if (!memcmp(p, "ENUM\0", 5)) {
-				/* XXX: Special case for ENUM that has
-				   it's own \0\0 end marker. Not exactly
-				   elegant, we should consider
-				   alternatives here. Maybe runlength
-				   encode the entire block? */
-				p += strlen(p) + 1;
-				while (p[0] != '\0' || p[1] != '\0')
-					p++;
-			}
-			p++;
-		}
-		p += 2;
-	}
-	/*lint -restore */
-}
-
-/*--------------------------------------------------------------------*/
-
-static void
-parse_ban(struct vcc *tl)
-{
-
-	vcc_NextToken(tl);
-
-	ExpectErr(tl, '(');
-	vcc_NextToken(tl);
-
-	Fb(tl, 1, "VRT_ban_string(\n");
-	tl->indent += INDENT;
-	vcc_Expr(tl, STRING);
-	tl->indent -= INDENT;
-	ERRCHK(tl);
-	Fb(tl, 1, ");\n");
-
-	ExpectErr(tl, ')');
-	vcc_NextToken(tl);
-}
-
-/*--------------------------------------------------------------------*/
-
-static void
-parse_hash_data(struct vcc *tl)
-{
-	vcc_NextToken(tl);
-	SkipToken(tl, '(');
-
-	Fb(tl, 1, "VRT_hashdata(ctx, ");
-	vcc_Expr(tl, STRING_LIST);
-	ERRCHK(tl);
-	Fb(tl, 0, ");\n");
-	SkipToken(tl, ')');
-}
-
-/*--------------------------------------------------------------------*/
-
-static void
-parse_return(struct vcc *tl)
-{
-	int retval = 0;
-
-	vcc_NextToken(tl);
-	ExpectErr(tl, '(');
-	vcc_NextToken(tl);
-	ExpectErr(tl, ID);
-
-	/* 'error' gets special handling, to allow optional status/response */
-	if (vcc_IdIs(tl->t, "error")) {
-		vcc_NextToken(tl);
-		if (tl->t->tok == ')') {
-			VSB_printf(tl->sb,
-			    "Syntax has changed, use:\n"
-			    "\treturn(error(999));\n"
-			    "or\n"
-			    "\treturn(error(999, \"Response text\"));\n");
-			vcc_ErrWhere(tl, tl->t);
-			return;
-		}
-		ExpectErr(tl, '(');
-		vcc_NextToken(tl);
-		Fb(tl, 1, "VRT_error(ctx,\n");
-		tl->indent += INDENT;
-		vcc_Expr(tl, INT);
-		ERRCHK(tl);
-		Fb(tl, 1, ",\n");
-		if (tl->t->tok == ',') {
-			vcc_NextToken(tl);
-			vcc_Expr(tl, STRING);
-			ERRCHK(tl);
-		} else {
-			Fb(tl, 1, "(const char*)0\n");
-		}
-		tl->indent -= INDENT;
-		ExpectErr(tl, ')');
-		vcc_NextToken(tl);
-		Fb(tl, 1, ");\n");
-		Fb(tl, 1, "VRT_handling(ctx, VCL_RET_ERROR);\n");
-		Fb(tl, 1, "return (1);\n");
-		vcc_ProcAction(tl->curproc, VCL_RET_ERROR, tl->t);
-		ExpectErr(tl, ')');
-		vcc_NextToken(tl);
-		return;
-	}
-
-#define VCL_RET_MAC(l, U, B)						\
-	do {								\
-		if (vcc_IdIs(tl->t, #l)) {				\
-			Fb(tl, 1, "VRT_handling(ctx, VCL_RET_" #U ");\n"); \
-			Fb(tl, 1, "return (1);\n");			\
-			vcc_ProcAction(tl->curproc, VCL_RET_##U, tl->t);\
-			retval = 1;					\
-		}							\
-	} while (0);
-#include "tbl/vcl_returns.h"
-#undef VCL_RET_MAC
-	if (!retval) {
-		VSB_printf(tl->sb, "Expected return action name.\n");
-		vcc_ErrWhere(tl, tl->t);
-		ERRCHK(tl);
-	}
-	vcc_NextToken(tl);
-	ExpectErr(tl, ')');
-	vcc_NextToken(tl);
-}
-
-/*--------------------------------------------------------------------*/
-
-static void
-parse_rollback(struct vcc *tl)
-{
-
-	vcc_NextToken(tl);
-	Fb(tl, 1, "VRT_Rollback(ctx);\n");
-}
-
-/*--------------------------------------------------------------------*/
-
-static void
-parse_purge(struct vcc *tl)
-{
-
-	vcc_NextToken(tl);
-	Fb(tl, 1, "VRT_purge(ctx, 0, 0);\n");
-}
-
-/*--------------------------------------------------------------------*/
-
-static void
-parse_synthetic(struct vcc *tl)
-{
-	vcc_NextToken(tl);
-
-	Fb(tl, 1, "VRT_synth_page(ctx, 0, ");
-	vcc_Expr(tl, STRING_LIST);
-	ERRCHK(tl);
-	Fb(tl, 0, ");\n");
-}
-
-/*--------------------------------------------------------------------*/
-
-typedef void action_f(struct vcc *tl);
-
-static struct action_table {
-	const char		*name;
-	action_f		*func;
-	unsigned		bitmask;
-} action_table[] = {
-	/* Keep list sorted from here */
-	{ "ban",		parse_ban },
-	{ "call",		parse_call },
-	{ "error",		parse_error },
-	{ "hash_data",		parse_hash_data, VCL_MET_HASH },
-	{ "new",		parse_new, VCL_MET_INIT},
-	{ "purge",		parse_purge, VCL_MET_MISS | VCL_MET_HIT },
-	{ "remove",		parse_unset }, /* backward compatibility */
-	{ "return",		parse_return },
-	{ "rollback",		parse_rollback },
-	{ "set",		parse_set },
-	{ "synthetic",		parse_synthetic, VCL_MET_ERROR },
-	{ "unset",		parse_unset },
-	{ NULL,			NULL }
-};
-
-int
-vcc_ParseAction(struct vcc *tl)
-{
-	struct token *at;
-	struct action_table *atp;
-	const struct symbol *sym;
-
-	at = tl->t;
-	assert(at->tok == ID);
-	for(atp = action_table; atp->name != NULL; atp++) {
-		if (vcc_IdIs(at, atp->name)) {
-			if (atp->bitmask != 0)
-				vcc_AddUses(tl, at, atp->bitmask,
-				    "not a valid action");
-			atp->func(tl);
-			return (1);
-		}
-	}
-	sym = VCC_FindSymbol(tl, tl->t, SYM_NONE);
-	if (sym != NULL && sym->kind == SYM_PROC) {
-		vcc_Expr_Call(tl, sym);
-		return (1);
-	}
-	return (0);
-}
diff --git a/lib/libvcl/vcc_backend.c b/lib/libvcl/vcc_backend.c
deleted file mode 100644
index b548d94..0000000
--- a/lib/libvcl/vcc_backend.c
+++ /dev/null
@@ -1,484 +0,0 @@
-/*-
- * Copyright (c) 2006 Verdens Gang AS
- * Copyright (c) 2006-2013 Varnish Software AS
- * All rights reserved.
- *
- * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- */
-
-#include "config.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "vcc_compile.h"
-
-#include "vss.h"
-
-/*--------------------------------------------------------------------
- * Struct sockaddr is not really designed to be a compile time
- * initialized data structure, so we encode it as a byte-string
- * and put it in an official sockaddr when we load the VCL.
- */
-
-static void
-Emit_Sockaddr(struct vcc *tl, const struct token *t_host, const char *port)
-{
-	const char *ipv4, *ipv4a, *ipv6, *ipv6a, *pa;
-	const char *err;
-	char *hop, *pop;
-
-	AN(t_host->dec);
-
-	err = VSS_parse(t_host->dec, &hop, &pop);
-	if (err != NULL) {
-		VSB_printf(tl->sb,
-		    "Backend host '%.*s': %s\n", PF(t_host), err);
-		vcc_ErrWhere(tl, t_host);
-		return;
-	}
-	Resolve_Sockaddr(tl,
-	    hop != NULL ? hop : t_host->dec,
-	    pop != NULL ? pop : port,
-	    &ipv4, &ipv4a, &ipv6, &ipv6a, &pa, 2, t_host, "Backend host");
-	ERRCHK(tl);
-	if (ipv4 != NULL) {
-		Fb(tl, 0, "\t.ipv4_sockaddr = %s,\n", ipv4);
-		Fb(tl, 0, "\t.ipv4_addr = \"%s\",\n", ipv4a);
-	}
-	if (ipv6 != NULL) {
-		Fb(tl, 0, "\t.ipv6_sockaddr = %s,\n", ipv6);
-		Fb(tl, 0, "\t.ipv6_addr = \"%s\",\n", ipv6a);
-	}
-	Fb(tl, 0, "\t.port = \"%s\",\n", pa);
-}
-
-/*--------------------------------------------------------------------
- * Parse a backend probe specification
- */
-
-static void
-vcc_ProbeRedef(struct vcc *tl, struct token **t_did,
-    struct token *t_field)
-{
-	/* .url and .request are mutually exclusive */
-
-	if (*t_did != NULL) {
-		VSB_printf(tl->sb, "Probe request redefinition at:\n");
-		vcc_ErrWhere(tl, t_field);
-		VSB_printf(tl->sb, "Previous definition:\n");
-		vcc_ErrWhere(tl, *t_did);
-		return;
-	}
-	*t_did = t_field;
-}
-
-static void
-vcc_ParseProbeSpec(struct vcc *tl)
-{
-	struct fld_spec *fs;
-	struct token *t_field;
-	struct token *t_did = NULL, *t_window = NULL, *t_threshold = NULL;
-	struct token *t_initial = NULL;
-	unsigned window, threshold, initial, status;
-	double t;
-
-	fs = vcc_FldSpec(tl,
-	    "?url",
-	    "?request",
-	    "?expected_response",
-	    "?timeout",
-	    "?interval",
-	    "?window",
-	    "?threshold",
-	    "?initial",
-	    NULL);
-
-	SkipToken(tl, '{');
-
-	window = 0;
-	threshold = 0;
-	initial = 0;
-	status = 0;
-	Fh(tl, 0, "static const struct vrt_backend_probe vgc_probe__%d = {\n",
-	    tl->nprobe++);
-	while (tl->t->tok != '}') {
-
-		vcc_IsField(tl, &t_field, fs);
-		ERRCHK(tl);
-		if (vcc_IdIs(t_field, "url")) {
-			vcc_ProbeRedef(tl, &t_did, t_field);
-			ERRCHK(tl);
-			ExpectErr(tl, CSTR);
-			Fh(tl, 0, "\t.url = ");
-			EncToken(tl->fh, tl->t);
-			Fh(tl, 0, ",\n");
-			vcc_NextToken(tl);
-		} else if (vcc_IdIs(t_field, "request")) {
-			vcc_ProbeRedef(tl, &t_did, t_field);
-			ERRCHK(tl);
-			ExpectErr(tl, CSTR);
-			Fh(tl, 0, "\t.request =\n");
-			while (tl->t->tok == CSTR) {
-				Fh(tl, 0, "\t\t");
-				EncToken(tl->fh, tl->t);
-				Fh(tl, 0, " \"\\r\\n\"\n");
-				vcc_NextToken(tl);
-			}
-			Fh(tl, 0, "\t\t\"\\r\\n\",\n");
-		} else if (vcc_IdIs(t_field, "timeout")) {
-			Fh(tl, 0, "\t.timeout = ");
-			vcc_Duration(tl, &t);
-			ERRCHK(tl);
-			Fh(tl, 0, "%g,\n", t);
-		} else if (vcc_IdIs(t_field, "interval")) {
-			Fh(tl, 0, "\t.interval = ");
-			vcc_Duration(tl, &t);
-			ERRCHK(tl);
-			Fh(tl, 0, "%g,\n", t);
-		} else if (vcc_IdIs(t_field, "window")) {
-			t_window = tl->t;
-			window = vcc_UintVal(tl);
-			ERRCHK(tl);
-		} else if (vcc_IdIs(t_field, "initial")) {
-			t_initial = tl->t;
-			initial = vcc_UintVal(tl);
-			ERRCHK(tl);
-		} else if (vcc_IdIs(t_field, "expected_response")) {
-			status = vcc_UintVal(tl);
-			if (status < 100 || status > 999) {
-				VSB_printf(tl->sb,
-				    "Must specify .expected_response with "
-				    "exactly three digits "
-				    "(100 <= x <= 999)\n");
-				vcc_ErrWhere(tl, tl->t);
-				return;
-			}
-			ERRCHK(tl);
-		} else if (vcc_IdIs(t_field, "threshold")) {
-			t_threshold = tl->t;
-			threshold = vcc_UintVal(tl);
-			ERRCHK(tl);
-		} else {
-			vcc_ErrToken(tl, t_field);
-			vcc_ErrWhere(tl, t_field);
-			ErrInternal(tl);
-			return;
-		}
-
-		SkipToken(tl, ';');
-	}
-
-	if (t_threshold != NULL || t_window != NULL) {
-		if (t_threshold == NULL && t_window != NULL) {
-			VSB_printf(tl->sb,
-			    "Must specify .threshold with .window\n");
-			vcc_ErrWhere(tl, t_window);
-			return;
-		} else if (t_threshold != NULL && t_window == NULL) {
-			if (threshold > 64) {
-				VSB_printf(tl->sb,
-				    "Threshold must be 64 or less.\n");
-				vcc_ErrWhere(tl, t_threshold);
-				return;
-			}
-			window = threshold + 1;
-		} else if (window > 64) {
-			AN(t_window);
-			VSB_printf(tl->sb, "Window must be 64 or less.\n");
-			vcc_ErrWhere(tl, t_window);
-			return;
-		}
-		if (threshold > window ) {
-			VSB_printf(tl->sb,
-			    "Threshold can not be greater than window.\n");
-			AN(t_threshold);
-			vcc_ErrWhere(tl, t_threshold);
-			AN(t_window);
-			vcc_ErrWhere(tl, t_window);
-		}
-		Fh(tl, 0, "\t.window = %u,\n", window);
-		Fh(tl, 0, "\t.threshold = %u,\n", threshold);
-	}
-	if (t_initial != NULL)
-		Fh(tl, 0, "\t.initial = %u,\n", initial);
-	else
-		Fh(tl, 0, "\t.initial = ~0U,\n");
-	if (status > 0)
-		Fh(tl, 0, "\t.exp_status = %u,\n", status);
-	Fh(tl, 0, "};\n");
-	SkipToken(tl, '}');
-}
-
-/*--------------------------------------------------------------------
- * Parse and emit a probe definition
- */
-
-void
-vcc_ParseProbe(struct vcc *tl)
-{
-	struct token *t_probe;
-	int i;
-
-	vcc_NextToken(tl);		/* ID: probe */
-
-	vcc_ExpectCid(tl);		/* ID: name */
-	ERRCHK(tl);
-	t_probe = tl->t;
-	vcc_NextToken(tl);
-	i = vcc_AddDef(tl, t_probe, SYM_PROBE);
-	if (i > 1) {
-		VSB_printf(tl->sb, "Probe %.*s redefined\n", PF(t_probe));
-		vcc_ErrWhere(tl, t_probe);
-	}
-
-	Fh(tl, 0, "\n#define vgc_probe_%.*s\tvgc_probe__%d\n",
-	    PF(t_probe), tl->nprobe);
-	vcc_ParseProbeSpec(tl);
-}
-
-/*--------------------------------------------------------------------
- * Parse and emit a backend host definition
- *
- * The struct vrt_backend is emitted to Fh().
- */
-
-static void
-vcc_ParseHostDef(struct vcc *tl, const struct token *t_be)
-{
-	struct token *t_field;
-	struct token *t_host = NULL;
-	struct token *t_port = NULL;
-	struct token *t_hosthdr = NULL;
-	struct fld_spec *fs;
-	struct vsb *vsb;
-	unsigned u;
-	double t;
-	char vgcname[MAX_BACKEND_NAME + 8];
-
-	sprintf(vgcname, "_%.*s", PF(t_be));
-
-	Fh(tl, 1, "\n#define VGC_backend_%s %d\n", vgcname, tl->ndirector);
-
-	fs = vcc_FldSpec(tl,
-	    "!host",
-	    "?port",
-	    "?host_header",
-	    "?connect_timeout",
-	    "?first_byte_timeout",
-	    "?between_bytes_timeout",
-	    "?probe",
-	    "?max_connections",
-	    NULL);
-
-	SkipToken(tl, '{');
-
-	vsb = VSB_new_auto();
-	AN(vsb);
-	tl->fb = vsb;
-
-	Fb(tl, 0, "\nstatic const struct vrt_backend vgc_dir_priv_%s = {\n",
-	    vgcname);
-
-	Fb(tl, 0, "\t.vcl_name = \"%.*s", PF(t_be));
-	Fb(tl, 0, "\",\n");
-
-	/* Check for old syntax */
-	if (tl->t->tok == ID && vcc_IdIs(tl->t, "set")) {
-		VSB_printf(tl->sb,
-		    "NB: Backend Syntax has changed:\n"
-		    "Remove \"set\" and \"backend\" in front"
-		    " of backend fields.\n" );
-		vcc_ErrToken(tl, tl->t);
-		VSB_printf(tl->sb, " at ");
-		vcc_ErrWhere(tl, tl->t);
-		return;
-	}
-
-	while (tl->t->tok != '}') {
-
-		vcc_IsField(tl, &t_field, fs);
-		ERRCHK(tl);
-		if (vcc_IdIs(t_field, "host")) {
-			ExpectErr(tl, CSTR);
-			assert(tl->t->dec != NULL);
-			t_host = tl->t;
-			vcc_NextToken(tl);
-			SkipToken(tl, ';');
-		} else if (vcc_IdIs(t_field, "port")) {
-			ExpectErr(tl, CSTR);
-			assert(tl->t->dec != NULL);
-			t_port = tl->t;
-			vcc_NextToken(tl);
-			SkipToken(tl, ';');
-		} else if (vcc_IdIs(t_field, "host_header")) {
-			ExpectErr(tl, CSTR);
-			assert(tl->t->dec != NULL);
-			t_hosthdr = tl->t;
-			vcc_NextToken(tl);
-			SkipToken(tl, ';');
-		} else if (vcc_IdIs(t_field, "connect_timeout")) {
-			Fb(tl, 0, "\t.connect_timeout = ");
-			vcc_Duration(tl, &t);
-			ERRCHK(tl);
-			Fb(tl, 0, "%g,\n", t);
-			SkipToken(tl, ';');
-		} else if (vcc_IdIs(t_field, "first_byte_timeout")) {
-			Fb(tl, 0, "\t.first_byte_timeout = ");
-			vcc_Duration(tl, &t);
-			ERRCHK(tl);
-			Fb(tl, 0, "%g,\n", t);
-			SkipToken(tl, ';');
-		} else if (vcc_IdIs(t_field, "between_bytes_timeout")) {
-			Fb(tl, 0, "\t.between_bytes_timeout = ");
-			vcc_Duration(tl, &t);
-			ERRCHK(tl);
-			Fb(tl, 0, "%g,\n", t);
-			SkipToken(tl, ';');
-		} else if (vcc_IdIs(t_field, "max_connections")) {
-			u = vcc_UintVal(tl);
-			ERRCHK(tl);
-			SkipToken(tl, ';');
-			Fb(tl, 0, "\t.max_connections = %u,\n", u);
-		} else if (vcc_IdIs(t_field, "probe") && tl->t->tok == '{') {
-			Fb(tl, 0, "\t.probe = &vgc_probe__%d,\n", tl->nprobe);
-			vcc_ParseProbeSpec(tl);
-			ERRCHK(tl);
-		} else if (vcc_IdIs(t_field, "probe") && tl->t->tok == ID) {
-			Fb(tl, 0, "\t.probe = &vgc_probe_%.*s,\n", PF(tl->t));
-			vcc_AddRef(tl, tl->t, SYM_PROBE);
-			vcc_NextToken(tl);
-			SkipToken(tl, ';');
-		} else if (vcc_IdIs(t_field, "probe")) {
-			VSB_printf(tl->sb,
-			    "Expected '{' or name of probe, got ");
-			vcc_ErrToken(tl, tl->t);
-			VSB_printf(tl->sb, " at\n");
-			vcc_ErrWhere(tl, tl->t);
-			return;
-		} else {
-			ErrInternal(tl);
-			return;
-		}
-
-	}
-
-	vcc_FieldsOk(tl, fs);
-	ERRCHK(tl);
-
-	/* Check that the hostname makes sense */
-	assert(t_host != NULL);
-	if (t_port != NULL)
-		Emit_Sockaddr(tl, t_host, t_port->dec);
-	else
-		Emit_Sockaddr(tl, t_host, "80");
-	ERRCHK(tl);
-
-	ExpectErr(tl, '}');
-
-	/* We have parsed it all, emit the ident string */
-
-	/* Emit the hosthdr field, fall back to .host if not specified */
-	Fb(tl, 0, "\t.hosthdr = ");
-	if (t_hosthdr != NULL)
-		EncToken(tl->fb, t_hosthdr);
-	else
-		EncToken(tl->fb, t_host);
-	Fb(tl, 0, ",\n");
-
-	/* Close the struct */
-	Fb(tl, 0, "};\n");
-
-	vcc_NextToken(tl);
-
-	tl->fb = NULL;
-	AZ(VSB_finish(vsb));
-	Fh(tl, 0, "%s", VSB_data(vsb));
-	VSB_delete(vsb);
-
-	Fi(tl, 0, "\tVRT_init_dir(cli, VCL_conf.director,\n"
-	    "\t    VGC_backend_%s, &vgc_dir_priv_%s);\n", vgcname, vgcname);
-	Ff(tl, 0, "\tVRT_fini_dir(cli, VGCDIR(%s));\n", vgcname);
-	tl->ndirector++;
-}
-
-/*--------------------------------------------------------------------
- * Parse directors and backends
- */
-
-void
-vcc_ParseBackend(struct vcc *tl)
-{
-	struct token *t_first, *t_be;
-	int isfirst;
-	struct symbol *sym;
-
-	t_first = tl->t;
-	vcc_NextToken(tl);		/* ID: backend */
-
-	vcc_ExpectCid(tl);		/* ID: name */
-	ERRCHK(tl);
-
-	if (tl->t->e - tl->t->b > MAX_BACKEND_NAME) {
-		VSB_printf(tl->sb,
-		    "Name of %.*s too long (max %d, is %zu):\n",
-		    PF(t_first), MAX_BACKEND_NAME,
-		    (size_t)(tl->t->e - tl->t->b));
-		vcc_ErrWhere(tl, tl->t);
-		return;
-	}
-
-	t_be = tl->t;
-	vcc_NextToken(tl);
-
-	isfirst = tl->ndirector;
-
-	sym = VCC_GetSymbolTok(tl, t_be, SYM_BACKEND);
-	AN(sym);
-	if (sym->ndef > 0) {
-		VSB_printf(tl->sb, "Backend %.*s redefined\n", PF(t_be));
-		vcc_ErrWhere(tl, t_be);
-		return;
-	}
-	sym->fmt = BACKEND;
-	sym->eval = vcc_Eval_Backend;
-	sym->ndef++;
-	ERRCHK(tl);
-
-	vcc_ParseHostDef(tl, t_be);
-	ERRCHK(tl);
-
-	if (tl->err) {
-		VSB_printf(tl->sb,
-		    "\nIn %.*s specification starting at:\n", PF(t_first));
-		vcc_ErrWhere(tl, t_first);
-		return;
-	}
-
-	if (isfirst == 1 || vcc_IdIs(t_be, "default")) {
-		tl->defaultdir = tl->ndirector - 1;
-		tl->t_defaultdir = t_be;
-	}
-}
diff --git a/lib/libvcl/vcc_backend_util.c b/lib/libvcl/vcc_backend_util.c
deleted file mode 100644
index de361a5..0000000
--- a/lib/libvcl/vcc_backend_util.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/*-
- * Copyright (c) 2006 Verdens Gang AS
- * Copyright (c) 2006-2011 Varnish Software AS
- * All rights reserved.
- *
- * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- */
-
-#include "config.h"
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "vcc_compile.h"
-
-/*--------------------------------------------------------------------
- * Helper functions to complain about duplicate and missing fields
- *
- * XXX: idea: add groups to check for exclusivity, such that
- * XXX:    ("!foo", "?bar", "!{", "this", "that", "}", NULL)
- * XXX: means exactly one of "this" or "that", and
- * XXX:    ("!foo", "?bar", "?{", "this", "that", "}", NULL)
- * XXX: means at most one of "this" or "that".
- */
-
-struct fld_spec {
-	const char	*name;
-	struct token	*found;
-};
-
-static void
-vcc_ResetFldSpec(struct fld_spec *f)
-{
-
-	for (; f->name != NULL; f++)
-		f->found = NULL;
-}
-
-struct fld_spec *
-vcc_FldSpec(struct vcc *tl, const char *first, ...)
-{
-	struct fld_spec f[100], *r;
-	int n = 0;
-	va_list ap;
-	const char *p;
-
-	f[n++].name = first;
-	va_start(ap, first);
-	while (1) {
-		p = va_arg(ap, const char *);
-		if (p == NULL)
-			break;
-		f[n++].name = p;
-		assert(n < 100);
-	}
-	va_end(ap);
-	f[n++].name = NULL;
-
-	vcc_ResetFldSpec(f);
-
-	r = TlAlloc(tl, sizeof *r * n);
-	memcpy(r, f, n * sizeof *r);
-	return (r);
-}
-
-void
-vcc_IsField(struct vcc *tl, struct token **t, struct fld_spec *fs)
-{
-	struct token *t_field;
-
-	SkipToken(tl, '.');
-	ExpectErr(tl, ID);
-	t_field = tl->t;
-	*t = t_field;
-	vcc_NextToken(tl);
-	SkipToken(tl, '=');
-
-	for (; fs->name != NULL; fs++) {
-		if (!vcc_IdIs(t_field, fs->name + 1))
-			continue;
-		if (fs->found == NULL) {
-			fs->found = t_field;
-			return;
-		}
-		VSB_printf(tl->sb, "Field ");
-		vcc_ErrToken(tl, t_field);
-		VSB_printf(tl->sb, " redefined at:\n");
-		vcc_ErrWhere(tl, t_field);
-		VSB_printf(tl->sb, "\nFirst defined at:\n");
-		vcc_ErrWhere(tl, fs->found);
-		return;
-	}
-	VSB_printf(tl->sb, "Unknown field: ");
-	vcc_ErrToken(tl, t_field);
-	VSB_printf(tl->sb, " at\n");
-	vcc_ErrWhere(tl, t_field);
-	return;
-}
-
-void
-vcc_FieldsOk(struct vcc *tl, const struct fld_spec *fs)
-{
-
-	for (; fs->name != NULL; fs++) {
-		if (*fs->name == '!' && fs->found == NULL) {
-			VSB_printf(tl->sb,
-			    "Mandatory field '%s' missing.\n", fs->name + 1);
-			tl->err = 1;
-		}
-	}
-}
diff --git a/lib/libvcl/vcc_compile.c b/lib/libvcl/vcc_compile.c
deleted file mode 100644
index 07eef41..0000000
--- a/lib/libvcl/vcc_compile.c
+++ /dev/null
@@ -1,823 +0,0 @@
-/*-
- * Copyright (c) 2006 Verdens Gang AS
- * Copyright (c) 2006-2013 Varnish Software AS
- * All rights reserved.
- *
- * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-/*
- * XXX:
- *	Better error messages, throughout.
- *	>It also accured to me that we could link the errors to the error
- *	>documentation.
- *	>
- *	>Unreferenced  function 'request_policy', first mention is
- *	>         Line 8 Pos 4
- *	>         sub request_policy {
- *	>         ----##############--
- *	>Read more about this type of error:
- *	>http://varnish/doc/error.html#Unreferenced%20function
- *	>
- *	>
- *	>         Unknown variable 'obj.bandwidth'
- *	>         At: Line 88 Pos 12
- *	>                 if (obj.bandwidth < 1 kb/h) {
- *	>         ------------#############------------
- *	>Read more about this type of error:
- *	>http://varnish/doc/error.html#Unknown%20variable
- *
- */
-
-#include "config.h"
-
-#include <ctype.h>
-#include <errno.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "vcc_compile.h"
-
-#include "libvcl.h"
-#include "vfil.h"
-
-struct method method_tab[] = {
-#define VCL_MET_MAC(l,U,m)	{ "vcl_"#l, m, VCL_MET_##U },
-#include "tbl/vcl_returns.h"
-#undef VCL_MET_MAC
-	{ NULL, 0U, 0}
-};
-
-/*--------------------------------------------------------------------*/
-
-static void
-TlDoFree(struct vcc *tl, void *p)
-{
-	struct membit *mb;
-
-	mb = calloc(sizeof *mb, 1);
-	assert(mb != NULL);
-	mb->ptr = p;
-	VTAILQ_INSERT_TAIL(&tl->membits, mb, list);
-}
-
-
-void *
-TlAlloc(struct vcc *tl, unsigned len)
-{
-	void *p;
-
-	p = calloc(len, 1);
-	assert(p != NULL);
-	TlDoFree(tl, p);
-	return (p);
-}
-
-char *
-TlDup(struct vcc *tl, const char *s)
-{
-	char *p;
-
-	p = TlAlloc(tl, strlen(s) + 1);
-	AN(p);
-	strcpy(p, s);
-	return (p);
-}
-
-char *
-TlDupTok(struct vcc *tl, const struct token *tok)
-{
-	char *p;
-	int i;
-
-	i = tok->e - tok->b;
-	p = TlAlloc(tl, i + 1);
-	AN(p);
-	memcpy(p, tok->b, i);
-	p[i] = '\0';
-	return (p);
-}
-
-/*--------------------------------------------------------------------*/
-
-int
-IsMethod(const struct token *t)
-{
-	struct method *m;
-
-	assert(t->tok == ID);
-	for(m = method_tab; m->name != NULL; m++) {
-		if (vcc_IdIs(t, m->name))
-			return (m - method_tab);
-	}
-	if ((t->b[0] == 'v'|| t->b[0] == 'V') &&
-	    (t->b[1] == 'c'|| t->b[1] == 'C') &&
-	    (t->b[2] == 'l'|| t->b[2] == 'L'))
-		return (-2);
-	return (-1);
-}
-
-/*--------------------------------------------------------------------
- * Printf output to the vsbs, possibly indented
- */
-
-void
-Fh(const struct vcc *tl, int indent, const char *fmt, ...)
-{
-	va_list ap;
-
-	if (indent)
-		VSB_printf(tl->fh, "%*.*s", tl->hindent, tl->hindent, "");
-	va_start(ap, fmt);
-	VSB_vprintf(tl->fh, fmt, ap);
-	va_end(ap);
-}
-
-void
-Fb(const struct vcc *tl, int indent, const char *fmt, ...)
-{
-	va_list ap;
-
-	assert(tl->fb != NULL);
-	if (indent)
-		VSB_printf(tl->fb, "%*.*s", tl->indent, tl->indent, "");
-	va_start(ap, fmt);
-	VSB_vprintf(tl->fb, fmt, ap);
-	va_end(ap);
-}
-
-void
-Fc(const struct vcc *tl, int indent, const char *fmt, ...)
-{
-	va_list ap;
-
-	if (indent)
-		VSB_printf(tl->fc, "%*.*s", tl->indent, tl->indent, "");
-	va_start(ap, fmt);
-	VSB_vprintf(tl->fc, fmt, ap);
-	va_end(ap);
-}
-
-void
-Fi(const struct vcc *tl, int indent, const char *fmt, ...)
-{
-	va_list ap;
-
-	if (indent)
-		VSB_printf(tl->fi, "%*.*s", tl->iindent, tl->iindent, "");
-	va_start(ap, fmt);
-	VSB_vprintf(tl->fi, fmt, ap);
-	va_end(ap);
-}
-
-void
-Fd(const struct vcc *tl, int indent, const char *fmt, ...)
-{
-	va_list ap;
-
-	if (indent)
-		VSB_printf(tl->fd, "%*.*s", tl->findent, tl->findent, "");
-	va_start(ap, fmt);
-	VSB_vprintf(tl->fd, fmt, ap);
-	va_end(ap);
-}
-
-
-void
-Ff(const struct vcc *tl, int indent, const char *fmt, ...)
-{
-	va_list ap;
-
-	if (indent)
-		VSB_printf(tl->ff, "%*.*s", tl->findent, tl->findent, "");
-	va_start(ap, fmt);
-	VSB_vprintf(tl->ff, fmt, ap);
-	va_end(ap);
-}
-
-/*--------------------------------------------------------------------*/
-
-void
-EncString(struct vsb *sb, const char *b, const char *e, int mode)
-{
-
-	if (e == NULL)
-		e = strchr(b, '\0');
-
-	VSB_cat(sb, "\"");
-	for (; b < e; b++) {
-		switch (*b) {
-		case '\\':
-		case '"':
-			VSB_printf(sb, "\\%c", *b);
-			break;
-		case '\n':
-			VSB_printf(sb, "\\n");
-			if (mode)
-				VSB_printf(sb, "\"\n\t\"");
-			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", (uint8_t)*b);
-			break;
-		}
-	}
-	VSB_cat(sb, "\"");
-}
-
-void
-EncToken(struct vsb *sb, const struct token *t)
-{
-
-	assert(t->tok == CSTR);
-	EncString(sb, t->dec, NULL, 1);
-}
-
-/*--------------------------------------------------------------------
- * Output the location/profiling table.  For each counted token, we
- * record source+line+charpos for the first character in the token.
- */
-
-static void
-LocTable(const struct vcc *tl)
-{
-	struct token *t;
-	unsigned lin, pos;
-	struct source *sp;
-	const char *p;
-
-	Fh(tl, 0, "\n#define VGC_NREFS %u\n", tl->cnt + 1);
-	Fc(tl, 0, "\nstatic struct vrt_ref VGC_ref[VGC_NREFS] = {\n");
-	lin = 1;
-	pos = 0;
-	sp = 0;
-	p = NULL;
-	VTAILQ_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 == '\n') {
-				lin++;
-				pos = 0;
-			} else if (*p == '\t') {
-				pos &= ~7;
-				pos += 8;
-			} else
-				pos++;
-
-		}
-		Fc(tl, 0, "  [%3u] = { %d, %8tu, %4u, %3u, 0, ",
-		    t->cnt, sp->idx, t->b - sp->b, lin, pos + 1);
-		if (t->tok == CSRC)
-			Fc(tl, 0, " \"C{\"},\n");
-		else
-			Fc(tl, 0, " \"%.*s\" },\n", PF(t));
-	}
-	Fc(tl, 0, "};\n");
-}
-
-/*--------------------------------------------------------------------*/
-
-static void
-EmitInitFunc(const struct vcc *tl)
-{
-
-	Fc(tl, 0, "\nstatic int\nVGC_Init(struct cli *cli)\n{\n\n");
-	AZ(VSB_finish(tl->fi));
-	VSB_cat(tl->fc, VSB_data(tl->fi));
-	Fc(tl, 0, "\treturn(0);\n");
-	Fc(tl, 0, "}\n");
-}
-
-static void
-EmitFiniFunc(const struct vcc *tl)
-{
-	unsigned u;
-
-	Fc(tl, 0, "\nstatic void\nVGC_Fini(struct cli *cli)\n{\n\n");
-
-	AZ(VSB_finish(tl->fd));
-	VSB_cat(tl->fc, VSB_data(tl->fd));
-
-	/*
-	 * We do this here, so we are sure they happen before any
-	 * per-vcl vmod_privs get cleaned.
-	 */
-	for (u = 0; u < tl->nvmodpriv; u++)
-		Fc(tl, 0, "\tvmod_priv_fini(&vmod_priv_%u);\n", u);
-
-	AZ(VSB_finish(tl->ff));
-	VSB_cat(tl->fc, VSB_data(tl->ff));
-	Fc(tl, 0, "}\n");
-}
-
-/*--------------------------------------------------------------------*/
-
-static void
-EmitStruct(const struct vcc *tl)
-{
-	struct source *sp;
-
-	Fc(tl, 0, "\nconst char *srcname[%u] = {\n", tl->nsources);
-	VTAILQ_FOREACH(sp, &tl->sources, list) {
-		Fc(tl, 0, "\t");
-		EncString(tl->fc, sp->name, NULL, 0);
-		Fc(tl, 0, ",\n");
-	}
-	Fc(tl, 0, "};\n");
-
-	Fc(tl, 0, "\nconst char *srcbody[%u] = {\n", tl->nsources);
-	VTAILQ_FOREACH(sp, &tl->sources, list) {
-		Fc(tl, 0, "    /* ");
-		EncString(tl->fc, sp->name, NULL, 0);
-		Fc(tl, 0, "*/\n");
-		Fc(tl, 0, "\t");
-		EncString(tl->fc, sp->b, sp->e, 1);
-		Fc(tl, 0, ",\n");
-	}
-	Fc(tl, 0, "};\n");
-
-	Fc(tl, 0, "\nstatic struct director\t*directors[%d];\n",
-	    tl->ndirector);
-
-	Fc(tl, 0, "\nconst struct VCL_conf VCL_conf = {\n");
-	Fc(tl, 0, "\t.magic = VCL_CONF_MAGIC,\n");
-	Fc(tl, 0, "\t.init_vcl = VGC_Init,\n");
-	Fc(tl, 0, "\t.fini_vcl = VGC_Fini,\n");
-	Fc(tl, 0, "\t.ndirector = %d,\n", tl->ndirector);
-	Fc(tl, 0, "\t.director = directors,\n");
-	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_MET_MAC(l,u,b) \
-	Fc(tl, 0, "\t." #l "_func = VGC_function_vcl_" #l ",\n");
-#include "tbl/vcl_returns.h"
-#undef VCL_MET_MAC
-	Fc(tl, 0, "};\n");
-}
-
-/*--------------------------------------------------------------------*/
-
-static struct source *
-vcc_new_source(const char *b, const char *e, const char *name)
-{
-	struct source *sp;
-
-	if (e == NULL)
-		e = strchr(b, '\0');
-	sp = calloc(sizeof *sp, 1);
-	assert(sp != NULL);
-	sp->name = strdup(name);
-	AN(sp->name);
-	sp->b = b;
-	sp->e = e;
-	return (sp);
-}
-
-static void
-vcc_destroy_source(struct source *sp)
-{
-
-	if (sp->freeit != NULL)
-		free(sp->freeit);
-	free(sp->name);
-	free(sp);
-}
-
-/*--------------------------------------------------------------------*/
-
-static struct source *
-vcc_file_source(const struct vcc *tl, struct vsb *sb, const char *fn)
-{
-	char *f;
-	struct source *sp;
-
-	if (!tl->unsafe_path && strchr(fn, '/') != NULL) {
-		VSB_printf(sb, "Include path is unsafe '%s'\n", fn);
-		return (NULL);
-	}
-	f = VFIL_readfile(tl->vcl_dir, fn, NULL);
-	if (f == NULL) {
-		VSB_printf(sb, "Cannot read file '%s': %s\n",
-		    fn, strerror(errno));
-		return (NULL);
-	}
-	sp = vcc_new_source(f, NULL, fn);
-	sp->freeit = f;
-	return (sp);
-}
-
-/*--------------------------------------------------------------------*/
-
-static void
-vcc_resolve_includes(struct vcc *tl)
-{
-	struct token *t, *t1, *t2;
-	struct source *sp;
-
-	VTAILQ_FOREACH(t, &tl->tokens, list) {
-		if (t->tok != ID || !vcc_IdIs(t, "include"))
-			continue;
-
-		t1 = VTAILQ_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 = VTAILQ_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;
-		}
-
-		sp = vcc_file_source(tl, tl->sb, t1->dec);
-		if (sp == NULL) {
-			vcc_ErrWhere(tl, t1);
-			return;
-		}
-		VTAILQ_INSERT_TAIL(&tl->sources, sp, list);
-		sp->idx = tl->nsources++;
-		tl->t = t2;
-		vcc_Lexer(tl, sp);
-
-		VTAILQ_REMOVE(&tl->tokens, t, list);
-		VTAILQ_REMOVE(&tl->tokens, t1, list);
-		VTAILQ_REMOVE(&tl->tokens, t2, list);
-		if (!tl->err)
-			vcc_resolve_includes(tl);
-		return;
-	}
-}
-
-/*--------------------------------------------------------------------*/
-
-static struct vcc *
-vcc_NewVcc(const struct vcc *tl0)
-{
-	struct vcc *tl;
-	int i;
-
-	ALLOC_OBJ(tl, VCC_MAGIC);
-	AN(tl);
-	if (tl0 != NULL) {
-		REPLACE(tl->default_vcl, tl0->default_vcl);
-		REPLACE(tl->vcl_dir, tl0->vcl_dir);
-		REPLACE(tl->vmod_dir, tl0->vmod_dir);
-		tl->vars = tl0->vars;
-		tl->err_unref = tl0->err_unref;
-		tl->allow_inline_c = tl0->allow_inline_c;
-		tl->unsafe_path = tl0->unsafe_path;
-	} else {
-		tl->err_unref = 1;
-	}
-	VTAILQ_INIT(&tl->symbols);
-	VTAILQ_INIT(&tl->membits);
-	VTAILQ_INIT(&tl->tokens);
-	VTAILQ_INIT(&tl->sources);
-
-	tl->nsources = 0;
-	tl->ndirector = 1;
-
-	/* General C code */
-	tl->fc = VSB_new_auto();
-	assert(tl->fc != NULL);
-
-	/* Forward decls (.h like) */
-	tl->fh = VSB_new_auto();
-	assert(tl->fh != NULL);
-
-	/* Init C code */
-	tl->fi = VSB_new_auto();
-	assert(tl->fi != NULL);
-
-	/* Destroy Objects */
-	tl->fd = VSB_new_auto();
-	assert(tl->fd != NULL);
-
-	/* Finish C code */
-	tl->ff = VSB_new_auto();
-	assert(tl->ff != NULL);
-
-	/* body code of methods */
-	for (i = 0; i < VCL_MET_MAX; i++) {
-		tl->fm[i] = VSB_new_auto();
-		assert(tl->fm[i] != NULL);
-	}
-	return (tl);
-}
-
-/*--------------------------------------------------------------------*/
-
-static char *
-vcc_DestroyTokenList(struct vcc *tl, char *ret)
-{
-	struct membit *mb;
-	struct source *sp;
-	struct symbol *sym;
-	int i;
-
-	while (!VTAILQ_EMPTY(&tl->membits)) {
-		mb = VTAILQ_FIRST(&tl->membits);
-		VTAILQ_REMOVE(&tl->membits, mb, list);
-		free(mb->ptr);
-		free(mb);
-	}
-	while (!VTAILQ_EMPTY(&tl->sources)) {
-		sp = VTAILQ_FIRST(&tl->sources);
-		VTAILQ_REMOVE(&tl->sources, sp, list);
-		vcc_destroy_source(sp);
-	}
-
-	while (!VTAILQ_EMPTY(&tl->symbols)) {
-		sym = VTAILQ_FIRST(&tl->symbols);
-		VTAILQ_REMOVE(&tl->symbols, sym, list);
-		FREE_OBJ(sym);
-	}
-
-	VSB_delete(tl->fh);
-	VSB_delete(tl->fc);
-	VSB_delete(tl->fi);
-	VSB_delete(tl->ff);
-	for (i = 0; i < VCL_MET_MAX; i++)
-		VSB_delete(tl->fm[i]);
-
-	free(tl);
-	return (ret);
-}
-
-/*--------------------------------------------------------------------
- * Compile the VCL code from the given source and return the C-source
- */
-
-static char *
-vcc_CompileSource(const struct vcc *tl0, struct vsb *sb, struct source *sp)
-{
-	struct vcc *tl;
-	struct symbol *sym;
-	const struct var *v;
-	char *of;
-	int i;
-
-	tl = vcc_NewVcc(tl0);
-	tl->sb = sb;
-
-	vcc_Expr_Init(tl);
-
-	for (v = tl->vars; v->name != NULL; v++) {
-		if (v->fmt == HEADER) {
-			sym = VCC_AddSymbolStr(tl, v->name, SYM_WILDCARD);
-			sym->wildcard = vcc_Var_Wildcard;
-		} else {
-			sym = VCC_AddSymbolStr(tl, v->name, SYM_VAR);
-		}
-		sym->var = v;
-		sym->fmt = v->fmt;
-		sym->eval = vcc_Eval_Var;
-		sym->r_methods = v->r_methods;
-	}
-
-	sym = VCC_AddSymbolStr(tl, "storage.", SYM_WILDCARD);
-	sym->wildcard = vcc_Stv_Wildcard;
-
-	vcl_output_lang_h(tl->fh);
-	Fh(tl, 0, "\n/* ---===### VCC generated below here ###===---*/\n");
-	Fh(tl, 0, "\nextern const struct VCL_conf VCL_conf;\n");
-
-	/* Macro for accessing directors */
-	Fh(tl, 0, "#define VGCDIR(n) VCL_conf.director[VGC_backend_##n]\n");
-
-	Fh(tl, 0, "#define __match_proto__(xxx)		/*lint -e{818} */\n");
-
-	/* Register and lex the main source */
-	VTAILQ_INSERT_TAIL(&tl->sources, sp, list);
-	sp->idx = tl->nsources++;
-	vcc_Lexer(tl, sp);
-	if (tl->err)
-		return (vcc_DestroyTokenList(tl, NULL));
-
-	/* Register and lex the default VCL */
-	sp = vcc_new_source(tl->default_vcl, NULL, "Default");
-	assert(sp != NULL);
-	VTAILQ_INSERT_TAIL(&tl->sources, sp, list);
-	sp->idx = tl->nsources++;
-	vcc_Lexer(tl, sp);
-	if (tl->err)
-		return (vcc_DestroyTokenList(tl, NULL));
-
-	/* Add "END OF INPUT" token */
-	vcc_AddToken(tl, EOI, sp->e, sp->e);
-	if (tl->err)
-		return (vcc_DestroyTokenList(tl, NULL));
-
-	/* Expand and lex any includes in the token string */
-	vcc_resolve_includes(tl);
-	if (tl->err)
-		return (vcc_DestroyTokenList(tl, NULL));
-
-	/* Parse the token string */
-	tl->t = VTAILQ_FIRST(&tl->tokens);
-	vcc_Parse(tl);
-	if (tl->err)
-		return (vcc_DestroyTokenList(tl, NULL));
-
-	/* Check if we have any backends at all */
-	if (tl->ndirector == 1) {
-		VSB_printf(tl->sb,
-		    "No backends or directors found in VCL program, "
-		    "at least one is necessary.\n");
-		tl->err = 1;
-		return (vcc_DestroyTokenList(tl, NULL));
-	}
-
-	/* Configure the default director */
-	Fi(tl, 0, "\tVCL_conf.director[0] = VCL_conf.director[%d];\n",
-	    tl->defaultdir);
-	vcc_AddRef(tl, tl->t_defaultdir, SYM_BACKEND);
-
-	/* Check for orphans */
-	if (vcc_CheckReferences(tl))
-		return (vcc_DestroyTokenList(tl, NULL));
-
-	/* Check that all action returns are legal */
-	if (vcc_CheckAction(tl) || tl->err)
-		return (vcc_DestroyTokenList(tl, NULL));
-
-	/* Check that all variable uses are legal */
-	if (vcc_CheckUses(tl) || tl->err)
-		return (vcc_DestroyTokenList(tl, NULL));
-
-	/* Emit method functions */
-	for (i = 0; i < VCL_MET_MAX; i++) {
-		Fc(tl, 1, "\nstatic int __match_proto__(vcl_func_f)\n");
-		Fc(tl, 1,
-		    "VGC_function_%s(const struct vrt_ctx *ctx)\n",
-		    method_tab[i].name);
-		AZ(VSB_finish(tl->fm[i]));
-		Fc(tl, 1, "{\n");
-		Fc(tl, 1, "%s", VSB_data(tl->fm[i]));
-		Fc(tl, 1, "}\n");
-	}
-
-	LocTable(tl);
-
-	EmitInitFunc(tl);
-
-	EmitFiniFunc(tl);
-
-	EmitStruct(tl);
-
-	/* Combine it all in the fh vsb */
-	AZ(VSB_finish(tl->fc));
-	VSB_cat(tl->fh, VSB_data(tl->fc));
-	AZ(VSB_finish(tl->fh));
-
-	of = strdup(VSB_data(tl->fh));
-	AN(of);
-
-	/* done */
-	return (vcc_DestroyTokenList(tl, of));
-}
-
-/*--------------------------------------------------------------------
- * Compile the VCL code in the argument.  Error messages, if any are
- * formatted into the vsb.
- */
-
-char *
-VCC_Compile(const struct vcc *tl, struct vsb *sb, const char *b)
-{
-	struct source *sp;
-	char *r;
-
-	sp = vcc_new_source(b, NULL, "input");
-	if (sp == NULL)
-		return (NULL);
-	r = vcc_CompileSource(tl, sb, sp);
-	return (r);
-}
-
-/*--------------------------------------------------------------------
- * Allocate a compiler instance
- */
-
-struct vcc *
-VCC_New(void)
-{
-	struct vcc *tl;
-
-	tl = vcc_NewVcc(NULL);
-
-	tl->vars = vcc_vars;
-
-	return (tl);
-}
-
-/*--------------------------------------------------------------------
- * Configure default VCL source code
- */
-
-void
-VCC_Default_VCL(struct vcc *tl, const char *str)
-{
-
-	CHECK_OBJ_NOTNULL(tl, VCC_MAGIC);
-	REPLACE(tl->default_vcl, str);
-}
-
-/*--------------------------------------------------------------------
- * Configure default VCL source directory
- */
-
-void
-VCC_VCL_dir(struct vcc *tl, const char *str)
-{
-
-	CHECK_OBJ_NOTNULL(tl, VCC_MAGIC);
-	REPLACE(tl->vcl_dir, str);
-}
-
-/*--------------------------------------------------------------------
- * Configure default VMOD directory
- */
-
-void
-VCC_VMOD_dir(struct vcc *tl, const char *str)
-{
-
-	CHECK_OBJ_NOTNULL(tl, VCC_MAGIC);
-	REPLACE(tl->vmod_dir, str);
-}
-
-/*--------------------------------------------------------------------
- * Configure settings
- */
-
-void
-VCC_Err_Unref(struct vcc *tl, unsigned u)
-{
-
-	CHECK_OBJ_NOTNULL(tl, VCC_MAGIC);
-	tl->err_unref = u;
-}
-
-void
-VCC_Allow_InlineC(struct vcc *tl, unsigned u)
-{
-
-	CHECK_OBJ_NOTNULL(tl, VCC_MAGIC);
-	tl->allow_inline_c = u;
-}
-
-void
-VCC_Unsafe_Path(struct vcc *tl, unsigned u)
-{
-
-	CHECK_OBJ_NOTNULL(tl, VCC_MAGIC);
-	tl->unsafe_path = u;
-}
diff --git a/lib/libvcl/vcc_compile.h b/lib/libvcl/vcc_compile.h
deleted file mode 100644
index b0983cc..0000000
--- a/lib/libvcl/vcc_compile.h
+++ /dev/null
@@ -1,351 +0,0 @@
-/*-
- * Copyright (c) 2006 Verdens Gang AS
- * Copyright (c) 2006-2013 Varnish Software AS
- * All rights reserved.
- *
- * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- */
-
-#include <sys/types.h>
-
-#include <errno.h>
-#include <stdio.h>
-#include <stdint.h>
-
-#include "miniobj.h"
-#include "vas.h"
-#include "vcl.h"
-#include "vdef.h"
-#include "vqueue.h"
-#include "vsb.h"
-
-
-#include "vcc_token_defs.h"
-
-#ifndef NULL
-#define NULL ((void*)0)
-#endif
-
-struct vsb;
-struct token;
-struct sockaddr_storage;
-
-#define isident1(c) (isalpha(c))
-#define isident(c) (isalpha(c) || isdigit(c) || (c) == '_' || (c) == '-')
-#define isvar(c) (isident(c) || (c) == '.')
-int vcc_isCid(const struct token *t);
-unsigned vcl_fixed_token(const char *p, const char **q);
-extern const char * const vcl_tnames[256];
-void vcl_output_lang_h(struct vsb *sb);
-
-#define PF(t)	(int)((t)->e - (t)->b), (t)->b
-
-#define INDENT		2
-
-struct acl_e;
-struct proc;
-struct expr;
-struct vcc;
-struct symbol;
-
-enum var_type {
-#define VCC_TYPE(foo)		foo,
-#include "tbl/vcc_types.h"
-#undef VCC_TYPE
-};
-
-struct membit {
-	VTAILQ_ENTRY(membit)	list;
-	void			*ptr;
-};
-
-struct source {
-	VTAILQ_ENTRY(source)	list;
-	char			*name;
-	const char		*b;
-	const char		*e;
-	unsigned		idx;
-	char			*freeit;
-};
-
-struct token {
-	unsigned		tok;
-	const char		*b;
-	const char		*e;
-	struct source		*src;
-	VTAILQ_ENTRY(token)	list;
-	unsigned		cnt;
-	char			*dec;
-};
-
-enum symkind {
-#define VCC_SYMB(uu, ll)	SYM_##uu,
-#include "tbl/symbol_kind.h"
-#undef VCC_SYMB
-};
-
-typedef void sym_expr_t(struct vcc *tl, struct expr **,
-    const struct symbol *sym);
-typedef struct symbol *sym_wildcard_t(struct vcc *tl, const struct token *t,
-    const struct symbol *sym);
-
-struct symbol {
-	unsigned			magic;
-#define SYMBOL_MAGIC			0x3368c9fb
-	VTAILQ_ENTRY(symbol)		list;
-
-	char				*name;
-	unsigned			nlen;
-	sym_wildcard_t			*wildcard;
-	enum symkind			kind;
-
-	const struct token		*def_b, *def_e;
-
-	enum var_type			fmt;
-
-	sym_expr_t			*eval;
-	void				*eval_priv;
-
-	/* xref.c */
-	struct proc			*proc;
-	unsigned			nref, ndef;
-
-	/* SYM_PROC, SYM_FUNC */
-	const char			*cfunc;
-	const char			*extra;
-	const char			*args;
-
-	/* SYM_VAR */
-	const struct var		*var;
-	unsigned			r_methods;
-};
-
-VTAILQ_HEAD(tokenhead, token);
-
-struct vcc {
-	unsigned		magic;
-#define VCC_MAGIC		0x24ad719d
-
-	/* Parameter/Template section */
-	char			*default_vcl;
-	char			*vcl_dir;
-	char			*vmod_dir;
-
-	const struct var	*vars;
-	VTAILQ_HEAD(, symbol)	symbols;
-
-	/* Instance section */
-	struct tokenhead	tokens;
-	VTAILQ_HEAD(, source)	sources;
-	VTAILQ_HEAD(, membit)	membits;
-	unsigned		nsources;
-	struct source		*src;
-	struct token		*t;
-	int			indent;
-	int			hindent;
-	int			iindent;
-	int			findent;
-	unsigned		cnt;
-
-	struct vsb		*fc;		/* C-code */
-	struct vsb		*fh;		/* H-code (before C-code) */
-	struct vsb		*fi;		/* Init func code */
-	struct vsb		*fd;		/* Object destructors */
-	struct vsb		*ff;		/* Finish func code */
-	struct vsb		*fb;		/* Body of current sub
-						 * NULL otherwise
-						 */
-	struct vsb		*fm[VCL_MET_MAX];	/* Method bodies */
-	struct vsb		*sb;
-	int			err;
-	int			ndirector;
-	struct proc		*curproc;
-	struct proc		*mprocs[VCL_MET_MAX];
-
-	VTAILQ_HEAD(, acl_e)	acl;
-
-	int			nprobe;
-
-	int			defaultdir;
-	struct token		*t_defaultdir;
-
-	unsigned		unique;
-	unsigned		nvmodpriv;
-
-	unsigned		err_unref;
-	unsigned		allow_inline_c;
-	unsigned		unsafe_path;
-};
-
-struct var {
-	const char		*name;
-	enum var_type		fmt;
-	unsigned		len;
-	const char		*rname;
-	unsigned		r_methods;
-	const char		*lname;
-	unsigned		w_methods;
-};
-
-struct method {
-	const char		*name;
-	unsigned		ret_bitmap;
-	unsigned		bitval;
-};
-
-/*--------------------------------------------------------------------*/
-
-/* vcc_acl.c */
-
-void vcc_Acl(struct vcc *tl);
-void vcc_Acl_Hack(struct vcc *tl, char *b);
-
-/* vcc_action.c */
-int vcc_ParseAction(struct vcc *tl);
-
-/* vcc_backend.c */
-#define MAX_BACKEND_NAME	64
-struct fld_spec;
-
-void vcc_ParseProbe(struct vcc *tl);
-void vcc_ParseBackend(struct vcc *tl);
-struct fld_spec * vcc_FldSpec(struct vcc *tl, const char *first, ...);
-void vcc_IsField(struct vcc *tl, struct token **t, struct fld_spec *fs);
-void vcc_FieldsOk(struct vcc *tl, const struct fld_spec *fs);
-
-/* vcc_compile.c */
-extern struct method method_tab[];
-/*
- * H -> Header, before the C code
- * C -> C-code
- * B -> Body of function, ends up in C once function is completed
- * I -> Initializer function
- * F -> Finish function
- */
-void Fh(const struct vcc *tl, int indent, const char *fmt, ...)
-    __printflike(3, 4);
-void Fc(const struct vcc *tl, int indent, const char *fmt, ...)
-    __printflike(3, 4);
-void Fb(const struct vcc *tl, int indent, const char *fmt, ...)
-    __printflike(3, 4);
-void Fi(const struct vcc *tl, int indent, const char *fmt, ...)
-    __printflike(3, 4);
-void Ff(const struct vcc *tl, int indent, const char *fmt, ...)
-    __printflike(3, 4);
-void Fd(const struct vcc *tl, int indent, const char *fmt, ...)
-    __printflike(3, 4);
-void EncToken(struct vsb *sb, const struct token *t);
-int IsMethod(const struct token *t);
-void *TlAlloc(struct vcc *tl, unsigned len);
-char *TlDup(struct vcc *tl, const char *s);
-char *TlDupTok(struct vcc *tl, const struct token *tok);
-
-void EncString(struct vsb *sb, const char *b, const char *e, int mode);
-
-/* vcc_expr.c */
-void vcc_Duration(struct vcc *tl, double *);
-unsigned vcc_UintVal(struct vcc *tl);
-void vcc_Expr(struct vcc *tl, enum var_type typ);
-void vcc_Expr_Call(struct vcc *tl, const struct symbol *sym);
-void vcc_Expr_Init(struct vcc *tl);
-sym_expr_t vcc_Eval_Var;
-sym_expr_t vcc_Eval_SymFunc;
-void vcc_Eval_Func(struct vcc *tl, const char *cfunc, const char *extra,
-    const char *name, const char *args);
-sym_expr_t vcc_Eval_Backend;
-
-/* vcc_obj.c */
-extern const struct var vcc_vars[];
-
-/* vcc_parse.c */
-void vcc_Parse(struct vcc *tl);
-
-/* vcc_storage.c */
-sym_wildcard_t vcc_Stv_Wildcard;
-
-/* vcc_utils.c */
-const char *vcc_regexp(struct vcc *tl);
-void Resolve_Sockaddr(struct vcc *tl, const char *host, const char *port, \
-    const char **ipv4, const char **ipv4_ascii, const char **ipv6, \
-    const char **ipv6_ascii, const char **p_ascii, int maxips,
-    const struct token *t_err, const char *errid);
-
-/* vcc_symb.c */
-struct symbol *VCC_AddSymbolStr(struct vcc *tl, const char *name, enum symkind);
-struct symbol *VCC_AddSymbolTok(struct vcc *tl, const struct token *t,
-    enum symkind kind);
-struct symbol *VCC_GetSymbolTok(struct vcc *tl, const struct token *tok,
-    enum symkind);
-struct symbol *VCC_FindSymbol(struct vcc *tl,
-    const struct token *t, enum symkind kind);
-const char * VCC_SymKind(struct vcc *tl, const struct symbol *s);
-typedef void symwalk_f(struct vcc *tl, const struct symbol *s);
-void VCC_WalkSymbols(struct vcc *tl, symwalk_f *func, enum symkind kind);
-
-/* vcc_token.c */
-void vcc_Coord(const struct vcc *tl, struct vsb *vsb,
-    const struct token *t);
-void vcc_ErrToken(const struct vcc *tl, const struct token *t);
-void vcc_ErrWhere(struct vcc *, const struct token *);
-void vcc_ErrWhere2(struct vcc *, const struct token *, const struct token *);
-
-void vcc__Expect(struct vcc *tl, unsigned tok, unsigned line);
-int vcc_IdIs(const struct token *t, const char *p);
-void vcc_ExpectCid(struct vcc *tl);
-void vcc_Lexer(struct vcc *tl, struct source *sp);
-void vcc_NextToken(struct vcc *tl);
-void vcc__ErrInternal(struct vcc *tl, const char *func,
-    unsigned line);
-void vcc_AddToken(struct vcc *tl, unsigned tok, const char *b,
-    const char *e);
-
-/* vcc_var.c */
-sym_wildcard_t vcc_Var_Wildcard;
-const struct var *vcc_FindVar(struct vcc *tl, const struct token *t,
-    int wr_access, const char *use);
-
-/* vcc_vmod.c */
-void vcc_ParseImport(struct vcc *tl);
-
-/* vcc_xref.c */
-int vcc_AddDef(struct vcc *tl, const struct token *t, enum symkind type);
-void vcc_AddRef(struct vcc *tl, const struct token *t, enum symkind type);
-int vcc_CheckReferences(struct vcc *tl);
-
-void vcc_AddCall(struct vcc *tl, struct token *t);
-struct proc *vcc_AddProc(struct vcc *tl, struct token *t);
-void vcc_ProcAction(struct proc *p, unsigned action, struct token *t);
-int vcc_CheckAction(struct vcc *tl);
-void vcc_AddUses(struct vcc *tl, const struct token *t, unsigned mask,
-    const char *use);
-int vcc_CheckUses(struct vcc *tl);
-
-#define ERRCHK(tl)      do { if ((tl)->err) return; } while (0)
-#define ErrInternal(tl) vcc__ErrInternal(tl, __func__, __LINE__)
-#define Expect(a, b) vcc__Expect(a, b, __LINE__)
-#define ExpectErr(a, b) \
-    do { vcc__Expect(a, b, __LINE__); ERRCHK(a);} while (0)
-#define SkipToken(a, b) \
-    do { vcc__Expect(a, b, __LINE__); ERRCHK(a); vcc_NextToken(a); } while (0)
diff --git a/lib/libvcl/vcc_expr.c b/lib/libvcl/vcc_expr.c
deleted file mode 100644
index 164a8d6..0000000
--- a/lib/libvcl/vcc_expr.c
+++ /dev/null
@@ -1,1257 +0,0 @@
-/*-
- * Copyright (c) 2006 Verdens Gang AS
- * Copyright (c) 2006-2011 Varnish Software AS
- * All rights reserved.
- *
- * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * XXX: add VRT_count()'s
- */
-
-#include "config.h"
-
-#include <math.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "vcc_compile.h"
-
-static const char *
-vcc_Type(enum var_type fmt)
-{
-	switch(fmt) {
-#define VCC_TYPE(a)	case a: return(#a);
-#include "tbl/vcc_types.h"
-#undef VCC_TYPE
-	default:
-		assert("Unknown Type");
-		return(NULL);
-	}
-}
-
-/*--------------------------------------------------------------------
- * Recognize and convert units of time, return seconds.
- */
-
-static double
-vcc_TimeUnit(struct vcc *tl)
-{
-	double sc = 1.0;
-
-	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 {
-		VSB_printf(tl->sb, "Unknown time unit ");
-		vcc_ErrToken(tl, tl->t);
-		VSB_printf(tl->sb, ".  Legal are 's', 'm', 'h' and 'd'\n");
-		vcc_ErrWhere(tl, tl->t);
-		return (1.0);
-	}
-	vcc_NextToken(tl);
-	return (sc);
-}
-
-/*--------------------------------------------------------------------
- * Recognize and convert { CNUM } to unsigned value
- * The tokenizer made sure we only get digits.
- */
-
-unsigned
-vcc_UintVal(struct vcc *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';
-	}
-	vcc_NextToken(tl);
-	return (d);
-}
-
-/*--------------------------------------------------------------------
- * Recognize and convert { CNUM [ '.' [ CNUM ] ] } to double value
- * The tokenizer made sure we only get digits and a '.'
- */
-
-static void
-vcc_NumVal(struct vcc *tl, double *d, int *frac)
-{
-	double e = 0.1;
-	const char *p;
-
-	*frac = 0;
-	*d = 0.0;
-	Expect(tl, CNUM);
-	if (tl->err) {
-		*d = NAN;
-		return;
-	}
-	for (p = tl->t->b; p < tl->t->e; p++) {
-		*d *= 10;
-		*d += *p - '0';
-	}
-	vcc_NextToken(tl);
-	if (tl->t->tok != '.')
-		return;
-	*frac = 1;
-	vcc_NextToken(tl);
-	if (tl->t->tok != CNUM)
-		return;
-	for (p = tl->t->b; p < tl->t->e; p++) {
-		*d += (*p - '0') * e;
-		e *= 0.1;
-	}
-	vcc_NextToken(tl);
-}
-
-static double
-vcc_DoubleVal(struct vcc *tl)
-{
-	double d;
-	int i;
-
-	vcc_NumVal(tl, &d, &i);
-	return (d);
-}
-
-/*--------------------------------------------------------------------*/
-
-void
-vcc_Duration(struct vcc *tl, double *d)
-{
-	double v, sc;
-
-	v = vcc_DoubleVal(tl);
-	ERRCHK(tl);
-	ExpectErr(tl, ID);
-	sc = vcc_TimeUnit(tl);
-	*d = v * sc;
-}
-
-/*--------------------------------------------------------------------*/
-
-static void
-vcc_ByteVal(struct vcc *tl, double *d)
-{
-	double v, sc;
-
-	v = vcc_DoubleVal(tl);
-	ERRCHK(tl);
-	if (tl->t->tok != ID) {
-		VSB_printf(tl->sb, "Expected BYTES unit (B, KB, MB...) got ");
-		vcc_ErrToken(tl, tl->t);
-		VSB_printf(tl->sb, "\n");
-		vcc_ErrWhere(tl, tl->t);
-		return;
-	}
-	if (vcc_IdIs(tl->t, "B"))
-		sc = 1.;
-	else if (vcc_IdIs(tl->t, "KB"))
-		sc = 1024.;
-	else if (vcc_IdIs(tl->t, "MB"))
-		sc = 1024. * 1024.;
-	else if (vcc_IdIs(tl->t, "GB"))
-		sc = 1024. * 1024. * 1024.;
-	else if (vcc_IdIs(tl->t, "TB"))
-		sc = 1024. * 1024. * 1024. * 1024.;
-	else {
-		VSB_printf(tl->sb, "Unknown BYTES unit ");
-		vcc_ErrToken(tl, tl->t);
-		VSB_printf(tl->sb,
-		    ".  Legal are 'B', 'KB', 'MB', 'GB' and 'TB'\n");
-		vcc_ErrWhere(tl, tl->t);
-		return;
-	}
-	vcc_NextToken(tl);
-	*d = v * sc;
-}
-
-/*--------------------------------------------------------------------
- * Facility for carrying expressions around and do text-processing on
- * them.
- */
-
-struct expr {
-	unsigned	magic;
-#define EXPR_MAGIC	0x38c794ab
-	enum var_type	fmt;
-	struct vsb	*vsb;
-	uint8_t		constant;
-#define EXPR_VAR	(1<<0)
-#define EXPR_CONST	(1<<1)
-#define EXPR_STR_CONST	(1<<2)
-	struct token	*t1, *t2;
-};
-
-static inline int
-vcc_isconst(const struct expr *e)
-{
-	AN(e->constant);
-	return (e->constant & EXPR_CONST);
-}
-
-static void vcc_expr0(struct vcc *tl, struct expr **e, enum var_type fmt);
-
-static struct expr *
-vcc_new_expr(void)
-{
-	struct expr *e;
-
-	/* XXX: use TlAlloc() ? */
-	ALLOC_OBJ(e, EXPR_MAGIC);
-	AN(e);
-	e->vsb = VSB_new_auto();
-	e->fmt = VOID;
-	e->constant = EXPR_VAR;
-	return (e);
-}
-
-static struct expr *
-vcc_mk_expr(enum var_type fmt, const char *str, ...)
-    __printflike(2, 3);
-
-static struct expr *
-vcc_mk_expr(enum var_type fmt, const char *str, ...)
-{
-	va_list ap;
-	struct expr *e;
-
-	e = vcc_new_expr();
-	e->fmt = fmt;
-	va_start(ap, str);
-	VSB_vprintf(e->vsb, str, ap);
-	va_end(ap);
-	AZ(VSB_finish(e->vsb));
-	return (e);
-}
-
-static void
-vcc_delete_expr(struct expr *e)
-{
-	if (e == NULL)
-		return;
-	CHECK_OBJ_NOTNULL(e, EXPR_MAGIC);
-	VSB_delete(e->vsb);
-	FREE_OBJ(e);
-}
-/*--------------------------------------------------------------------
- * We want to get the indentation right in the emitted C code so we have
- * to represent it symbolically until we are ready to render.
- *
- * Many of the operations have very schematic output syntaxes, so we
- * use the same facility to simplify the text-processing of emitting
- * a given operation on two subexpressions.
- *
- * We use '\v' as the magic escape character.
- *	\v1  insert subexpression 1
- *	\v2  insert subexpression 2
- *	\v+  increase indentation
- *	\v-  increase indentation
- *	anything else is literal
- *
- * When editing, we check if any of the subexpressions contain a newline
- * and issue it as an indented block of so.
- *
- * XXX: check line lengths in edit, should pass indent in for this
- */
-
-static struct expr *
-vcc_expr_edit(enum var_type fmt, const char *p, struct expr *e1,
-    struct expr *e2)
-{
-	struct expr *e;
-	int nl = 1;
-
-	AN(e1);
-	e = vcc_new_expr();
-	while (*p != '\0') {
-		if (*p != '\v') {
-			if (*p != '\n' || !nl)
-				VSB_putc(e->vsb, *p);
-			nl = (*p == '\n');
-			p++;
-			continue;
-		}
-		assert(*p == '\v');
-		switch(*++p) {
-		case '+': VSB_cat(e->vsb, "\v+"); break;
-		case '-': VSB_cat(e->vsb, "\v-"); break;
-		case '1':
-			VSB_cat(e->vsb, VSB_data(e1->vsb));
-			break;
-		case '2':
-			AN(e2);
-			VSB_cat(e->vsb, VSB_data(e2->vsb));
-			break;
-		default:
-			WRONG("Illegal edit in VCC expression");
-		}
-		p++;
-	}
-	AZ(VSB_finish(e->vsb));
-	e->t1 = e1->t1;
-	e->t2 = e1->t2;
-	if (e2 != NULL)
-		e->t2 = e2->t2;
-	vcc_delete_expr(e1);
-	vcc_delete_expr(e2);
-	e->fmt = fmt;
-	return (e);
-}
-
-/*--------------------------------------------------------------------
- * Expand finished expression into C-source code
- */
-
-static void
-vcc_expr_fmt(struct vsb *d, int ind, const struct expr *e1)
-{
-	char *p;
-	int i;
-
-	for (i = 0; i < ind; i++)
-		VSB_cat(d, " ");
-	p = VSB_data(e1->vsb);
-	while (*p != '\0') {
-		if (*p == '\n') {
-			VSB_putc(d, '\n');
-			if (p[1] != '\0') {
-				for (i = 0; i < ind; i++)
-					VSB_cat(d, " ");
-			}
-			p++;
-			continue;
-		}
-		if (*p != '\v') {
-			VSB_putc(d, *p);
-			p++;
-			continue;
-		}
-		p++;
-		switch(*p) {
-		case '+': ind += 2; break;
-		case '-': ind -= 2; break;
-		default:
-			WRONG("Illegal format in VCC expression");
-		}
-		p++;
-	}
-}
-
-/*--------------------------------------------------------------------
- */
-
-static enum var_type
-vcc_arg_type(const char **p)
-{
-
-#define VCC_TYPE(a) if (!strcmp(#a, *p)) { *p += strlen(#a) + 1; return (a);}
-#include "tbl/vcc_types.h"
-#undef VCC_TYPE
-	return (VOID);
-}
-
-/*--------------------------------------------------------------------
- */
-
-static void
-vcc_expr_tostring(struct expr **e, enum var_type fmt)
-{
-	const char *p;
-	uint8_t	constant = EXPR_VAR;
-
-	CHECK_OBJ_NOTNULL(*e, EXPR_MAGIC);
-	AN(fmt == STRING || fmt == STRING_LIST);
-
-	p = NULL;
-	switch((*e)->fmt) {
-	case BACKEND:	p = "VRT_BACKEND_string(\v1)"; break;
-	case BOOL:	p = "VRT_BOOL_string(\v1)"; break;
-	case DURATION:	p = "VRT_REAL_string(ctx, \v1)"; break;
-			 /* XXX: should DURATION insist on "s" suffix ? */
-	case INT:
-		if (vcc_isconst(*e)) {
-			p = "\"\v1\"";
-			constant = EXPR_CONST;
-		} else {
-			p = "VRT_INT_string(ctx, \v1)";
-		}
-		break;
-	case IP:	p = "VRT_IP_string(ctx, \v1)"; break;
-	case BYTES:	p = "VRT_REAL_string(ctx, \v1)"; break; /* XXX */
-	case REAL:	p = "VRT_REAL_string(ctx, \v1)"; break;
-	case TIME:	p = "VRT_TIME_string(ctx, \v1)"; break;
-	case HEADER:	p = "VRT_GetHdr(ctx, \v1)"; break;
-	case ENUM:
-	case STRING:
-	case STRING_LIST:
-			break;
-	default:
-			INCOMPL();
-			break;
-	}
-	if (p != NULL) {
-		*e = vcc_expr_edit(fmt, p, *e, NULL);
-		(*e)->constant = constant;
-	}
-}
-
-/*--------------------------------------------------------------------
- */
-
-static void
-vcc_Eval_Regsub(struct vcc *tl, struct expr **e, const struct symbol *sym)
-{
-	struct expr *e2;
-	int all = sym->eval_priv == NULL ? 0 : 1;
-	const char *p;
-	char buf[128];
-
-	vcc_delete_expr(*e);
-	SkipToken(tl, ID);
-	SkipToken(tl, '(');
-
-	vcc_expr0(tl, &e2, STRING);
-	if (e2 == NULL)
-		return;
-	if (e2->fmt != STRING)
-		vcc_expr_tostring(&e2, STRING);
-
-	SkipToken(tl, ',');
-	ExpectErr(tl, CSTR);
-	p = vcc_regexp(tl);
-	vcc_NextToken(tl);
-
-	bprintf(buf, "VRT_regsub(ctx, %d,\v+\n\v1,\n%s", all, p);
-	*e = vcc_expr_edit(STRING, buf, e2, *e);
-
-	SkipToken(tl, ',');
-	vcc_expr0(tl, &e2, STRING);
-	if (e2 == NULL)
-		return;
-	if (e2->fmt != STRING)
-		vcc_expr_tostring(&e2, STRING);
-	*e = vcc_expr_edit(STRING, "\v1,\n\v2)\v-", *e, e2);
-	SkipToken(tl, ')');
-}
-
-/*--------------------------------------------------------------------
- */
-
-static void
-vcc_Eval_BoolConst(struct vcc *tl, struct expr **e, const struct symbol *sym)
-{
-
-	vcc_NextToken(tl);
-	*e = vcc_mk_expr(BOOL, "(0==%d)", sym->eval_priv == NULL ? 1 : 0);
-	(*e)->constant = EXPR_CONST;
-}
-
-/*--------------------------------------------------------------------
- */
-
-void
-vcc_Eval_Backend(struct vcc *tl, struct expr **e, const struct symbol *sym)
-{
-
-	assert(sym->kind == SYM_BACKEND);
-
-	vcc_ExpectCid(tl);
-	vcc_AddRef(tl, tl->t, SYM_BACKEND);
-	*e = vcc_mk_expr(BACKEND, "VGCDIR(_%.*s)", PF(tl->t));
-	(*e)->constant = EXPR_VAR;	/* XXX ? */
-	vcc_NextToken(tl);
-}
-
-/*--------------------------------------------------------------------
- */
-void
-vcc_Eval_Var(struct vcc *tl, struct expr **e, const struct symbol *sym)
-{
-	const struct var *vp;
-
-	assert(sym->kind == SYM_VAR);
-	vcc_AddUses(tl, tl->t, sym->r_methods, "Not available");
-	vp = vcc_FindVar(tl, tl->t, 0, "cannot be read");
-	ERRCHK(tl);
-	assert(vp != NULL);
-	*e = vcc_mk_expr(vp->fmt, "%s", vp->rname);
-	vcc_NextToken(tl);
-}
-
-/*--------------------------------------------------------------------
- */
-
-static void
-vcc_func(struct vcc *tl, struct expr **e, const char *cfunc,
-    const char *extra, const char *name, const char *args)
-{
-	const char *p, *r;
-	struct expr *e1, *e2;
-	enum var_type fmt;
-	char buf[32];
-
-	AN(cfunc);
-	AN(args);
-	AN(name);
-	SkipToken(tl, '(');
-	p = args;
-	if (extra == NULL)
-		extra = "";
-	e2 = vcc_mk_expr(vcc_arg_type(&p), "%s(ctx%s\v+", cfunc, extra);
-	while (*p != '\0') {
-		e1 = NULL;
-		fmt = vcc_arg_type(&p);
-		if (fmt == VOID && !strcmp(p, "PRIV_VCL")) {
-			r = strchr(name, '.');
-			AN(r);
-			e1 = vcc_mk_expr(VOID, "&vmod_priv_%.*s",
-			    (int) (r - name), name);
-			p += strlen(p) + 1;
-		} else if (fmt == VOID && !strcmp(p, "PRIV_CALL")) {
-			bprintf(buf, "vmod_priv_%u", tl->nvmodpriv++);
-			Fh(tl, 0, "struct vmod_priv %s;\n", buf);
-			e1 = vcc_mk_expr(VOID, "&%s", buf);
-			p += strlen(p) + 1;
-		} else if (fmt == ENUM) {
-			ExpectErr(tl, ID);
-			ERRCHK(tl);
-			r = p;
-			do {
-				if (vcc_IdIs(tl->t, p))
-					break;
-				p += strlen(p) + 1;
-			} while (*p != '\0');
-			if (*p == '\0') {
-				VSB_printf(tl->sb, "Wrong enum value.");
-				VSB_printf(tl->sb, "  Expected one of:\n");
-				do {
-					VSB_printf(tl->sb, "\t%s\n", r);
-					r += strlen(r) + 1;
-				} while (*r != '\0');
-				vcc_ErrWhere(tl, tl->t);
-				return;
-			}
-			e1 = vcc_mk_expr(VOID, "\"%.*s\"", PF(tl->t));
-			while (*p != '\0')
-				p += strlen(p) + 1;
-			p++;
-			SkipToken(tl, ID);
-			if (*p != '\0')		/*lint !e448 */
-				SkipToken(tl, ',');
-		} else {
-			vcc_expr0(tl, &e1, fmt);
-			ERRCHK(tl);
-			if (e1->fmt != fmt) {
-				VSB_printf(tl->sb, "Wrong argument type.");
-				VSB_printf(tl->sb, "  Expected %s.",
-					vcc_Type(fmt));
-				VSB_printf(tl->sb, "  Got %s.\n",
-					vcc_Type(e1->fmt));
-				vcc_ErrWhere2(tl, e1->t1, tl->t);
-				return;
-			}
-			assert(e1->fmt == fmt);
-			if (e1->fmt == STRING_LIST) {
-				e1 = vcc_expr_edit(STRING_LIST,
-				    "\v+\n\v1,\nvrt_magic_string_end\v-",
-				    e1, NULL);
-			}
-			if (*p != '\0')
-				SkipToken(tl, ',');
-		}
-		e2 = vcc_expr_edit(e2->fmt, "\v1,\n\v2", e2, e1);
-	}
-	SkipToken(tl, ')');
-	e2 = vcc_expr_edit(e2->fmt, "\v1\n)\v-", e2, NULL);
-	*e = e2;
-}
-
-/*--------------------------------------------------------------------
- */
-
-void
-vcc_Eval_Func(struct vcc *tl, const char *cfunc,
-    const char *extra, const char *name, const char *args)
-{
-	struct expr *e = NULL;
-	struct token *t1;
-
-	t1 = tl->t;
-	vcc_func(tl, &e, cfunc, extra, name, args);
-	if (!tl->err) {
-		vcc_expr_fmt(tl->fb, tl->indent, e);
-		VSB_cat(tl->fb, ";\n");
-	} else if (t1 != tl->t) {
-		vcc_ErrWhere2(tl, t1, tl->t);
-	}
-	vcc_delete_expr(e);
-}
-
-/*--------------------------------------------------------------------
- */
-
-void
-vcc_Eval_SymFunc(struct vcc *tl, struct expr **e, const struct symbol *sym)
-{
-
-	assert(sym->kind == SYM_FUNC || sym->kind == SYM_PROC);
-	AN(sym->cfunc);
-	AN(sym->name);
-	AN(sym->args);
-	SkipToken(tl, ID);
-	vcc_func(tl, e, sym->cfunc, sym->extra, sym->name, sym->args);
-}
-
-/*--------------------------------------------------------------------
- * SYNTAX:
- *    Expr4:
- *	'(' Expr0 ')'
- *	CNUM
- *	CSTR
- */
-
-static void
-vcc_expr4(struct vcc *tl, struct expr **e, enum var_type fmt)
-{
-	struct expr *e1, *e2;
-	const char *ip;
-	const struct symbol *sym;
-	double d;
-
-	*e = NULL;
-	if (tl->t->tok == '(') {
-		SkipToken(tl, '(');
-		vcc_expr0(tl, &e2, fmt);
-		ERRCHK(tl);
-		SkipToken(tl, ')');
-		*e = vcc_expr_edit(e2->fmt, "(\v1)", e2, NULL);
-		return;
-	}
-	switch(tl->t->tok) {
-	case ID:
-		/*
-		 * XXX: what if var and func/proc had same name ?
-		 * XXX: look for SYM_VAR first for consistency ?
-		 */
-		sym = VCC_FindSymbol(tl, tl->t, SYM_NONE);
-		if (sym == NULL || sym->eval == NULL) {
-			VSB_printf(tl->sb, "Symbol not found: ");
-			vcc_ErrToken(tl, tl->t);
-			VSB_printf(tl->sb, " (expected type %s):\n",
-			    vcc_Type(fmt));
-			vcc_ErrWhere(tl, tl->t);
-			return;
-		}
-		AN(sym);
-		switch(sym->kind) {
-		case SYM_VAR:
-		case SYM_FUNC:
-		case SYM_BACKEND:
-			AN(sym->eval);
-			AZ(*e);
-			sym->eval(tl, e, sym);
-			return;
-		default:
-			break;
-		}
-		VSB_printf(tl->sb,
-		    "Symbol type (%s) can not be used in expression.\n",
-		    VCC_SymKind(tl, sym));
-		vcc_ErrWhere(tl, tl->t);
-		return;
-	case CSTR:
-		assert(fmt != VOID);
-		if (fmt == IP) {
-			Resolve_Sockaddr(tl, tl->t->dec, "80",
-			    &ip, NULL, &ip, NULL, NULL, 1,
-			    tl->t, "IP constant");
-			ERRCHK(tl);
-			e1 = vcc_mk_expr(IP, "%s", ip);
-			ERRCHK(tl);
-		} else {
-			e1 = vcc_new_expr();
-			EncToken(e1->vsb, tl->t);
-			e1->fmt = STRING;
-			AZ(VSB_finish(e1->vsb));
-		}
-		e1->t1 = tl->t;
-		e1->constant = EXPR_CONST;
-		vcc_NextToken(tl);
-		*e = e1;
-		break;
-	case CNUM:
-		/*
-		 * XXX: %g may not have enough decimals by default
-		 * XXX: but %a is ugly, isn't it ?
-		 */
-		assert(fmt != VOID);
-		if (fmt == DURATION) {
-			vcc_Duration(tl, &d);
-			ERRCHK(tl);
-			e1 = vcc_mk_expr(DURATION, "%g", d);
-		} else if (fmt == BYTES) {
-			vcc_ByteVal(tl, &d);
-			ERRCHK(tl);
-			e1 = vcc_mk_expr(BYTES, "%.1f", d);
-			ERRCHK(tl);
-		} else if (fmt == REAL) {
-			e1 = vcc_mk_expr(REAL, "%g", vcc_DoubleVal(tl));
-			ERRCHK(tl);
-		} else {
-			e1 = vcc_mk_expr(INT, "%.*s", PF(tl->t));
-			vcc_NextToken(tl);
-		}
-		e1->constant = EXPR_CONST;
-		*e = e1;
-		break;
-	default:
-		VSB_printf(tl->sb, "Unknown token ");
-		vcc_ErrToken(tl, tl->t);
-		VSB_printf(tl->sb, " when looking for %s\n\n", vcc_Type(fmt));
-		vcc_ErrWhere(tl, tl->t);
-		break;
-	}
-}
-
-/*--------------------------------------------------------------------
- * SYNTAX:
- *    Expr3:
- *      Expr4 { {'*'|'/'} Expr4 } *
- */
-
-static void
-vcc_expr_mul(struct vcc *tl, struct expr **e, enum var_type fmt)
-{
-	struct expr *e2;
-	enum var_type f2, f3;
-	struct token *tk;
-
-	*e = NULL;
-	vcc_expr4(tl, e, fmt);
-	ERRCHK(tl);
-	f3 = f2 = (*e)->fmt;
-
-	switch(f2) {
-	case INT:	f2 = INT; break;
-	case DURATION:	f2 = REAL; break;
-	case BYTES:	f2 = REAL; break;
-	default:
-		if (tl->t->tok != '*' && tl->t->tok != '/')
-			return;
-		VSB_printf(tl->sb, "Operator %.*s not possible on type %s.\n",
-		    PF(tl->t), vcc_Type(f2));
-		vcc_ErrWhere(tl, tl->t);
-		return;
-	}
-
-	while (tl->t->tok == '*' || tl->t->tok == '/') {
-		tk = tl->t;
-		vcc_NextToken(tl);
-		vcc_expr4(tl, &e2, f2);
-		ERRCHK(tl);
-		assert(e2->fmt == f2);
-		if (tk->tok == '*')
-			*e = vcc_expr_edit(f3, "(\v1*\v2)", *e, e2);
-		else
-			*e = vcc_expr_edit(f3, "(\v1/\v2)", *e, e2);
-	}
-}
-
-/*--------------------------------------------------------------------
- * SYNTAX:
- *    ExprAdd:
- *      ExprMul { {'+'|'-'} ExprMul } *
- *
- * For reasons of memory allocation/copying and general performance,
- * STRINGs in VCL are quite special.   Addition/concatenation is split
- * into it's own subfunction to encapsulate this.
- */
-
-static void
-vcc_expr_string_add(struct vcc *tl, struct expr **e)
-{
-	struct expr  *e2;
-	enum var_type f2;
-
-	f2 = (*e)->fmt;
-
-	while (tl->t->tok == '+') {
-		vcc_NextToken(tl);
-		vcc_expr_mul(tl, &e2, STRING);
-		ERRCHK(tl);
-		if (e2->fmt != STRING && e2->fmt != STRING_LIST)
-			vcc_expr_tostring(&e2, f2);
-		ERRCHK(tl);
-		assert(e2->fmt == STRING || e2->fmt == STRING_LIST);
-
-		if (vcc_isconst(*e) && vcc_isconst(e2)) {
-			assert((*e)->fmt == STRING);
-			assert(e2->fmt == STRING);
-			*e = vcc_expr_edit(STRING, "\v1\n\v2", *e, e2);
-			(*e)->constant = EXPR_CONST;
-		} else if (((*e)->constant & EXPR_STR_CONST) &&
-		    vcc_isconst(e2)) {
-			assert((*e)->fmt == STRING_LIST);
-			assert(e2->fmt == STRING);
-			*e = vcc_expr_edit(STRING_LIST, "\v1\n\v2", *e, e2);
-			(*e)->constant = EXPR_VAR | EXPR_STR_CONST;
-		} else if (e2->fmt == STRING && vcc_isconst(e2)) {
-			*e = vcc_expr_edit(STRING_LIST, "\v1,\n\v2", *e, e2);
-			(*e)->constant = EXPR_VAR | EXPR_STR_CONST;
-		} else {
-			*e = vcc_expr_edit(STRING_LIST, "\v1,\n\v2", *e, e2);
-			(*e)->constant = EXPR_VAR;
-		}
-	}
-}
-
-static void
-vcc_expr_add(struct vcc *tl, struct expr **e, enum var_type fmt)
-{
-	struct expr  *e2;
-	enum var_type f2;
-	struct token *tk;
-
-	*e = NULL;
-	vcc_expr_mul(tl, e, fmt);
-	ERRCHK(tl);
-	f2 = (*e)->fmt;
-
-	/* Unless we specifically ask for a HEADER, fold them to string here */
-	if (fmt != HEADER && f2 == HEADER) {
-		vcc_expr_tostring(e, STRING);
-		f2 = (*e)->fmt;
-		assert(f2 == STRING);
-	}
-
-	if (tl->t->tok != '+' && tl->t->tok != '-')
-		return;
-
-	switch(f2) {
-	case STRING:
-	case STRING_LIST:
-		vcc_expr_string_add(tl, e);
-		return;
-	case INT:		break;
-	case TIME:		break;
-	case DURATION:		break;
-	case BYTES:		break;
-	default:
-		VSB_printf(tl->sb, "Operator %.*s not possible on type %s.\n",
-		    PF(tl->t), vcc_Type(f2));
-		vcc_ErrWhere(tl, tl->t);
-		return;
-	}
-
-	while (tl->t->tok == '+' || tl->t->tok == '-') {
-		if (f2 == TIME)
-			f2 = DURATION;
-		tk = tl->t;
-		vcc_NextToken(tl);
-		vcc_expr_mul(tl, &e2, f2);
-		ERRCHK(tl);
-		if (tk->tok == '-' && (*e)->fmt == TIME && e2->fmt == TIME) {
-			/* OK */
-		} else if ((*e)->fmt == TIME && e2->fmt == DURATION) {
-			f2 = TIME;
-			/* OK */
-		} else if (tk->tok == '-' &&
-		    (*e)->fmt == BYTES && e2->fmt == BYTES) {
-			/* OK */
-		} else if (e2->fmt != f2) {
-			VSB_printf(tl->sb, "%s %.*s %s not possible.\n",
-			    vcc_Type((*e)->fmt), PF(tk), vcc_Type(e2->fmt));
-			vcc_ErrWhere2(tl, tk, tl->t);
-			return;
-		}
-		if (tk->tok == '+')
-			*e = vcc_expr_edit(f2, "(\v1+\v2)", *e, e2);
-		else if (f2 == TIME && e2->fmt == TIME)
-			*e = vcc_expr_edit(DURATION, "(\v1-\v2)", *e, e2);
-		else
-			*e = vcc_expr_edit(f2, "(\v1-\v2)", *e, e2);
-	}
-}
-
-/*--------------------------------------------------------------------
- * Fold the STRING types correctly
- */
-
-static void
-vcc_expr_strfold(struct vcc *tl, struct expr **e, enum var_type fmt)
-{
-
-	vcc_expr_add(tl, e, fmt);
-	ERRCHK(tl);
-
-	if (fmt != STRING_LIST && (*e)->fmt == STRING_LIST)
-		*e = vcc_expr_edit(STRING,
-		    "\v+VRT_CollectString(ctx,\n\v1,\nvrt_magic_string_end)\v-",
-		    *e, NULL);
-	if (fmt == STRING_LIST && (*e)->fmt == STRING)
-		(*e)->fmt = STRING_LIST;
-}
-
-/*--------------------------------------------------------------------
- * SYNTAX:
- *    ExprCmp:
- *	ExprAdd
- *      ExprAdd Relation ExprAdd
- *	ExprAdd(STRING) '~' CString
- *	ExprAdd(STRING) '!~' CString
- *	ExprAdd(IP) '~' IP
- *	ExprAdd(IP) '!~' IP
- */
-
-#define NUM_REL(typ)					\
-	{typ,		T_EQ,	"(\v1 == \v2)" },	\
-	{typ,		T_NEQ,	"(\v1 != \v2)" },	\
-	{typ,		T_LEQ,	"(\v1 <= \v2)" },	\
-	{typ,		T_GEQ,	"(\v1 >= \v2)" },	\
-	{typ,		'<',	"(\v1 < \v2)" },	\
-	{typ,		'>',	"(\v1 > \v2)" }
-
-static const struct cmps {
-	enum var_type		fmt;
-	unsigned		token;
-	const char		*emit;
-} vcc_cmps[] = {
-	NUM_REL(INT),
-	NUM_REL(DURATION),
-	NUM_REL(BYTES),
-	NUM_REL(REAL),
-
-	{STRING,	T_EQ,	"!VRT_strcmp(\v1, \v2)" },
-	{STRING,	T_NEQ,	"VRT_strcmp(\v1, \v2)" },
-
-	{VOID, 0, NULL}
-};
-
-#undef NUM_REL
-
-static void
-vcc_expr_cmp(struct vcc *tl, struct expr **e, enum var_type fmt)
-{
-	struct expr *e2;
-	const struct cmps *cp;
-	char buf[256];
-	const char *re;
-	const char *not;
-	struct token *tk;
-
-	*e = NULL;
-
-	vcc_expr_strfold(tl, e, fmt);
-	ERRCHK(tl);
-
-	if ((*e)->fmt == BOOL)
-		return;
-
-	tk = tl->t;
-	for (cp = vcc_cmps; cp->fmt != VOID; cp++)
-		if ((*e)->fmt == cp->fmt && tl->t->tok == cp->token)
-			break;
-	if (cp->fmt != VOID) {
-		vcc_NextToken(tl);
-		vcc_expr_strfold(tl, &e2, (*e)->fmt);
-		ERRCHK(tl);
-		if (e2->fmt != (*e)->fmt) { /* XXX */
-			VSB_printf(tl->sb, "Comparison of different types: ");
-			VSB_printf(tl->sb, "%s ", vcc_Type((*e)->fmt));
-			vcc_ErrToken(tl, tk);
-			VSB_printf(tl->sb, " %s\n", vcc_Type(e2->fmt));
-			vcc_ErrWhere(tl, tk);
-			return;
-		}
-		*e = vcc_expr_edit(BOOL, cp->emit, *e, e2);
-		return;
-	}
-	if ((*e)->fmt == STRING &&
-	    (tl->t->tok == '~' || tl->t->tok == T_NOMATCH)) {
-	        not = tl->t->tok == '~' ? "" : "!";
-		vcc_NextToken(tl);
-		ExpectErr(tl, CSTR);
-		re = vcc_regexp(tl);
-		ERRCHK(tl);
-		vcc_NextToken(tl);
-		bprintf(buf, "%sVRT_re_match(ctx, \v1, %s)", not, re);
-		*e = vcc_expr_edit(BOOL, buf, *e, NULL);
-		return;
-	}
-	if ((*e)->fmt == IP &&
-	    (tl->t->tok == '~' || tl->t->tok == T_NOMATCH)) {
-	        not = tl->t->tok == '~' ? "" : "!";
-		vcc_NextToken(tl);
-		ExpectErr(tl, ID);
-		vcc_AddRef(tl, tl->t, SYM_ACL);
-		bprintf(buf, "%smatch_acl_named_%.*s(ctx, \v1)",
-		    not, PF(tl->t));
-		vcc_NextToken(tl);
-		*e = vcc_expr_edit(BOOL, buf, *e, NULL);
-		return;
-	}
-	if ((*e)->fmt == IP && (tl->t->tok == T_EQ || tl->t->tok == T_NEQ)) {
-		vcc_Acl_Hack(tl, buf);
-		*e = vcc_expr_edit(BOOL, buf, *e, NULL);
-		return;
-	}
-	if ((*e)->fmt == BACKEND &&
-	    (tl->t->tok == T_EQ || tl->t->tok == T_NEQ)) {
-		vcc_NextToken(tl);
-		ExpectErr(tl, ID);
-		vcc_AddRef(tl, tl->t, SYM_BACKEND);
-		bprintf(buf, "(\v1 %.*s VGCDIR(_%.*s))", PF(tk), PF(tl->t));
-		vcc_NextToken(tl);
-		*e = vcc_expr_edit(BOOL, buf, *e, NULL);
-		return;
-	}
-	switch (tl->t->tok) {
-	case T_EQ:
-	case T_NEQ:
-	case '<':
-	case T_LEQ:
-	case '>':
-	case T_GEQ:
-	case '~':
-	case T_NOMATCH:
-		VSB_printf(tl->sb, "Operator %.*s not possible on %s\n",
-		    PF(tl->t), vcc_Type((*e)->fmt));
-		vcc_ErrWhere(tl, tl->t);
-		return;
-	default:
-		break;
-	}
-	if (fmt == BOOL && (*e)->fmt == STRING) {
-		*e = vcc_expr_edit(BOOL, "(\v1 != 0)", *e, NULL);
-		return;
-	}
-}
-
-/*--------------------------------------------------------------------
- * SYNTAX:
- *    ExprNot:
- *      '!' ExprCmp
- */
-
-static void
-vcc_expr_not(struct vcc *tl, struct expr **e, enum var_type fmt)
-{
-	struct expr *e2;
-	struct token *tk;
-
-	*e = NULL;
-	if (fmt != BOOL || tl->t->tok != '!') {
-		vcc_expr_cmp(tl, e, fmt);
-		return;
-	}
-
-	vcc_NextToken(tl);
-	tk = tl->t;
-	vcc_expr_cmp(tl, &e2, fmt);
-	ERRCHK(tl);
-	if (e2->fmt == BOOL) {
-		*e = vcc_expr_edit(BOOL, "!(\v1)", e2, NULL);
-		return;
-	}
-	VSB_printf(tl->sb, "'!' must be followed by BOOL, found ");
-	VSB_printf(tl->sb, "%s.\n", vcc_Type(e2->fmt));
-	vcc_ErrWhere2(tl, tk, tl->t);
-}
-
-/*--------------------------------------------------------------------
- * SYNTAX:
- *    ExprCand:
- *      ExprNot { '&&' ExprNot } *
- */
-
-static void
-vcc_expr_cand(struct vcc *tl, struct expr **e, enum var_type fmt)
-{
-	struct expr *e2;
-	struct token *tk;
-
-	*e = NULL;
-	vcc_expr_not(tl, e, fmt);
-	ERRCHK(tl);
-	if ((*e)->fmt != BOOL || tl->t->tok != T_CAND)
-		return;
-	*e = vcc_expr_edit(BOOL, "(\v+\n\v1", *e, NULL);
-	while (tl->t->tok == T_CAND) {
-		vcc_NextToken(tl);
-		tk = tl->t;
-		vcc_expr_not(tl, &e2, fmt);
-		ERRCHK(tl);
-		if (e2->fmt != BOOL) {
-			VSB_printf(tl->sb,
-			    "'&&' must be followed by BOOL, found ");
-			VSB_printf(tl->sb, "%s.\n", vcc_Type(e2->fmt));
-			vcc_ErrWhere2(tl, tk, tl->t);
-			return;
-		}
-		*e = vcc_expr_edit(BOOL, "\v1\v-\n&&\v+\n\v2", *e, e2);
-	}
-	*e = vcc_expr_edit(BOOL, "\v1\v-\n)", *e, NULL);
-}
-
-/*--------------------------------------------------------------------
- * SYNTAX:
- *    Expr0:
- *      ExprCand { '||' ExprCand } *
- */
-
-static void
-vcc_expr0(struct vcc *tl, struct expr **e, enum var_type fmt)
-{
-	struct expr *e2;
-	struct token *tk;
-
-	*e = NULL;
-	vcc_expr_cand(tl, e, fmt);
-	ERRCHK(tl);
-	if ((*e)->fmt != BOOL || tl->t->tok != T_COR)
-		return;
-	*e = vcc_expr_edit(BOOL, "(\v+\n\v1", *e, NULL);
-	while (tl->t->tok == T_COR) {
-		vcc_NextToken(tl);
-		tk = tl->t;
-		vcc_expr_cand(tl, &e2, fmt);
-		ERRCHK(tl);
-		if (e2->fmt != BOOL) {
-			VSB_printf(tl->sb,
-			    "'||' must be followed by BOOL, found ");
-			VSB_printf(tl->sb, "%s.\n", vcc_Type(e2->fmt));
-			vcc_ErrWhere2(tl, tk, tl->t);
-			return;
-		}
-		*e = vcc_expr_edit(BOOL, "\v1\v-\n||\v+\n\v2", *e, e2);
-	}
-	*e = vcc_expr_edit(BOOL, "\v1\v-\n)", *e, NULL);
-}
-
-/*--------------------------------------------------------------------
- * This function parses and emits the C-code to evaluate an expression
- *
- * We know up front what kind of type we want the expression to be,
- * and this function is the backstop if that doesn't succeed.
- */
-
-void
-vcc_Expr(struct vcc *tl, enum var_type fmt)
-{
-	struct expr *e;
-	struct token *t1;
-
-	assert(fmt != VOID);
-
-	t1 = tl->t;
-	vcc_expr0(tl, &e, fmt);
-	ERRCHK(tl);
-	if (fmt == STRING || fmt == STRING_LIST)
-		vcc_expr_tostring(&e, fmt);
-	if (!tl->err && fmt != e->fmt)  {
-		VSB_printf(tl->sb, "Expression has type %s, expected %s\n",
-		    vcc_Type(e->fmt), vcc_Type(fmt));
-		tl->err = 1;
-	}
-	if (!tl->err) {
-		if (e->fmt == STRING_LIST) {
-			e = vcc_expr_edit(STRING_LIST,
-			    "\v+\n\v1,\nvrt_magic_string_end\v-", e, NULL);
-		}
-		vcc_expr_fmt(tl->fb, tl->indent, e);
-		VSB_putc(tl->fb, '\n');
-	} else {
-		if (t1 != tl->t)
-			vcc_ErrWhere2(tl, t1, tl->t);
-	}
-	vcc_delete_expr(e);
-}
-
-/*--------------------------------------------------------------------
- */
-
-void
-vcc_Expr_Call(struct vcc *tl, const struct symbol *sym)
-{
-
-	struct expr *e;
-	struct token *t1;
-
-	t1 = tl->t;
-	e = NULL;
-	vcc_Eval_SymFunc(tl, &e, sym);
-	if (!tl->err) {
-		vcc_expr_fmt(tl->fb, tl->indent, e);
-		VSB_cat(tl->fb, ";\n");
-	} else if (t1 != tl->t) {
-		vcc_ErrWhere2(tl, t1, tl->t);
-	}
-	vcc_delete_expr(e);
-}
-
-/*--------------------------------------------------------------------
- */
-
-void
-vcc_Expr_Init(struct vcc *tl)
-{
-	struct symbol *sym;
-
-	sym = VCC_AddSymbolStr(tl, "regsub", SYM_FUNC);
-	AN(sym);
-	sym->eval = vcc_Eval_Regsub;
-	sym->eval_priv = NULL;
-
-	sym = VCC_AddSymbolStr(tl, "regsuball", SYM_FUNC);
-	AN(sym);
-	sym->eval = vcc_Eval_Regsub;
-	sym->eval_priv = sym;
-
-	sym = VCC_AddSymbolStr(tl, "true", SYM_FUNC);
-	AN(sym);
-	sym->eval = vcc_Eval_BoolConst;
-	sym->eval_priv = sym;
-
-	sym = VCC_AddSymbolStr(tl, "false", SYM_FUNC);
-	AN(sym);
-	sym->eval = vcc_Eval_BoolConst;
-	sym->eval_priv = NULL;
-}
diff --git a/lib/libvcl/vcc_parse.c b/lib/libvcl/vcc_parse.c
deleted file mode 100644
index ab562f5..0000000
--- a/lib/libvcl/vcc_parse.c
+++ /dev/null
@@ -1,359 +0,0 @@
-/*-
- * Copyright (c) 2006 Verdens Gang AS
- * Copyright (c) 2006-2013 Varnish Software AS
- * All rights reserved.
- *
- * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#include <stdio.h>
-#include <string.h>
-
-#include "vcc_compile.h"
-
-/*--------------------------------------------------------------------*/
-
-static void vcc_Compound(struct vcc *tl);
-
-/*--------------------------------------------------------------------*/
-
-#define L(tl, foo)	do {	\
-	tl->indent += INDENT;	\
-	foo;			\
-	tl->indent -= INDENT;	\
-} while (0)
-
-#define C(tl, sep)	do {					\
-	Fb(tl, 1, "VRT_count(ctx, %u)%s\n", ++tl->cnt, sep);	\
-	tl->t->cnt = tl->cnt;					\
-} while (0)
-
-/*--------------------------------------------------------------------
- * SYNTAX:
- *    Conditional:
- *	'(' Cond_0 ')'
- */
-
-static void
-vcc_Conditional(struct vcc *tl)
-{
-
-	SkipToken(tl, '(');
-	Fb(tl, 0, "(\n");
-	L(tl, vcc_Expr(tl, BOOL));
-	ERRCHK(tl);
-	Fb(tl, 1, ")\n");
-	SkipToken(tl, ')');
-}
-
-/*--------------------------------------------------------------------
- * SYNTAX:
- *    IfStmt:
- *	'if' Conditional  Compound Branch1* Branch2
- *    Branch1:
- *      'elseif' Conditional Compound
- *    Branch2:
- *      'else' Compound
- *	null
- */
-
-static void
-vcc_IfStmt(struct vcc *tl)
-{
-
-	SkipToken(tl, ID);
-	Fb(tl, 1, "if ");
-	vcc_Conditional(tl);
-	ERRCHK(tl);
-	L(tl, vcc_Compound(tl));
-	ERRCHK(tl);
-	while (tl->t->tok == ID) {
-		if (vcc_IdIs(tl->t, "else")) {
-			vcc_NextToken(tl);
-			if (tl->t->tok == '{') {
-				Fb(tl, 1, "else\n");
-				L(tl, vcc_Compound(tl));
-				ERRCHK(tl);
-				return;
-			}
-			if (tl->t->tok != ID || !vcc_IdIs(tl->t, "if")) {
-				VSB_printf(tl->sb,
-				    "'else' must be followed by 'if' or '{'\n");
-				vcc_ErrWhere(tl, tl->t);
-				return;
-			}
-			Fb(tl, 1, "else if ");
-			vcc_NextToken(tl);
-			vcc_Conditional(tl);
-			ERRCHK(tl);
-			L(tl, vcc_Compound(tl));
-			ERRCHK(tl);
-		} else if (vcc_IdIs(tl->t, "elseif") ||
-		     vcc_IdIs(tl->t, "elsif") ||
-		     vcc_IdIs(tl->t, "elif")) {
-			Fb(tl, 1, "else if ");
-			vcc_NextToken(tl);
-			vcc_Conditional(tl);
-			ERRCHK(tl);
-			L(tl, vcc_Compound(tl));
-			ERRCHK(tl);
-		} else {
-			break;
-		}
-	}
-	C(tl, ";");
-}
-
-/*--------------------------------------------------------------------
- * SYNTAX:
- *    Compound:
- *	'{' Stmt* '}'
- *
- *    Stmt:
- *	Compound
- *	IfStmt
- *	CSRC
- *	Id(Action) (XXX)
- */
-
-static void
-vcc_Compound(struct vcc *tl)
-{
-	int i;
-
-	SkipToken(tl, '{');
-	Fb(tl, 1, "{\n");
-	tl->indent += INDENT;
-	C(tl, ";");
-	while (1) {
-		ERRCHK(tl);
-		switch (tl->t->tok) {
-		case '{':
-			vcc_Compound(tl);
-			break;
-		case '}':
-			vcc_NextToken(tl);
-			tl->indent -= INDENT;
-			Fb(tl, 1, "}\n");
-			return;
-		case CSRC:
-			if (tl->allow_inline_c) {
-				Fb(tl, 1, "%.*s\n",
-				    (int) (tl->t->e - (tl->t->b + 2)),
-				    tl->t->b + 1);
-				vcc_NextToken(tl);
-			} else {
-				VSB_printf(tl->sb,
-				    "Inline-C not allowed\n");
-				vcc_ErrWhere(tl, tl->t);
-			}
-			break;
-		case EOI:
-			VSB_printf(tl->sb,
-			    "End of input while in compound statement\n");
-			tl->err = 1;
-			return;
-		case ID:
-			if (vcc_IdIs(tl->t, "if")) {
-				vcc_IfStmt(tl);
-				break;
-			} else {
-				i = vcc_ParseAction(tl);
-				ERRCHK(tl);
-				if (i) {
-					SkipToken(tl, ';');
-					break;
-				}
-			}
-			/* FALLTHROUGH */
-		default:
-			/* We deliberately do not mention inline C */
-			VSB_printf(tl->sb,
-			    "Expected an action, 'if', '{' or '}'\n");
-			vcc_ErrWhere(tl, tl->t);
-			return;
-		}
-	}
-}
-
-/*--------------------------------------------------------------------
- * SYNTAX:
- *    Function:
- *	'sub' ID(name) Compound
- */
-
-static void
-vcc_Function(struct vcc *tl)
-{
-	int m, i;
-
-	vcc_NextToken(tl);
-	ExpectErr(tl, ID);
-	if (!vcc_isCid(tl->t)) {
-		VSB_printf(tl->sb,
-		    "Names of VCL sub's cannot contain '-'\n");
-		vcc_ErrWhere(tl, tl->t);
-		return;
-	}
-
-	m = IsMethod(tl->t);
-	if (m == -2) {
-		VSB_printf(tl->sb,
-		    "VCL sub's named 'vcl*' are reserved names.\n");
-		vcc_ErrWhere(tl, tl->t);
-		VSB_printf(tl->sb, "Valid vcl_* methods are:\n");
-		for (i = 0; method_tab[i].name != NULL; i++)
-			VSB_printf(tl->sb, "\t%s\n", method_tab[i].name);
-		return;
-	} else if (m != -1) {
-		assert(m < VCL_MET_MAX);
-		tl->fb = tl->fm[m];
-		if (tl->mprocs[m] == NULL) {
-			(void)vcc_AddDef(tl, tl->t, SYM_SUB);
-			vcc_AddRef(tl, tl->t, SYM_SUB);
-			tl->mprocs[m] = vcc_AddProc(tl, tl->t);
-		}
-		tl->curproc = tl->mprocs[m];
-		Fb(tl, 1, "  /* ... from ");
-		vcc_Coord(tl, tl->fb, NULL);
-		Fb(tl, 0, " */\n");
-	} else {
-		tl->fb = tl->fc;
-		i = vcc_AddDef(tl, tl->t, SYM_SUB);
-		if (i > 1) {
-			VSB_printf(tl->sb,
-			    "Function %.*s redefined\n", PF(tl->t));
-			vcc_ErrWhere(tl, tl->t);
-			return;
-		}
-		tl->curproc = vcc_AddProc(tl, tl->t);
-		Fh(tl, 0, "static int VGC_function_%.*s "
-		    "(struct vrt_ctx *ctx);\n", PF(tl->t));
-		Fc(tl, 1, "\nstatic int __match_proto__(vcl_func_t)\n");
-		Fc(tl, 1, "VGC_function_%.*s(struct vrt_ctx *ctx)\n",
-		    PF(tl->t));
-	}
-	vcc_NextToken(tl);
-	tl->indent += INDENT;
-	Fb(tl, 1, "{\n");
-	L(tl, vcc_Compound(tl));
-	if (m == -1) {
-		/*
-		 * non-method subroutines must have an explicit non-action
-		 * return in case they just fall through the bottom.
-		 */
-		Fb(tl, 1, "  return(0);\n");
-	}
-	Fb(tl, 1, "}\n");
-	tl->indent -= INDENT;
-	tl->fb = NULL;
-	tl->curproc = NULL;
-}
-
-/*--------------------------------------------------------------------
- */
-
-static void
-vcc_Director(struct vcc *tl)
-{
-	VSB_printf(tl->sb, "\ndirectors are now in directors VMOD.\n");
-	vcc_ErrWhere(tl, tl->t);
-}
-
-/*--------------------------------------------------------------------
- * Top level of parser, recognize:
- *	Inline C-code
- *	ACL definitions
- *	Function definitions
- *	Backend & Director definitions
- *	End of input
- */
-
-typedef void parse_f(struct vcc *tl);
-
-static struct toplev {
-	const char	*name;
-	parse_f		*func;
-} toplev[] = {
-	{ "acl",		vcc_Acl },
-	{ "sub",		vcc_Function },
-	{ "backend",		vcc_ParseBackend },
-	{ "director",		vcc_Director },
-	{ "probe",		vcc_ParseProbe },
-	{ "import",		vcc_ParseImport },
-	{ NULL, NULL }
-};
-
-void
-vcc_Parse(struct vcc *tl)
-{
-	struct toplev *tp;
-
-	while (tl->t->tok != EOI) {
-		ERRCHK(tl);
-		switch (tl->t->tok) {
-		case CSRC:
-			if (tl->allow_inline_c) {
-				Fc(tl, 0, "%.*s\n",
-				    (int) (tl->t->e - (tl->t->b + 4)),
-				    tl->t->b + 2);
-				vcc_NextToken(tl);
-			} else {
-				VSB_printf(tl->sb,
-				    "Inline-C not allowed\n");
-				vcc_ErrWhere(tl, tl->t);
-			}
-			break;
-		case EOI:
-			break;
-		case ID:
-			for (tp = toplev; tp->name != NULL; tp++) {
-				if (!vcc_IdIs(tl->t, tp->name))
-					continue;
-				tp->func(tl);
-				break;
-			}
-			if (tp->name != NULL)
-				break;
-			/* FALLTHROUGH */
-		default:
-			/* We deliberately do not mention inline-C */
-			VSB_printf(tl->sb, "Expected one of\n\t");
-			for (tp = toplev; tp->name != NULL; tp++) {
-				if (tp[1].name == NULL)
-					VSB_printf(tl->sb, " or ");
-				VSB_printf(tl->sb, "'%s'", tp->name);
-				if (tp[1].name != NULL)
-					VSB_printf(tl->sb, ", ");
-			}
-			VSB_printf(tl->sb, "\nFound: ");
-			vcc_ErrToken(tl, tl->t);
-			VSB_printf(tl->sb, " at\n");
-			vcc_ErrWhere(tl, tl->t);
-			return;
-		}
-	}
-}
diff --git a/lib/libvcl/vcc_storage.c b/lib/libvcl/vcc_storage.c
deleted file mode 100644
index 5f9712a..0000000
--- a/lib/libvcl/vcc_storage.c
+++ /dev/null
@@ -1,149 +0,0 @@
-/*-
- * Copyright (c) 2010 Varnish Software AS
- * All rights reserved.
- *
- * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * All stuff related to the storage.* part of the namespace.
- *
- * "All" is actually only a wildcard function, which instantiates variables
- * on demand under the storage.* tree of the namespace.
- *
- * About the syntax:
- * -----------------
- *
- * One of our long term goals is to have dynamic storage configuration, such
- * as the ability to add or remove a stevedore on the fly, without restarting
- * the worker process.
- *
- * Even though this goal is far out in the future, it influences the syntax
- * design of storage selection from VCL.
- *
- * In difference from backends, where we know the possible set of backends at
- * compile time, we will not in the future know the identity of the stevedores
- * available at compile time, so we have to rely on VRT name resolution.
- *
- * This indicates a namespace on the form storage.<stevedore>.<property>
- *
- * For each property, we must define a default value if the named stevedore
- * does not exists, such that for instance stevedore.forgetit.freespace
- * returns zero etc.
- *
- */
-
-#include "config.h"
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "vcc_compile.h"
-
-#define PFX "storage."
-
-/*--------------------------------------------------------------------
- *
- */
-
-static struct var *
-vcc_Stv_mkvar(struct vcc *tl, const struct token *t, enum var_type fmt)
-{
-	struct var *v;
-
-	v = TlAlloc(tl, sizeof *v);
-	AN(v);
-
-	v->name = TlDupTok(tl, t);
-	v->r_methods = 0
-#define VCL_MET_MAC(l,u,b)	| VCL_MET_##u
-#include "tbl/vcl_returns.h"
-#undef VCL_MET_MAC
-		;
-	v->fmt = fmt;
-
-	return (v);
-}
-
-static struct stvars {
-	const char	*name;
-	enum var_type	fmt;
-} stvars[] = {
-#define VRTSTVVAR(nm, vtype, ctype, dval)	{ #nm, vtype },
-#include "tbl/vrt_stv_var.h"
-#undef VRTSTVVAR
-	{ NULL,			BOOL }
-};
-
-struct symbol *
-vcc_Stv_Wildcard(struct vcc *tl, const struct token *t,
-    const struct symbol *wcsym)
-{
-	const char *p, *q;
-	struct var *v = NULL;
-	struct symbol *sym;
-	struct stvars *sv;
-	char stv[1024];
-	char buf[1024];
-
-	(void)wcsym;
-	assert((t->e - t->b) > strlen(PFX));
-	assert(!memcmp(t->b, PFX, strlen(PFX)));
-
-	p = t->b + strlen(PFX);
-	for (q = p; q < t->e && *q != '.'; q++)
-		continue;
-	bprintf(stv, "%.*s", (int)(q - p), p);
-
-	if (q == t->e) {
-		v = vcc_Stv_mkvar(tl, t, BOOL);
-		bprintf(buf, "VRT_Stv(\"%s\")", stv);
-		v->rname = TlDup(tl, buf);
-	} else {
-		assert(*q  == '.');
-		q++;
-		for(sv = stvars; sv->name != NULL; sv++) {
-			if (strncmp(q, sv->name, t->e - q))
-				continue;
-			if (sv->name[t->e - q] != '\0')
-				continue;
-			v = vcc_Stv_mkvar(tl, t, sv->fmt);
-			bprintf(buf, "VRT_Stv_%s(\"%s\")", sv->name, stv);
-			v->rname = TlDup(tl, buf);
-			break;
-		}
-	}
-
-	if (v == NULL)
-		return (NULL);
-
-	sym = VCC_AddSymbolTok(tl, t, SYM_VAR);
-	AN(sym);
-	sym->var = v;
-	sym->fmt = v->fmt;
-	sym->eval = vcc_Eval_Var;
-	sym->r_methods = v->r_methods;
-
-	return (sym);
-}
diff --git a/lib/libvcl/vcc_symb.c b/lib/libvcl/vcc_symb.c
deleted file mode 100644
index c3d8a13..0000000
--- a/lib/libvcl/vcc_symb.c
+++ /dev/null
@@ -1,142 +0,0 @@
-/*-
- * Copyright (c) 2010 Varnish Software AS
- * All rights reserved.
- *
- * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "vcc_compile.h"
-
-/*--------------------------------------------------------------------*/
-
-const char *
-VCC_SymKind(struct vcc *tl, const struct symbol *s)
-{
-	switch(s->kind) {
-#define VCC_SYMB(uu, ll)	case SYM_##uu: return(#ll);
-#include "tbl/symbol_kind.h"
-#undef VCC_SYMB
-	default:
-		ErrInternal(tl);
-		VSB_printf(tl->sb, "Symbol Kind 0x%x\n", s->kind);
-		return("INTERNALERROR");
-	}
-}
-
-
-static struct symbol *
-vcc_AddSymbol(struct vcc *tl, const char *nb, int l, enum symkind kind)
-{
-	struct symbol *sym;
-
-	VTAILQ_FOREACH(sym, &tl->symbols, list) {
-		if (sym->nlen != l)
-			continue;
-		if (memcmp(nb, sym->name, l))
-			continue;
-		if (kind != sym->kind)
-			continue;
-		VSB_printf(tl->sb, "Name Collision: <%.*s> <%s>\n",
-		    l, nb, VCC_SymKind(tl, sym));
-		ErrInternal(tl);
-		return (NULL);
-	}
-	ALLOC_OBJ(sym, SYMBOL_MAGIC);
-	AN(sym);
-	sym->name = malloc(l + 1L);
-	AN(sym->name);
-	memcpy(sym->name, nb, l);
-	sym->name[l] = '\0';
-	sym->nlen = l;
-	VTAILQ_INSERT_HEAD(&tl->symbols, sym, list);
-	sym->kind = kind;
-	return (sym);
-}
-
-struct symbol *
-VCC_AddSymbolStr(struct vcc *tl, const char *name, enum symkind kind)
-{
-
-	return (vcc_AddSymbol(tl, name, strlen(name), kind));
-}
-
-struct symbol *
-VCC_AddSymbolTok(struct vcc *tl, const struct token *t, enum symkind kind)
-{
-
-	return (vcc_AddSymbol(tl, t->b, t->e - t->b, kind));
-}
-
-struct symbol *
-VCC_GetSymbolTok(struct vcc *tl, const struct token *tok, enum symkind kind)
-{
-	struct symbol *sym;
-
-	sym = VCC_FindSymbol(tl, tok, kind);
-	if (sym == NULL) {
-		sym = vcc_AddSymbol(tl, tok->b, tok->e - tok->b, kind);
-		AN(sym);
-		sym->def_b = tok;
-	}
-	return (sym);
-}
-
-struct symbol *
-VCC_FindSymbol(struct vcc *tl, const struct token *t, enum symkind kind)
-{
-	struct symbol *sym;
-
-	assert(t->tok == ID);
-	VTAILQ_FOREACH(sym, &tl->symbols, list) {
-		if (sym->kind == SYM_WILDCARD &&
-		   (t->e - t->b > sym->nlen) &&
-		   !memcmp(sym->name, t->b, sym->nlen)) {
-			AN(sym->wildcard);
-			return (sym->wildcard(tl, t, sym));
-		}
-		if (kind != SYM_NONE && kind != sym->kind)
-			continue;
-		if (vcc_IdIs(t, sym->name))
-			return (sym);
-	}
-	return (NULL);
-}
-
-void
-VCC_WalkSymbols(struct vcc *tl, symwalk_f *func, enum symkind kind)
-{
-	struct symbol *sym;
-
-	VTAILQ_FOREACH(sym, &tl->symbols, list) {
-		if (kind == SYM_NONE || kind == sym->kind)
-			func(tl, sym);
-		ERRCHK(tl);
-	}
-}
diff --git a/lib/libvcl/vcc_token.c b/lib/libvcl/vcc_token.c
deleted file mode 100644
index 6201fea..0000000
--- a/lib/libvcl/vcc_token.c
+++ /dev/null
@@ -1,523 +0,0 @@
-/*-
- * Copyright (c) 2006 Verdens Gang AS
- * Copyright (c) 2006-2011 Varnish Software AS
- * All rights reserved.
- *
- * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#include <ctype.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "vcc_compile.h"
-
-/*--------------------------------------------------------------------*/
-
-void
-vcc_ErrToken(const struct vcc *tl, const struct token *t)
-{
-
-	if (t->tok == EOI)
-		VSB_printf(tl->sb, "end of input");
-	else if (t->tok == CSRC)
-		VSB_printf(tl->sb, "C{ ... }C");
-	else
-		VSB_printf(tl->sb, "'%.*s'", PF(t));
-}
-
-void
-vcc__ErrInternal(struct vcc *tl, const char *func, unsigned line)
-{
-
-	VSB_printf(tl->sb, "VCL compiler internal error at %s():%u\n",
-	    func, line);
-	tl->err = 1;
-}
-
-/*--------------------------------------------------------------------
- * Find start of source-line of token
- */
-
-static void
-vcc_iline(const struct token *t, const char **ll, int tail)
-{
-	const char *p, *b, *x;
-
-	b = t->src->b;
-	if (ll != NULL)
-		*ll = b;
-	x = tail ? t->e - 1 : t->b;
-	for (p = b; p < x; p++) {
-		if (*p == '\n') {
-			if (ll != NULL)
-				*ll = p + 1;
-		}
-	}
-}
-
-/*--------------------------------------------------------------------
- * Find and print src+line+pos of this token
- */
-
-static void
-vcc_icoord(struct vsb *vsb, const struct token *t, int tail)
-{
-	unsigned lin, pos;
-	const char *p, *b, *x;
-
-	lin = 1;
-	pos = 0;
-	b = t->src->b;
-	x = tail ? t->e - 1 : t->b;
-	for (p = b; p < x; p++) {
-		if (*p == '\n') {
-			lin++;
-			pos = 0;
-		} else if (*p == '\t') {
-			pos &= ~7;
-			pos += 8;
-		} else
-			pos++;
-	}
-	VSB_printf(vsb, "('%s' Line %u Pos %u)", t->src->name, lin, pos + 1);
-}
-
-/*--------------------------------------------------------------------*/
-
-void
-vcc_Coord(const struct vcc *tl, struct vsb *vsb, const struct token *t)
-{
-
-	if (t == NULL)
-		t = tl->t;
-	vcc_icoord(vsb, t, 0);
-}
-
-/*--------------------------------------------------------------------
- * Output one line of source code, starting at 'l' and ending at the
- * first NL or 'le'.
- */
-
-static void
-vcc_quoteline(const struct vcc *tl, const char *l, const char *le)
-{
-	const char *p;
-	unsigned x, y;
-
-	x = y = 0;
-	for (p = l; p < le && *p != '\n'; p++) {
-		if (*p == '\t') {
-			y &= ~7;
-			y += 8;
-			while (x < y) {
-				VSB_bcat(tl->sb, " ", 1);
-				x++;
-			}
-		} else {
-			x++;
-			y++;
-			VSB_bcat(tl->sb, p, 1);
-		}
-	}
-	VSB_putc(tl->sb, '\n');
-}
-
-/*--------------------------------------------------------------------
- * Output a marker line for a sourceline starting at 'l' and ending at
- * the first NL or 'le'.  Characters between 'b' and 'e' are marked.
- */
-
-static void
-vcc_markline(const struct vcc *tl, const char *l, const char *le,
-    const char *b, const char *e)
-{
-	const char *p;
-	unsigned x, y;
-	char c;
-
-	x = y = 0;
-	for (p = l; p < le && *p != '\n'; p++) {
-		if (p >= b && p < e)
-			c = '#';
-		else
-			c = '-';
-
-		if (*p == '\t') {
-			y &= ~7;
-			y += 8;
-		} else
-			y++;
-		while (x < y) {
-			VSB_putc(tl->sb, c);
-			x++;
-		}
-	}
-	VSB_putc(tl->sb, '\n');
-}
-
-/*--------------------------------------------------------------------*/
-/* XXX: should take first+last token */
-
-void
-vcc_ErrWhere2(struct vcc *tl, const struct token *t, const struct token *t2)
-{
-	const char  *l1, *l2, *l3;
-
-	if (t == NULL) {
-		vcc_ErrWhere(tl, t2);
-		return;
-	}
-	vcc_iline(t, &l1, 0);
-	t2 = VTAILQ_PREV(t2, tokenhead, list);
-	vcc_iline(t2, &l2, 1);
-
-
-	if (l1 == l2) {
-		vcc_icoord(tl->sb, t, 0);
-		VSB_cat(tl->sb, " -- ");
-		vcc_icoord(tl->sb, t2, 1);
-		VSB_putc(tl->sb, '\n');
-		/* Two tokens on same line */
-		vcc_quoteline(tl, l1, t->src->e);
-		vcc_markline(tl, l1, t->src->e, t->b, t2->e);
-	} else {
-		/* Two tokens different lines */
-		l3 = strchr(l1, '\n');
-		AN(l3);
-		/* XXX: t had better be before t2 */
-		vcc_icoord(tl->sb, t, 0);
-		if (l3 + 1 == l2) {
-			VSB_cat(tl->sb, " -- ");
-			vcc_icoord(tl->sb, t2, 1);
-		}
-		VSB_putc(tl->sb, '\n');
-		vcc_quoteline(tl, l1, t->src->e);
-		vcc_markline(tl, l1, t->src->e, t->b, t2->e);
-		if (l3 + 1 != l2) {
-			VSB_cat(tl->sb, "[...]\n");
-			vcc_icoord(tl->sb, t2, 1);
-			VSB_putc(tl->sb, '\n');
-		}
-		vcc_quoteline(tl, l2, t->src->e);
-		vcc_markline(tl, l2, t->src->e, t->b, t2->e);
-	}
-	VSB_putc(tl->sb, '\n');
-	tl->err = 1;
-}
-
-void
-vcc_ErrWhere(struct vcc *tl, const struct token *t)
-{
-	const char  *l1;
-
-	vcc_iline(t, &l1, 0);
-	vcc_icoord(tl->sb, t, 0);
-	VSB_putc(tl->sb, '\n');
-	vcc_quoteline(tl, l1, t->src->e);
-	vcc_markline(tl, l1, t->src->e, t->b, t->e);
-	VSB_putc(tl->sb, '\n');
-	tl->err = 1;
-}
-
-/*--------------------------------------------------------------------*/
-
-void
-vcc_NextToken(struct vcc *tl)
-{
-
-	tl->t = VTAILQ_NEXT(tl->t, list);
-	if (tl->t == NULL) {
-		VSB_printf(tl->sb,
-		    "Ran out of input, something is missing or"
-		    " maybe unbalanced (...) or {...}\n");
-		tl->err = 1;
-		return;
-	}
-}
-
-void
-vcc__Expect(struct vcc *tl, unsigned tok, unsigned line)
-{
-	if (tl->t->tok == tok)
-		return;
-	VSB_printf(tl->sb, "Expected %s got ", vcl_tnames[tok]);
-	vcc_ErrToken(tl, tl->t);
-	VSB_printf(tl->sb, "\n(program line %u), at\n", line);
-	vcc_ErrWhere(tl, tl->t);
-}
-
-/*--------------------------------------------------------------------
- * Compare ID token to string, return true of match
- */
-
-int
-vcc_IdIs(const 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);
-}
-
-/*--------------------------------------------------------------------
- * Check that we have a C-identifier
- */
-
-int
-vcc_isCid(const struct token *t)
-{
-	const char *q;
-
-	assert(t->tok == ID);
-	for (q = t->b; q < t->e; q++) {
-		if (!isalnum(*q) && *q != '_')
-			return (0);
-	}
-	return (1);
-}
-
-void
-vcc_ExpectCid(struct vcc *tl)
-{
-
-	ExpectErr(tl, ID);
-	ERRCHK(tl);
-	if (vcc_isCid(tl->t))
-		return;
-	VSB_printf(tl->sb, "Identifier ");
-	vcc_ErrToken(tl, tl->t);
-	VSB_printf(tl->sb,
-	    " contains illegal characters, use [0-9a-zA-Z_] only.\n");
-	vcc_ErrWhere(tl, tl->t);
-}
-
-/*--------------------------------------------------------------------
- * Decode a string
- */
-
-static int
-vcc_decstr(struct vcc *tl)
-{
-	char *q;
-	unsigned int l;
-
-	assert(tl->t->tok == CSTR);
-	l = (tl->t->e - tl->t->b) - 2;
-	tl->t->dec = TlAlloc(tl, l + 1);
-	assert(tl->t->dec != NULL);
-	q = tl->t->dec;
-	memcpy(q, tl->t->b + 1, l);
-	q[l] = '\0';
-	return (0);
-}
-
-/*--------------------------------------------------------------------
- * Add a token to the token list.
- */
-
-void
-vcc_AddToken(struct vcc *tl, unsigned tok, const char *b, const char *e)
-{
-	struct token *t;
-
-	t = TlAlloc(tl, sizeof *t);
-	assert(t != NULL);
-	t->tok = tok;
-	t->b = b;
-	t->e = e;
-	t->src = tl->src;
-	if (tl->t != NULL)
-		VTAILQ_INSERT_AFTER(&tl->tokens, tl->t, t, list);
-	else
-		VTAILQ_INSERT_TAIL(&tl->tokens, t, list);
-	tl->t = t;
-}
-
-/*--------------------------------------------------------------------
- * Lexical analysis and token generation
- */
-
-void
-vcc_Lexer(struct vcc *tl, struct source *sp)
-{
-	const char *p, *q;
-	unsigned u;
-
-	tl->src = sp;
-	for (p = sp->b; p < sp->e; ) {
-
-		/* Skip any whitespace */
-		if (isspace(*p)) {
-			p++;
-			continue;
-		}
-
-		/* Skip '#.*\n' comments */
-		if (*p == '#') {
-			while (p < sp->e && *p != '\n')
-				p++;
-			continue;
-		}
-
-		/* Skip C-style comments */
-		if (*p == '/' && p[1] == '*') {
-			for (q = p + 2; q < sp->e; q++) {
-				if (*q == '/' && q[1] == '*') {
-					VSB_printf(tl->sb,
-					    "/* ... */ comment contains /*\n");
-					vcc_AddToken(tl, EOI, p, p + 2);
-					vcc_ErrWhere(tl, tl->t);
-					vcc_AddToken(tl, EOI, q, q + 2);
-					vcc_ErrWhere(tl, tl->t);
-					return;
-				}
-				if (*q == '*' && q[1] == '/') {
-					p = q + 2;
-					break;
-				}
-			}
-			if (q < sp->e)
-				continue;
-			vcc_AddToken(tl, EOI, p, p + 2);
-			VSB_printf(tl->sb,
-			    "Unterminated /* ... */ comment, starting at\n");
-			vcc_ErrWhere(tl, tl->t);
-			return;
-		}
-
-		/* Skip C++-style comments */
-		if (*p == '/' && p[1] == '/') {
-			while (p < sp->e && *p != '\n')
-				p++;
-			continue;
-		}
-
-		/* Recognize inline C-code */
-		if (*p == 'C' && p[1] == '{') {
-			for (q = p + 2; q < sp->e; q++) {
-				if (*q == '}' && q[1] == 'C') {
-					vcc_AddToken(tl, CSRC, p, q + 2);
-					break;
-				}
-			}
-			if (q < sp->e) {
-				p = q + 2;
-				continue;
-			}
-			vcc_AddToken(tl, EOI, p, p + 2);
-			VSB_printf(tl->sb,
-			    "Unterminated inline C source, starting at\n");
-			vcc_ErrWhere(tl, tl->t);
-			return;
-		}
-
-		/* Recognize long-strings */
-		if (*p == '{' && p[1] == '"') {
-			for (q = p + 2; q < sp->e; q++) {
-				if (*q == '"' && q[1] == '}') {
-					vcc_AddToken(tl, CSTR, p, q + 2);
-					break;
-				}
-			}
-			if (q < sp->e) {
-				p = q + 2;
-				u = tl->t->e - tl->t->b;
-				u -= 4;		/* {" ... "} */
-				tl->t->dec = TlAlloc(tl, u + 1 );
-				AN(tl->t->dec);
-				memcpy(tl->t->dec, tl->t->b + 2, u);
-				tl->t->dec[u] = '\0';
-				continue;
-			}
-			vcc_AddToken(tl, EOI, p, p + 2);
-			VSB_printf(tl->sb,
-			    "Unterminated long-string, starting at\n");
-			vcc_ErrWhere(tl, tl->t);
-			return;
-		}
-
-		/* Match for the fixed tokens (see token.tcl) */
-		u = vcl_fixed_token(p, &q);
-		if (u != 0) {
-			vcc_AddToken(tl, u, p, q);
-			p = q;
-			continue;
-		}
-
-		/* Match strings */
-		if (*p == '"') {
-			for (q = p + 1; q < sp->e; q++) {
-				if (*q == '"') {
-					q++;
-					break;
-				}
-				if (*q == '\r' || *q == '\n') {
-					vcc_AddToken(tl, EOI, p, q);
-					VSB_printf(tl->sb,
-					    "Unterminated string at\n");
-					vcc_ErrWhere(tl, tl->t);
-					return;
-				}
-			}
-			vcc_AddToken(tl, CSTR, p, q);
-			if (vcc_decstr(tl))
-				return;
-			p = q;
-			continue;
-		}
-
-		/* Match Identifiers */
-		if (isident1(*p)) {
-			for (q = p; q < sp->e; q++)
-				if (!isvar(*q))
-					break;
-			vcc_AddToken(tl, ID, p, q);
-			p = q;
-			continue;
-		}
-
-		/* Match numbers { [0-9]+ } */
-		if (isdigit(*p)) {
-			for (q = p; q < sp->e; q++)
-				if (!isdigit(*q))
-					break;
-			vcc_AddToken(tl, CNUM, p, q);
-			p = q;
-			continue;
-		}
-		vcc_AddToken(tl, EOI, p, p + 1);
-		VSB_printf(tl->sb, "Syntax error at\n");
-		vcc_ErrWhere(tl, tl->t);
-		return;
-	}
-}
diff --git a/lib/libvcl/vcc_utils.c b/lib/libvcl/vcc_utils.c
deleted file mode 100644
index 5870af5..0000000
--- a/lib/libvcl/vcc_utils.c
+++ /dev/null
@@ -1,255 +0,0 @@
-/*-
- * Copyright (c) 2006 Verdens Gang AS
- * Copyright (c) 2006-2013 Varnish Software AS
- * All rights reserved.
- *
- * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netdb.h>
-
-#include "vcc_compile.h"
-
-#include "vre.h"
-#include "vrt.h"
-#include "vsa.h"
-
-/*--------------------------------------------------------------------*/
-
-const char *
-vcc_regexp(struct vcc *tl)
-{
-	char buf[BUFSIZ], *p;
-	vre_t *t;
-	const char *error;
-	int erroroffset;
-
-	Expect(tl, CSTR);
-	if (tl->err)
-		return (NULL);
-	memset(&t, 0, sizeof t);
-	t = VRE_compile(tl->t->dec, 0, &error, &erroroffset);
-	if (t == NULL) {
-		VSB_printf(tl->sb,
-		    "Regexp compilation error:\n\n%s\n\n", error);
-		vcc_ErrWhere(tl, tl->t);
-		return (NULL);
-	}
-	VRE_free(&t);
-	sprintf(buf, "VGC_re_%u", tl->unique++);
-	p = TlAlloc(tl, strlen(buf) + 1);
-	strcpy(p, buf);
-
-	Fh(tl, 0, "static void *%s;\n", buf);
-	Fi(tl, 0, "\tVRT_re_init(&%s, ",buf);
-	EncToken(tl->fi, tl->t);
-	Fi(tl, 0, ");\n");
-	Ff(tl, 0, "\tVRT_re_fini(%s);\n", buf);
-	return (p);
-}
-
-/*
- * The IPv6 crew royally screwed up the entire idea behind
- * struct sockaddr, and combined with various other incomptency
- * in the OS business, that means that there is no sane or even
- * remotely portable way to initialize a sockaddr at compile time.
- *
- * In our case it is slightly more tricky than that, because we don't
- * even want to #include the struct sockaddr* definitions.
- *
- * Instead we make sure the sockaddr is sane (for our values of sane)
- * and dump it in binary, using a 64 bit integertype, hoping that this
- * will ensure good enough alignment.
- */
-
-static const char *
-vcc_sockaddr(struct vcc *tl, const void *sa, unsigned sal)
-{
-	unsigned n = (sal + 7) / 8, len;
-	uint64_t b[n];
-	char *p;
-
-	assert(VSA_Sane(sa));
-	AN(sa);
-	AN(sal);
-	assert(sal < sizeof(struct sockaddr_storage));
-	assert(sizeof(unsigned long long) == 8);
-
-	p = TlAlloc(tl, 20);
-	sprintf(p, "sockaddr_%u", tl->unique++);
-
-	Fh(tl, 0, "static const unsigned long long");
-	Fh(tl, 0, " %s[%d] = {\n", p, n);
-	memcpy(b, sa, sal);
-	for (len = 0; len <n; len++) {
-		Fh(tl, 0, "%s    0x%016jx",
-		    len ? ",\n" : "",
-		    (uintmax_t)b[len]);
-	}
-	Fh(tl, 0, "\n};\n");
-	return (p);
-}
-
-/*--------------------------------------------------------------------
- * This routine is a monster, but at least we only have one such monster.
- * Look up a IP number, and return IPv4/IPv6 address as VGC produced names
- * and optionally ascii strings.
- *
- * For IP compile time constants we only want one IP#, but it can be
- * IPv4 or IPv6.
- *
- * For backends, we accept up to one IPv4 and one IPv6.
- */
-
-struct foo_proto {
-	const char		*name;
-	int			family;
-	struct sockaddr_storage	sa;
-	socklen_t		l;
-	const char		**dst;
-	const char		**dst_ascii;
-};
-
-void
-Resolve_Sockaddr(struct vcc *tl,
-    const char *host,
-    const char *port,
-    const char **ipv4,
-    const char **ipv4_ascii,
-    const char **ipv6,
-    const char **ipv6_ascii,
-    const char **p_ascii,
-    int maxips,
-    const struct token *t_err,
-    const char *errid)
-{
-	struct foo_proto protos[3], *pp;
-	struct addrinfo *res, *res0, *res1, hint;
-	int error, retval;
-	char hbuf[NI_MAXHOST];
-
-	memset(protos, 0, sizeof protos);
-	protos[0].name = "ipv4";
-	protos[0].family = PF_INET;
-	protos[0].dst = ipv4;
-	protos[0].dst_ascii = ipv4_ascii;
-	*ipv4 = NULL;
-
-	protos[1].name = "ipv6";
-	protos[1].family = PF_INET6;
-	protos[1].dst = ipv6;
-	protos[1].dst_ascii = ipv6_ascii;
-	*ipv6 = NULL;
-
-	retval = 0;
-	memset(&hint, 0, sizeof hint);
-	hint.ai_family = PF_UNSPEC;
-	hint.ai_socktype = SOCK_STREAM;
-
-	error = getaddrinfo(host, port, &hint, &res0);
-	if (error) {
-		VSB_printf(tl->sb,
-		    "%s '%.*s' could not be resolved to an IP address:\n",
-		    errid, PF(t_err));
-		VSB_printf(tl->sb,
-		    "\t%s\n"
-		    "(Sorry if that error message is gibberish.)\n",
-		    gai_strerror(error));
-		vcc_ErrWhere(tl, t_err);
-		return;
-	}
-
-	for (res = res0; res; res = res->ai_next) {
-		for (pp = protos; pp->name != NULL; pp++)
-			if (res->ai_family == pp->family)
-				break;
-		if (pp->name == NULL) {
-			/* Unknown proto, ignore */
-			continue;
-		}
-		if (pp->l == res->ai_addrlen &&
-		    !memcmp(&pp->sa, res->ai_addr, pp->l)) {
-			/*
-			 * Same address we already emitted.
-			 * This can happen using /etc/hosts
-			 */
-			continue;
-		}
-
-		if (pp->l != 0 || retval == maxips) {
-			VSB_printf(tl->sb,
-			    "%s %.*s: resolves to too many addresses.\n"
-			    "Only one IPv4 %s IPv6 are allowed.\n"
-			    "Please specify which exact address "
-			    "you want to use, we found all of these:\n",
-			    errid, PF(t_err),
-			    maxips > 1 ? "and one" :  "or");
-			for (res1 = res0; res1 != NULL; res1 = res1->ai_next) {
-				error = getnameinfo(res1->ai_addr,
-				    res1->ai_addrlen, hbuf, sizeof hbuf,
-				    NULL, 0, NI_NUMERICHOST);
-				AZ(error);
-				VSB_printf(tl->sb, "\t%s\n", hbuf);
-			}
-			freeaddrinfo(res0);
-			vcc_ErrWhere(tl, t_err);
-			return;
-		}
-
-		pp->l =  res->ai_addrlen;
-		assert(pp->l < sizeof(struct sockaddr_storage));
-		memcpy(&pp->sa, res->ai_addr, pp->l);
-
-		error = getnameinfo(res->ai_addr, res->ai_addrlen,
-		    hbuf, sizeof hbuf, NULL, 0, NI_NUMERICHOST);
-		AZ(error);
-
-		Fh(tl, 0, "\n/* \"%s\" -> %s */\n", host, hbuf);
-		*(pp->dst) = vcc_sockaddr(tl, &pp->sa, pp->l);
-		if (pp->dst_ascii != NULL) {
-			*pp->dst_ascii = TlDup(tl, hbuf);
-		}
-		retval++;
-	}
-	if (p_ascii != NULL) {
-		error = getnameinfo(res0->ai_addr,
-		    res0->ai_addrlen, NULL, 0, hbuf, sizeof hbuf,
-		    NI_NUMERICSERV);
-		AZ(error);
-		*p_ascii = TlDup(tl, hbuf);
-	}
-	if (retval == 0) {
-		VSB_printf(tl->sb,
-		    "%s '%.*s': resolves to "
-		    "neither IPv4 nor IPv6 addresses.\n",
-		    errid, PF(t_err) );
-		vcc_ErrWhere(tl, t_err);
-	}
-}
diff --git a/lib/libvcl/vcc_var.c b/lib/libvcl/vcc_var.c
deleted file mode 100644
index 74713b8..0000000
--- a/lib/libvcl/vcc_var.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/*-
- * Copyright (c) 2006 Verdens Gang AS
- * Copyright (c) 2006-2011 Varnish Software AS
- * All rights reserved.
- *
- * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#include <stdio.h>
-#include <string.h>
-
-#include "vcc_compile.h"
-#include "vct.h"
-
-/*--------------------------------------------------------------------*/
-
-struct symbol *
-vcc_Var_Wildcard(struct vcc *tl, const struct token *t, const struct symbol *wc)
-{
-	struct symbol *sym;
-	struct var *v;
-	const struct var *vh;
-	int l, i;
-	char c;
-	char buf[258];
-	char cnam[256];
-
-	vh = wc->var;
-
-	v = TlAlloc(tl, sizeof *v);
-	AN(v);
-
-	assert(vh->fmt == HEADER);
-	v->name = TlDupTok(tl, t);
-	v->r_methods = vh->r_methods;
-	v->w_methods = vh->w_methods;
-	v->fmt = vh->fmt;
-
-	/* Create a C-name version of the header name */
-	l = strlen(v->name + vh->len) + 1;
-	for (i = 0; i < l - 1; i++) {
-		c = *(v->name + vh->len + i);
-		if (vct_isalpha(c) || vct_isdigit(c))
-			cnam[i] = c;
-		else
-			cnam[i] = '_';
-	}
-	cnam[i] = '\0';
-
-	/* Create the static identifier */
-	Fh(tl, 0, "static const struct gethdr_s VGC_%s_%s =\n",
-	    vh->rname, cnam);
-	Fh(tl, 0, "    { %s, \"\\%03o%s:\"};\n",
-	    vh->rname, (unsigned)l, v->name + vh->len);
-
-	bprintf(buf, "&VGC_%s_%s", vh->rname, cnam);
-	v->rname = TlDup(tl, buf);
-	bprintf(buf, "VRT_SetHdr(ctx, %s, ", v->rname);
-	v->lname = TlDup(tl, buf);
-
-	sym = VCC_AddSymbolTok(tl, t, SYM_VAR);
-	AN(sym);
-	sym->var = v;
-	sym->fmt = v->fmt;
-	sym->eval = vcc_Eval_Var;
-	sym->r_methods = v->r_methods;
-	return (sym);
-}
-
-/*--------------------------------------------------------------------*/
-
-const struct var *
-vcc_FindVar(struct vcc *tl, const struct token *t, int wr_access,
-    const char *use)
-{
-	const struct var *v;
-	const struct symbol *sym;
-
-	AN(tl->vars);
-	sym = VCC_FindSymbol(tl, t, SYM_VAR);
-	if (sym != NULL) {
-		v = sym->var;
-		AN(v);
-
-		if (wr_access && v->w_methods == 0) {
-			VSB_printf(tl->sb, "Variable ");
-			vcc_ErrToken(tl, t);
-			VSB_printf(tl->sb, " is read only.");
-			VSB_cat(tl->sb, "\nAt: ");
-			vcc_ErrWhere(tl, t);
-			return (NULL);
-		} else if (wr_access) {
-			vcc_AddUses(tl, t, v->w_methods, use);
-		} else if (v->r_methods == 0) {
-			VSB_printf(tl->sb, "Variable ");
-			vcc_ErrToken(tl, t);
-			VSB_printf(tl->sb, " is write only.");
-			VSB_cat(tl->sb, "\nAt: ");
-			vcc_ErrWhere(tl, t);
-			return (NULL);
-		} else {
-			vcc_AddUses(tl, t, v->r_methods, use);
-		}
-		return (v);
-	}
-	VSB_printf(tl->sb, "Unknown variable ");
-	vcc_ErrToken(tl, t);
-	VSB_cat(tl->sb, "\nAt: ");
-	vcc_ErrWhere(tl, t);
-	return (NULL);
-}
diff --git a/lib/libvcl/vcc_vmod.c b/lib/libvcl/vcc_vmod.c
deleted file mode 100644
index 7eb9d32c..0000000
--- a/lib/libvcl/vcc_vmod.c
+++ /dev/null
@@ -1,204 +0,0 @@
-/*-
- * Copyright (c) 2010-2013 Varnish Software AS
- * All rights reserved.
- *
- * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include "config.h"
-
-#include <dlfcn.h>
-#include <stdio.h>
-#include <string.h>
-
-#include "vcc_compile.h"
-
-#include "vmod_abi.h"
-
-void
-vcc_ParseImport(struct vcc *tl)
-{
-	void *hdl;
-	char fn[1024];
-	char buf[256];
-	struct token *mod, *t1;
-	const char *modname;
-	const char *proto;
-	const char *abi;
-	const char **spec;
-	struct symbol *sym;
-	const struct symbol *osym;
-	const char *p;
-	// int *modlen;
-
-	t1 = tl->t;
-	SkipToken(tl, ID);		/* "import" */
-
-	ExpectErr(tl, ID);
-	mod = tl->t;
-	vcc_NextToken(tl);
-
-	osym = VCC_FindSymbol(tl, mod, SYM_NONE);
-	if (osym != NULL && osym->kind != SYM_VMOD) {
-		VSB_printf(tl->sb, "Module %.*s conflics with other symbol.\n",
-		    PF(mod));
-		vcc_ErrWhere2(tl, t1, tl->t);
-		return;
-	}
-	if (osym != NULL) {
-		VSB_printf(tl->sb, "Module %.*s already imported.\n",
-		    PF(mod));
-		vcc_ErrWhere2(tl, t1, tl->t);
-		VSB_printf(tl->sb, "Previous import was here:\n");
-		vcc_ErrWhere2(tl, osym->def_b, osym->def_e);
-		return;
-	}
-
-	bprintf(fn, "%.*s", PF(mod));
-	sym = VCC_AddSymbolStr(tl, fn, SYM_VMOD);
-	ERRCHK(tl);
-	AN(sym);
-	sym->def_b = t1;
-	sym->def_e = tl->t;
-
-	if (tl->t->tok == ID) {
-		if (!tl->unsafe_path) {
-			VSB_printf(tl->sb,
-			    "'import ... from path...'"
-			    " not allowed.\nAt:");
-			vcc_ErrToken(tl, tl->t);
-			vcc_ErrWhere(tl, tl->t);
-			return;
-		}
-		if (!vcc_IdIs(tl->t, "from")) {
-			VSB_printf(tl->sb, "Expected 'from path...'\n");
-			vcc_ErrWhere(tl, tl->t);
-			return;
-		}
-		vcc_NextToken(tl);
-		ExpectErr(tl, CSTR);
-		bprintf(fn, "%s", tl->t->dec);
-		vcc_NextToken(tl);
-	} else {
-		bprintf(fn, "%s/libvmod_%.*s.so", tl->vmod_dir, PF(mod));
-	}
-
-	Fh(tl, 0, "static void *VGC_vmod_%.*s;\n", PF(mod));
-
-	Fi(tl, 0, "\tif (VRT_Vmod_Init(&VGC_vmod_%.*s,\n", PF(mod));
-	Fi(tl, 0, "\t    &Vmod_%.*s_Func,\n", PF(mod));
-	Fi(tl, 0, "\t    sizeof(Vmod_%.*s_Func),\n", PF(mod));
-	Fi(tl, 0, "\t    \"%.*s\",\n", PF(mod));
-	Fi(tl, 0, "\t    ");
-	EncString(tl->fi, fn, NULL, 0);
-	Fi(tl, 0, ",\n\t    ");
-	Fi(tl, 0, "cli))\n");
-	Fi(tl, 0, "\t\treturn(1);\n");
-
-	SkipToken(tl, ';');
-
-	hdl = dlopen(fn, RTLD_NOW | RTLD_LOCAL);
-	if (hdl == NULL) {
-		VSB_printf(tl->sb, "Could not load module %.*s\n\t%s\n\t%s\n",
-		    PF(mod), fn, dlerror());
-		vcc_ErrWhere(tl, mod);
-		return;
-	}
-
-	bprintf(buf, "Vmod_%.*s_Name", PF(mod));
-	modname = dlsym(hdl, buf);
-	if (modname == NULL) {
-		VSB_printf(tl->sb, "Could not load module %.*s\n\t%s\n\t%s\n",
-		    PF(mod), fn, "Symbol Vmod_Name not found");
-		vcc_ErrWhere(tl, mod);
-		return;
-	}
-	if (!vcc_IdIs(mod, modname)) {
-		VSB_printf(tl->sb, "Could not load module %.*s\n\t%s\n",
-		    PF(mod), fn);
-		VSB_printf(tl->sb, "\tModule has wrong name: <%s>\n", modname);
-		vcc_ErrWhere(tl, mod);
-		return;
-	}
-
-	bprintf(buf, "Vmod_%.*s_ABI", PF(mod));
-	abi = dlsym(hdl, buf);
-	if (abi == NULL || strcmp(abi, VMOD_ABI_Version) != 0) {
-		VSB_printf(tl->sb, "Could not load module %.*s\n\t%s\n",
-		    PF(mod), fn);
-		VSB_printf(tl->sb, "\tABI mismatch, expected <%s>, got <%s>\n",
-			   VMOD_ABI_Version, abi);
-		vcc_ErrWhere(tl, mod);
-		return;
-	}
-
-	bprintf(buf, "Vmod_%.*s_Proto", PF(mod));
-	proto = dlsym(hdl, buf);
-	if (proto == NULL) {
-		VSB_printf(tl->sb, "Could not load module %.*s\n\t%s\n\t%s\n",
-		    PF(mod), fn, "Symbol Vmod_Proto not found");
-		vcc_ErrWhere(tl, mod);
-		return;
-	}
-	bprintf(buf, "Vmod_%.*s_Spec", PF(mod));
-	spec = dlsym(hdl, buf);
-	if (spec == NULL) {
-		VSB_printf(tl->sb, "Could not load module %.*s\n\t%s\n\t%s\n",
-		    PF(mod), fn, "Symbol Vmod_Spec not found");
-		vcc_ErrWhere(tl, mod);
-		return;
-	}
-	Fh(tl, 0, "static struct vmod_priv vmod_priv_%.*s;\n", PF(mod));
-	for (; *spec != NULL; spec++) {
-		p = *spec;
-		if (!strcmp(p, "OBJ")) {
-			p += strlen(p) + 1;
-			sym = VCC_AddSymbolStr(tl, p, SYM_OBJECT);
-			XXXAN(sym);
-			sym->args = p;
-		} else if (!strcmp(p, "INIT")) {
-			p += strlen(p) + 1;
-			Fi(tl, 0, "\t%s(&vmod_priv_%.*s, &VCL_conf);\n",
-			    p, PF(mod));
-		} else {
-			sym = VCC_AddSymbolStr(tl, p, SYM_FUNC);
-			ERRCHK(tl);
-			AN(sym);
-			sym->eval = vcc_Eval_SymFunc;
-			p += strlen(p) + 1;
-			sym->cfunc = p;
-			p += strlen(p) + 1;
-			sym->args = p;
-
-			/* Functions which return VOID are procedures */
-			if (!memcmp(p, "VOID\0", 5))
-				sym->kind = SYM_PROC;
-		}
-	}
-	Fh(tl, 0, "\n%s\n", proto);
-
-	/* XXX: zero the function pointer structure ?*/
-	Ff(tl, 0, "\tvmod_priv_fini(&vmod_priv_%.*s);\n", PF(mod));
-	Ff(tl, 0, "\tVRT_Vmod_Fini(&VGC_vmod_%.*s);\n", PF(mod));
-}
diff --git a/lib/libvcl/vcc_xref.c b/lib/libvcl/vcc_xref.c
deleted file mode 100644
index c3ef375..0000000
--- a/lib/libvcl/vcc_xref.c
+++ /dev/null
@@ -1,388 +0,0 @@
-/*-
- * Copyright (c) 2006 Verdens Gang AS
- * Copyright (c) 2006-2011 Varnish Software AS
- * All rights reserved.
- *
- * Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * This file contains code for two cross-reference or consistency checks.
- *
- * The first check is simply that all subroutine, acls and backends are
- * both defined and referenced.  Complaints about referenced but undefined
- * or defined but unreferenced objects will be emitted.
- *
- * The second check recursively decends through subroutine calls to make
- * sure that action actions are correct for the methods through which
- * they are called.
- */
-
-#include "config.h"
-
-#include <stdio.h>
-
-#include "vcc_compile.h"
-
-/*--------------------------------------------------------------------*/
-
-struct proccall {
-	VTAILQ_ENTRY(proccall)	list;
-	struct proc		*p;
-	struct token		*t;
-};
-
-struct procuse {
-	VTAILQ_ENTRY(procuse)	list;
-	const struct token	*t;
-	unsigned		mask;
-	const char		*use;
-};
-
-struct proc {
-	VTAILQ_HEAD(,proccall)	calls;
-	VTAILQ_HEAD(,procuse)	uses;
-	struct token		*name;
-	unsigned		ret_bitmap;
-	unsigned		exists;
-	unsigned		called;
-	unsigned		active;
-	struct token		*return_tok[VCL_RET_MAX];
-};
-
-/*--------------------------------------------------------------------
- * Keep track of definitions and references
- */
-
-void
-vcc_AddRef(struct vcc *tl, const struct token *t, enum symkind kind)
-{
-	struct symbol *sym;
-
-	sym = VCC_GetSymbolTok(tl, t, kind);
-	AN(sym);
-	sym->nref++;
-}
-
-int
-vcc_AddDef(struct vcc *tl, const struct token *t, enum symkind kind)
-{
-	struct symbol *sym;
-
-	sym = VCC_GetSymbolTok(tl, t, kind);
-	AN(sym);
-	sym->ndef++;
-	return (sym->ndef);
-}
-
-/*--------------------------------------------------------------------*/
-
-static void
-vcc_checkref(struct vcc *tl, const struct symbol *sym)
-{
-
-	if (sym->ndef == 0 && sym->nref != 0) {
-		VSB_printf(tl->sb, "Undefined %s %.*s, first reference:\n",
-		    VCC_SymKind(tl, sym), PF(sym->def_b));
-		vcc_ErrWhere(tl, sym->def_b);
-	} else if (sym->ndef != 0 && sym->nref == 0) {
-		VSB_printf(tl->sb, "Unused %s %.*s, defined:\n",
-		    VCC_SymKind(tl, sym), PF(sym->def_b));
-		vcc_ErrWhere(tl, sym->def_b);
-		if (!tl->err_unref) {
-			VSB_printf(tl->sb, "(That was just a warning)\n");
-			tl->err = 0;
-		}
-	}
-}
-
-int
-vcc_CheckReferences(struct vcc *tl)
-{
-
-	VCC_WalkSymbols(tl, vcc_checkref, SYM_NONE);
-	return (tl->err);
-}
-
-/*--------------------------------------------------------------------
- * Returns checks
- */
-
-static struct proc *
-vcc_findproc(struct vcc *tl, struct token *t)
-{
-	struct symbol *sym;
-	struct proc *p;
-
-
-	sym = VCC_GetSymbolTok(tl, t, SYM_SUB);
-	AN(sym);
-	if (sym->proc != NULL)
-		return (sym->proc);
-
-	p = TlAlloc(tl, sizeof *p);
-	assert(p != NULL);
-	VTAILQ_INIT(&p->calls);
-	VTAILQ_INIT(&p->uses);
-	p->name = t;
-	sym->proc = p;
-	return (p);
-}
-
-struct proc *
-vcc_AddProc(struct vcc *tl, struct token *t)
-{
-	struct proc *p;
-
-	p = vcc_findproc(tl, t);
-	p->name = t;	/* make sure the name matches the definition */
-	p->exists++;
-	return (p);
-}
-
-void
-vcc_AddUses(struct vcc *tl, const struct token *t, unsigned mask,
-    const char *use)
-{
-	struct procuse *pu;
-
-	if (tl->curproc == NULL)	/* backend */
-		return;
-	pu = TlAlloc(tl, sizeof *pu);
-	assert(pu != NULL);
-	pu->t = t;
-	pu->mask = mask;
-	pu->use = use;
-	VTAILQ_INSERT_TAIL(&tl->curproc->uses, pu, list);
-}
-
-void
-vcc_AddCall(struct vcc *tl, struct token *t)
-{
-	struct proccall *pc;
-	struct proc *p;
-
-	p = vcc_findproc(tl, t);
-	pc = TlAlloc(tl, sizeof *pc);
-	assert(pc != NULL);
-	pc->p = p;
-	pc->t = t;
-	VTAILQ_INSERT_TAIL(&tl->curproc->calls, pc, list);
-}
-
-void
-vcc_ProcAction(struct proc *p, unsigned returns, struct token *t)
-{
-
-	assert(returns < VCL_RET_MAX);
-	p->ret_bitmap |= (1U << returns);
-	/* Record the first instance of this return */
-	if (p->return_tok[returns] == NULL)
-		p->return_tok[returns] = t;
-}
-
-static int
-vcc_CheckActionRecurse(struct vcc *tl, struct proc *p, unsigned bitmap)
-{
-	unsigned u;
-	struct proccall *pc;
-
-	if (!p->exists) {
-		VSB_printf(tl->sb, "Function %.*s does not exist\n",
-		    PF(p->name));
-		return (1);
-	}
-	if (p->active) {
-		VSB_printf(tl->sb, "Function recurses on\n");
-		vcc_ErrWhere(tl, p->name);
-		return (1);
-	}
-	u = p->ret_bitmap & ~bitmap;
-	if (u) {
-
-#define VCL_RET_MAC(l, U, B)						\
-		if (u & (1 << (VCL_RET_##U))) {				\
-			VSB_printf(tl->sb, "Invalid return \"" #l "\"\n");\
-			vcc_ErrWhere(tl, p->return_tok[VCL_RET_##U]);	\
-		}
-#include "tbl/vcl_returns.h"
-#undef VCL_RET_MAC
-
-		VSB_printf(tl->sb, "\n...in subroutine \"%.*s\"\n",
-		    PF(p->name));
-		vcc_ErrWhere(tl, p->name);
-		return (1);
-	}
-	p->active = 1;
-	VTAILQ_FOREACH(pc, &p->calls, list) {
-		if (vcc_CheckActionRecurse(tl, pc->p, bitmap)) {
-			VSB_printf(tl->sb, "\n...called from \"%.*s\"\n",
-			    PF(p->name));
-			vcc_ErrWhere(tl, pc->t);
-			return (1);
-		}
-	}
-	p->active = 0;
-	p->called++;
-	return (0);
-}
-
-/*--------------------------------------------------------------------*/
-
-static void
-vcc_checkaction1(struct vcc *tl, const struct symbol *sym)
-{
-	struct proc *p;
-	struct method *m;
-	int i;
-
-	p = sym->proc;
-	AN(p);
-	i = IsMethod(p->name);
-	if (i < 0)
-		return;
-	m = method_tab + i;
-	if (vcc_CheckActionRecurse(tl, p, m->ret_bitmap)) {
-		VSB_printf(tl->sb,
-		    "\n...which is the \"%s\" method\n", m->name);
-		VSB_printf(tl->sb, "Legal returns are:");
-#define VCL_RET_MAC(l, U, B)						\
-		if (m->ret_bitmap & ((1 << VCL_RET_##U)))	\
-			VSB_printf(tl->sb, " \"%s\"", #l);
-
-#include "tbl/vcl_returns.h"
-#undef VCL_RET_MAC
-		VSB_printf(tl->sb, "\n");
-		tl->err = 1;
-	}
-
-}
-
-static void
-vcc_checkaction2(struct vcc *tl, const struct symbol *sym)
-{
-	struct proc *p;
-
-	p = sym->proc;
-	AN(p);
-
-	if (p->called)
-		return;
-	VSB_printf(tl->sb, "Function unused\n");
-	vcc_ErrWhere(tl, p->name);
-	if (!tl->err_unref) {
-		VSB_printf(tl->sb, "(That was just a warning)\n");
-		tl->err = 0;
-	}
-}
-
-int
-vcc_CheckAction(struct vcc *tl)
-{
-
-	VCC_WalkSymbols(tl, vcc_checkaction1, SYM_SUB);
-	if (tl->err)
-		return (tl->err);
-	VCC_WalkSymbols(tl, vcc_checkaction2, SYM_SUB);
-	return (tl->err);
-}
-
-/*--------------------------------------------------------------------*/
-
-static struct procuse *
-vcc_FindIllegalUse(const struct proc *p, const struct method *m)
-{
-	struct procuse *pu;
-
-	VTAILQ_FOREACH(pu, &p->uses, list)
-		if (!(pu->mask & m->bitval))
-			return (pu);
-	return (NULL);
-}
-
-static int
-vcc_CheckUseRecurse(struct vcc *tl, const struct proc *p,
-    struct method *m)
-{
-	struct proccall *pc;
-	struct procuse *pu;
-
-	pu = vcc_FindIllegalUse(p, m);
-	if (pu != NULL) {
-		VSB_printf(tl->sb,
-		    "'%.*s': %s from method '%.*s'.\n",
-		    PF(pu->t), pu->use, PF(p->name));
-		vcc_ErrWhere(tl, pu->t);
-		VSB_printf(tl->sb, "\n...in subroutine \"%.*s\"\n",
-		    PF(p->name));
-		vcc_ErrWhere(tl, p->name);
-		return (1);
-	}
-	VTAILQ_FOREACH(pc, &p->calls, list) {
-		if (vcc_CheckUseRecurse(tl, pc->p, m)) {
-			VSB_printf(tl->sb, "\n...called from \"%.*s\"\n",
-			    PF(p->name));
-			vcc_ErrWhere(tl, pc->t);
-			return (1);
-		}
-	}
-	return (0);
-}
-
-static void
-vcc_checkuses(struct vcc *tl, const struct symbol *sym)
-{
-	struct proc *p;
-	struct method *m;
-	struct procuse *pu;
-	int i;
-
-	p = sym->proc;
-	AN(p);
-
-	i = IsMethod(p->name);
-	if (i < 0)
-		return;
-	m = method_tab + i;
-	pu = vcc_FindIllegalUse(p, m);
-	if (pu != NULL) {
-		VSB_printf(tl->sb,
-		    "'%.*s': %s in method '%.*s'.",
-		    PF(pu->t), pu->use, PF(p->name));
-		VSB_cat(tl->sb, "\nAt: ");
-		vcc_ErrWhere(tl, pu->t);
-		return;
-	}
-	if (vcc_CheckUseRecurse(tl, p, m)) {
-		VSB_printf(tl->sb,
-		    "\n...which is the \"%s\" method\n", m->name);
-		return;
-	}
-}
-
-int
-vcc_CheckUses(struct vcc *tl)
-{
-
-	VCC_WalkSymbols(tl, vcc_checkuses, SYM_SUB);
-	return (tl->err);
-}
diff --git a/lib/libvcl/vmodtool.py b/lib/libvcl/vmodtool.py
deleted file mode 100755
index 2b6db42..0000000
--- a/lib/libvcl/vmodtool.py
+++ /dev/null
@@ -1,553 +0,0 @@
-#!/usr/bin/env python
-#-
-# Copyright (c) 2010-2013 Varnish Software AS
-# All rights reserved.
-#
-# Author: Poul-Henning Kamp <phk at phk.freebsd.dk>
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-# 1. Redistributions of source code must retain the above copyright
-#    notice, this list of conditions and the following disclaimer.
-# 2. Redistributions in binary form must reproduce the above copyright
-#    notice, this list of conditions and the following disclaimer in the
-#    documentation and/or other materials provided with the distribution.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
-# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-# ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
-# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-# SUCH DAMAGE.
-#
-# Read the vmod.spec file and produce the vmod.h and vmod.c files.
-#
-# vmod.h contains the prototypes for the published functions, the module
-# C-code should include this file to ensure type-consistency.
-#
-# vmod.c contains the symbols which VCC and varnishd will use to access
-# the module:  A structure of properly typed function pointers, the
-# size of this structure in bytes, and the definition of the structure
-# as a string, suitable for inclusion in the C-source of the compile VCL
-# program.
-
-import sys
-import re
-
-if len(sys.argv) == 2:
-	specfile = sys.argv[1]
-else:
-	specfile = "vmod.vcc"
-
-ctypes = {
-	'BACKEND':	"VCL_BACKEND",
-	'BOOL':		"VCL_BOOL",
-	'DURATION':	"VCL_DURATION",
-	'ENUM':		"VCL_ENUM",
-	'HEADER':	"const struct gethdr_s *",
-	'INT':		"VCL_INT",
-	'IP':		"VCL_IP",
-	'PRIV_CALL':	"struct vmod_priv *",
-	'PRIV_VCL':	"struct vmod_priv *",
-	'REAL':		"VCL_REAL",
-	'STRING':	"VCL_STRING",
-	'STRING_LIST':	"const char *, ...",
-	'TIME':		"VCL_TIME",
-	'VOID':		"VCL_VOID",
-}
-
-#######################################################################
-
-def file_header(fo):
-        fo.write("""/*
- * NB:  This file is machine generated, DO NOT EDIT!
- *
- * Edit vmod.vcc and run vmod.py instead
- */
-
-""")
-
-#######################################################################
-
-def is_c_name(s):
-	return None != re.match("^[a-z][a-z0-9_]*$", s)
-
-#######################################################################
-
-class token(object):
-	def __init__(self, ln, ch, str):
-		self.ln = ln
-		self.ch = ch
-		self.str = str
-
-	def __repr__(self):
-		return "<@%d \"%s\">" % (self.ln, self.str)
-
-#######################################################################
-
-class vmod(object):
-	def __init__(self, nam):
-		if not is_c_name(nam):
-			raise Exception("Module name '%s' is illegal" % nam)
-		self.nam = nam
-		self.init = None
-		self.funcs = list()
-		self.objs = list()
-
-	def set_init(self, nam):
-		if self.init != None:
-			raise Exception("Module %s already has Init" % self.nam)
-		if not is_c_name(nam):
-			raise Exception("Init name '%s' is illegal" % nam)
-		self.init = nam
-
-	def add_func(self, fn):
-		self.funcs.append(fn)
-
-	def add_obj(self, obj):
-		self.objs.append(obj)
-		obj.set_modnam(self.nam)
-
-	def c_proto(self, fo):
-		for o in self.objs:
-			o.c_proto(fo)
-			fo.write("\n")
-		for f in self.funcs:
-			f.c_proto(fo)
-		if self.init != None:
-			fo.write("\n")
-			fo.write("int " + self.init)
-			fo.write(
-			    "(struct vmod_priv *, const struct VCL_conf *);\n")
-		#fo.write("\n")
-		#fo.write("extern const void * const Vmod_" + self.nam + "_Id;\n")
-
-	def c_typedefs_(self):
-		l = list()
-		for o in self.objs:
-			for t in o.c_typedefs(self.nam):
-				l.append(t)
-			l.append("")
-		l.append("/* Functions */")
-		for f in self.funcs:
-			l.append(f.c_typedef(self.nam))
-		l.append("")
-		return l
-
-	def c_typedefs(self, fo):
-		for i in self.c_typedefs_():
-			fo.write(i + "\n")
-
-	def c_vmod(self, fo):
-		fo.write('const char Vmod_' + self.nam + '_Name[] =')
-		fo.write(' \"' + self.nam + '";\n')
-		fo.write("\n")
-
-		cs = self.c_struct()
-		fo.write("const " + cs + ' Vmod_' + self.nam + '_Func = ')
-		fo.write(self.c_initializer())
-		fo.write("\n")
-
-		fo.write("\n")
-		fo.write("const int Vmod_" + self.nam + '_Len =')
-		fo.write(" sizeof(Vmod_" + self.nam + "_Func);\n")
-		fo.write("\n")
-
-		fo.write("const char Vmod_" + self.nam + "_Proto[] =\n")
-		for t in self.c_typedefs_():
-			fo.write('\t"' + t + '\\n"\n')
-		fo.write('\t"\\n"\n')
-		for i in (cs + " Vmod_" + self.nam + '_Func;').split("\n"):
-			fo.write('\n\t"' + i + '\\n"')
-		fo.write(";\n\n")
-
-		fo.write(self.c_strspec())
-
-		fo.write("\n")
-		fo.write('const char Vmod_' + self.nam + '_ABI[] =')
-		fo.write(' VMOD_ABI_Version;\n')
-		#fo.write("\n")
-		#fo.write('const void * const Vmod_' + self.nam + '_Id =')
-		#fo.write(' &Vmod_' + self.nam + '_Id;\n')
-
-	def c_initializer(self):
-		s = '{\n'
-		for o in self.objs:
-			s += o.c_initializer()
-
-		s += "\n\t/* Functions */\n"
-		for f in self.funcs:
-			s += f.c_initializer()
-
-		s += "\n\t/* Init/Fini */\n"
-		if self.init != None:
-			s += "\t" + self.init + ",\n"
-		s += "};"
-
-		return s
-
-	def c_struct(self):
-		s = 'struct Vmod_' + self.nam + '_Func {\n'
-		for o in self.objs:
-			s += o.c_struct(self.nam)
-
-		s += "\n\t/* Functions */\n"
-		for f in self.funcs:
-			s += f.c_struct(self.nam)
-
-		s += "\n\t/* Init/Fini */\n"
-		if self.init != None:
-			s += "\tvmod_init_f\t*_init;\n"
-		s += '}'
-		return s
-
-	def c_strspec(self):
-		s = "const char * const Vmod_" + self.nam + "_Spec[] = {\n"
-
-		for o in self.objs:
-			s += o.c_strspec(self.nam)
-
-		s += "\n\t/* Functions */\n"
-		for f in self.funcs:
-			s += '\t"' + f.c_strspec(self.nam) + '",\n'
-
-		s += "\n\t/* Init/Fini */\n"
-		if self.init != None:
-			s += '\t"INIT\\0Vmod_' + self.nam + '_Func._init",\n'
-
-		s += "\t0\n"
-		s += "};\n"
-		return s
-
-#######################################################################
-
-class func(object):
-	def __init__(self, nam, retval, al):
-		#if not is_c_name(nam):
-		#	raise Exception("Func name '%s' is illegal" % nam)
-		if retval not in ctypes:
-			raise Exception(
-			    "Return type '%s' not a valid type" % retval)
-		self.nam = nam
-		self.cnam = nam.replace(".", "_")
-		self.al = al
-		self.retval = retval
-		self.pfx = None
-
-	def __repr__(self):
-		return "<FUNC %s %s>" % (self.retval, self.nam)
-
-	def set_pfx(self, s):
-		self.pfx = s
-
-	def c_proto(self, fo, fini=False):
-		fo.write(ctypes[self.retval])
-		fo.write(" vmod_" + self.cnam + "(")
-		p = ""
-		if not fini:
-			fo.write("const struct vrt_ctx *")
-			p = ", "
-		if self.pfx != None:
-			fo.write(p + self.pfx)
-			p = ", "
-		for a in self.al:
-			fo.write(p + ctypes[a.typ])
-			p = ", "
-			if a.nam != None:
-				fo.write(" " + a.nam)
-		fo.write(");\n")
-
-	def c_typedef(self, modname, fini=False):
-		s = "typedef "
-		s += ctypes[self.retval]
-		s += " td_" + modname + "_" + self.cnam + "("
-		p = ""
-		if not fini:
-			s += "const struct vrt_ctx *"
-			p = ", "
-		if self.pfx != None:
-			s += p + self.pfx
-			p = ", "
-		for a in self.al:
-			s += p + ctypes[a.typ]
-			p = ", "
-		s += ");"
-		return s
-
-	def c_struct(self, modname):
-		s = '\ttd_' + modname + "_" + self.cnam
-		while len(s.expandtabs()) < 40:
-			s += "\t"
-		s += "*" + self.cnam + ";\n"
-		return s
-
-	def c_initializer(self):
-		return "\tvmod_" + self.cnam + ",\n"
-
-	def c_strspec(self, modnam):
-		s = modnam + "." + self.nam
-		s += "\\0"
-		s += "Vmod_" + modnam + "_Func." + self.cnam + "\\0"
-		s += self.retval + "\\0"
-		for a in self.al:
-			s += a.c_strspec()
-		return s
-
-#######################################################################
-
-class obj(object):
-	def __init__(self, nam):
-		self.nam = nam
-		self.init = None
-		self.fini = None
-		self.methods = list()
-
-	def set_modnam(self, modnam):
-		self.st = "struct vmod_" + modnam + "_" + self.nam
-		self.init.set_pfx(self.st + " **, const char *")
-		self.fini.set_pfx(self.st + " **")
-		for m in self.methods:
-			m.set_pfx(self.st + " *")
-
-	def set_init(self, f):
-		self.init = f
-		self.fini = func(f.nam, "VOID", [])
-		self.init.cnam += "__init"
-		self.fini.cnam += "__fini"
-
-	def add_method(self, m):
-		self.methods.append(m)
-
-	def c_typedefs(self, modnam):
-		l = list()
-		l.append("/* Object " + self.nam + " */")
-		l.append(self.st + ";")
-		l.append(self.init.c_typedef(modnam) + "")
-		l.append(self.fini.c_typedef(modnam, fini=True) + "")
-		for m in self.methods:
-			l.append(m.c_typedef(modnam) + "")
-		return l
-
-	def c_proto(self, fo):
-		fo.write(self.st + ";\n")
-		self.init.c_proto(fo)
-		self.fini.c_proto(fo, fini = True)
-		for m in self.methods:
-			m.c_proto(fo)
-
-	def c_struct(self, modnam):
-		s = "\t/* Object " + self.nam + " */\n"
-		s += self.init.c_struct(modnam)
-		s += self.fini.c_struct(modnam)
-		for m in self.methods:
-			s += m.c_struct(modnam)
-		return s
-
-	def c_initializer(self):
-		s = "\t/* Object " + self.nam + " */\n"
-		s += self.init.c_initializer()
-		s += self.fini.c_initializer()
-		for m in self.methods:
-			s += m.c_initializer()
-		return s
-
-	def c_strspec(self, modnam):
-		s = "\t/* Object " + self.nam + " */\n"
-		s += '\t"OBJ\\0"\n'
-		s += '\t\t"' + self.init.c_strspec(modnam) + '\\0"\n'
-		s += '\t\t"' + self.st + '\\0"\n'
-		s += '\t\t"' + self.fini.c_strspec(modnam) + '\\0"\n'
-		for m in self.methods:
-			s += '\t\t"' + m.c_strspec(modnam) + '\\0"\n'
-		s += '\t\t"\\0",\n'
-		return s
-
-#######################################################################
-
-class arg(object):
-	def __init__(self, typ, nam = None, det = None):
-		self.nam = nam
-		self.typ = typ
-		self.det = det
-
-	def __repr__(self):
-		return "<ARG %s %s %s>" % (self.nam, self.typ, str(self.det))
-
-	def c_strspec(self):
-		if self.det == None:
-			return self.typ + "\\0"
-		else:
-			return self.det
-		return "??"
-
-#######################################################################
-
-f = open(specfile, "r")
-tl = list()
-lines = list()
-ln = 0
-for l in f:
-	ln += 1
-	lines.append(l)
-	if l == "":
-		continue
-	l = re.sub("[ \t]*#.*$", "", l)
-	l = re.sub("[ \t]*\n", "", l)
-	l = re.sub("([(){},])", r' \1 ', l)
-	if l == "":
-		continue
-	for j in l.split():
-		tl.append(token(ln, 0, j))
-f.close()
-
-#######################################################################
-#
-#
-def parse_enum2(tl):
-	t = tl.pop(0)
-	if t.str != "{":
-		raise Exception("expected \"{\"")
-	s = "ENUM\\0"
-	while True:
-		t = tl.pop(0)
-		if t.str == "}":
-			break
-		s += t.str + "\\0"
-		if tl[0].str == ",":
-			tl.pop(0)
-		elif tl[0].str != "}":
-			raise Exception("Expceted \"}\" or \",\"")
-	s += "\\0"
-	return arg("ENUM", det=s)
-
-#######################################################################
-#
-#
-
-def parse_func(tl, rt_type = None, obj=None):
-	al = list()
-	if rt_type == None:
-		t = tl.pop(0)
-		rt_type = t.str
-	if rt_type not in ctypes:
-		raise Exception(
-		    "Return type '%s' not a valid type" % rt_type)
-
-	t = tl.pop(0)
-	fname = t.str
-	if obj != None and fname[0] == "." and is_c_name(fname[1:]):
-		fname = obj + fname
-	elif not is_c_name(fname):
-		raise Exception("Function name '%s' is illegal" % fname)
-
-	t = tl.pop(0)
-	if t.str != "(":
-		raise Exception("Expected \"(\" got \"%s\"", t.str)
-
-	while True:
-		t = tl.pop(0)
-		if t.str == ")":
-			break
-		if t.str == "ENUM":
-			al.append(parse_enum2(tl))
-		elif t.str in ctypes:
-			al.append(arg(t.str))
-		else:
-			raise Exception("ARG? %s" % t.str)
-		if is_c_name(tl[0].str):
-			al[-1].nam = tl[0].str
-			t = tl.pop(0)
-		if tl[0].str == ",":
-			tl.pop(0)
-		elif tl[0].str != ")":
-			raise Exception("Expceted \")\" or \",\"")
-	if t.str != ")":
-		raise Exception("End Of Input looking for ')'")
-	f = func(fname, rt_type, al)
-	return f
-
-#######################################################################
-#
-#
-
-def parse_obj(tl):
-	o = obj(tl[0].str)
-	f = parse_func(tl, "VOID")
-	o.set_init(f)
-	t = tl.pop(0)
-	assert t.str == "{"
-	while True:
-		t = tl.pop(0)
-		if t.str == "}":
-			break
-		assert t.str == "Method"
-		f = parse_func(tl, obj=o.nam)
-		o.add_method(f)
-	return o
-
-#######################################################################
-# The first thing in the file must be the Module declaration
-#
-
-t = tl.pop(0)
-if t.str != "Module":
-	raise Exception("\"Module\" must be first in file")
-t = tl.pop(0)
-vmod = vmod(t.str)
-
-#######################################################################
-# Parse the rest of the file
-#
-
-while len(tl) > 0:
-	t = tl.pop(0)
-
-	if t.str == "Init":
-		t = tl.pop(0)
-		vmod.set_init(t.str)
-	elif t.str == "Function":
-		f = parse_func(tl)
-		vmod.add_func(f)
-	elif t.str == "Object":
-		o = parse_obj(tl)
-		vmod.add_obj(o)
-	else:
-		raise Exception("Expected \"Init\", \"Fini\" or \"Function\"")
-
-#######################################################################
-# Parsing done, now process
-#
-
-fc = open("vcc_if.c", "w")
-fh = open("vcc_if.h", "w")
-
-file_header(fc)
-file_header(fh)
-
-fh.write('struct vrt_ctx;\n')
-fh.write('struct VCL_conf;\n')
-fh.write('struct vmod_priv;\n')
-fh.write("\n");
-
-vmod.c_proto(fh)
-
-fc.write("""#include "config.h"
-
-#include "vrt.h"
-#include "vcc_if.h"
-#include "vmod_abi.h"
-
-
-""")
-
-vmod.c_typedefs(fc)
-vmod.c_vmod(fc)
-
-fc.close()
-fh.close()
diff --git a/lib/libvmod_debug/Makefile.am b/lib/libvmod_debug/Makefile.am
index 7e2c849..f73720c 100644
--- a/lib/libvmod_debug/Makefile.am
+++ b/lib/libvmod_debug/Makefile.am
@@ -8,7 +8,7 @@ AM_CPPFLAGS = \
 
 vmoddir = $(pkglibdir)/vmods
 vmod_srcdir = $(top_srcdir)/lib/libvmod_debug
-vmodtool = $(top_srcdir)/lib/libvcl/vmodtool.py
+vmodtool = $(top_srcdir)/lib/libvcc/vmodtool.py
 noinst_LTLIBRARIES = libvmod_debug.la
 
 libvmod_debug_la_LDFLAGS = $(AM_LDFLAGS) -module -export-dynamic -avoid-version -shared -rpath /nowhere
diff --git a/lib/libvmod_directors/Makefile.am b/lib/libvmod_directors/Makefile.am
index e49a285..7e2e2f3 100644
--- a/lib/libvmod_directors/Makefile.am
+++ b/lib/libvmod_directors/Makefile.am
@@ -8,7 +8,7 @@ AM_CPPFLAGS = \
 
 vmoddir = $(pkglibdir)/vmods
 vmod_srcdir = $(top_srcdir)/lib/libvmod_directors
-vmodtool = $(top_srcdir)/lib/libvcl/vmodtool.py
+vmodtool = $(top_srcdir)/lib/libvcc/vmodtool.py
 noinst_LTLIBRARIES = libvmod_directors.la
 
 libvmod_directors_la_LDFLAGS = $(AM_LDFLAGS) -module -export-dynamic -avoid-version -shared -rpath /nowhere
diff --git a/lib/libvmod_std/Makefile.am b/lib/libvmod_std/Makefile.am
index acc0842..cd55e5b 100644
--- a/lib/libvmod_std/Makefile.am
+++ b/lib/libvmod_std/Makefile.am
@@ -11,7 +11,7 @@ dist_man_MANS = vmod_std.3
 
 vmoddir = $(pkglibdir)/vmods
 vmod_srcdir = $(top_srcdir)/lib/libvmod_std
-vmodtool = $(top_srcdir)/lib/libvcl/vmodtool.py
+vmodtool = $(top_srcdir)/lib/libvcc/vmodtool.py
 vmod_LTLIBRARIES = libvmod_std.la
 
 libvmod_std_la_LDFLAGS = $(AM_LDFLAGS) -module -export-dynamic -avoid-version -shared
diff --git a/redhat/varnish.spec b/redhat/varnish.spec
index ea0fc24..df56f62 100644
--- a/redhat/varnish.spec
+++ b/redhat/varnish.spec
@@ -150,7 +150,7 @@ rm -rf doc/sphinx/\=build
 	%endif
 %endif
 
-make check LD_LIBRARY_PATH="../../lib/libvarnish/.libs:../../lib/libvarnishcompat/.libs:../../lib/libvarnishapi/.libs:../../lib/libvcl/.libs:../../lib/libvgz/.libs"
+make check LD_LIBRARY_PATH="../../lib/libvarnish/.libs:../../lib/libvarnishcompat/.libs:../../lib/libvarnishapi/.libs:../../lib/libvcc/.libs:../../lib/libvgz/.libs"
 
 %install
 rm -rf %{buildroot}
@@ -247,7 +247,7 @@ rm -rf %{buildroot}
 #%{_libdir}/libvarnish.a
 #%{_libdir}/libvarnishapi.a
 #%{_libdir}/libvarnishcompat.a
-#%{_libdir}/libvcl.a
+#%{_libdir}/libvcc.a
 #%doc LICENSE
 
 %pre



More information about the varnish-commit mailing list