[PATCH] Add PCRE support
Tollef Fog Heen
tfheen at redpill-linpro.com
Fri Oct 16 16:20:28 CEST 2009
We no longer use POSIX style regexes, but rather PCRE regexes. This
introduces a hard dependency on libpcre.
Test suite passes, but only lightly tested.
---
varnish-cache/bin/varnishd/Makefile.am | 3 +-
varnish-cache/bin/varnishd/cache_ban.c | 29 ++++++++-------
varnish-cache/bin/varnishd/cache_ban.h | 2 +-
varnish-cache/bin/varnishd/cache_vrt_re.c | 48 +++++++++++++-----------
varnish-cache/bin/varnishlog/Makefile.am | 3 +-
varnish-cache/bin/varnishlog/varnishlog.c | 18 +++++----
varnish-cache/configure.ac | 31 ++++++++++++++++
varnish-cache/include/vrt.h | 2 +-
varnish-cache/lib/libvarnishapi/Makefile.am | 4 ++-
varnish-cache/lib/libvarnishapi/shmlog.c | 52 +++++++++++++--------------
varnish-cache/lib/libvcl/Makefile.am | 4 ++-
varnish-cache/lib/libvcl/vcc_compile.h | 2 +-
varnish-cache/lib/libvcl/vcc_parse.c | 2 +-
varnish-cache/lib/libvcl/vcc_string.c | 23 ++++++------
14 files changed, 132 insertions(+), 91 deletions(-)
diff --git a/varnish-cache/bin/varnishd/Makefile.am b/varnish-cache/bin/varnishd/Makefile.am
index dfdef42..daa389b 100644
--- a/varnish-cache/bin/varnishd/Makefile.am
+++ b/varnish-cache/bin/varnishd/Makefile.am
@@ -1,6 +1,6 @@
# $Id$
-INCLUDES = -I$(top_srcdir)/include
+INCLUDES = -I$(top_srcdir)/include @PCRE_CFLAGS@
sbin_PROGRAMS = varnishd
@@ -87,6 +87,7 @@ varnishd_LDADD = \
$(top_builddir)/lib/libvarnishcompat/libvarnishcompat.la \
$(top_builddir)/lib/libvcl/libvcl.la \
@JEMALLOC_LDADD@ \
+ @PCRE_LIBS@ \
${DL_LIBS} ${PTHREAD_LIBS} ${NET_LIBS} ${LIBM} ${LIBUMEM}
EXTRA_DIST = default.vcl
diff --git a/varnish-cache/bin/varnishd/cache_ban.c b/varnish-cache/bin/varnishd/cache_ban.c
index 57bdb05..6f6cc0e 100644
--- a/varnish-cache/bin/varnishd/cache_ban.c
+++ b/varnish-cache/bin/varnishd/cache_ban.c
@@ -50,7 +50,7 @@ SVNID("$Id$")
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <regex.h>
+#include <pcre.h>
#include "shmlog.h"
#include "cli.h"
@@ -116,7 +116,7 @@ BAN_Free(struct ban *b)
bt = VTAILQ_FIRST(&b->tests);
VTAILQ_REMOVE(&b->tests, bt, list);
if (bt->flags & BAN_T_REGEXP)
- regfree(&bt->re);
+ pcre_free(&bt->re);
if (bt->dst != NULL)
free(bt->dst);
if (bt->src != NULL)
@@ -137,10 +137,13 @@ ban_cond_str(const struct ban_test *bt, const char *p)
if (p == NULL)
return(!(bt->flags & BAN_T_NOT));
- if (bt->flags & BAN_T_REGEXP)
- i = regexec(&bt->re, p, 0, NULL, 0);
- else
+ if (bt->flags & BAN_T_REGEXP) {
+ i = pcre_exec(bt->re, NULL, p, strlen(p), 0, 0, NULL, 0);
+ if (i >= 0)
+ i = 0;
+ } else {
i = strcmp(bt->dst, p);
+ }
if (bt->flags & BAN_T_NOT)
return (!i);
return (i);
@@ -199,15 +202,13 @@ ban_cond_obj_http(const struct ban_test *bt, const struct object *o,
static int
ban_parse_regexp(struct cli *cli, struct ban_test *bt, const char *a3)
{
- int i;
- char buf[512];
-
- i = regcomp(&bt->re, a3, REG_EXTENDED | REG_ICASE | REG_NOSUB);
- if (i) {
- (void)regerror(i, &bt->re, buf, sizeof buf);
- regfree(&bt->re);
- VSL(SLT_Debug, 0, "REGEX: <%s>", buf);
- cli_out(cli, "%s", buf);
+ const char *error;
+ int erroroffset;
+
+ bt->re = pcre_compile(a3, 0, &error, &erroroffset, NULL);
+ if (bt->re == NULL) {
+ VSL(SLT_Debug, 0, "REGEX: <%s>", error);
+ cli_out(cli, "%s", error);
cli_result(cli, CLIS_PARAM);
return (-1);
}
diff --git a/varnish-cache/bin/varnishd/cache_ban.h b/varnish-cache/bin/varnishd/cache_ban.h
index 58a1ff8..673e5a9 100644
--- a/varnish-cache/bin/varnishd/cache_ban.h
+++ b/varnish-cache/bin/varnishd/cache_ban.h
@@ -44,7 +44,7 @@ struct ban_test {
int flags;
#define BAN_T_REGEXP (1 << 0)
#define BAN_T_NOT (1 << 1)
- regex_t re;
+ pcre *re;
char *dst;
char *src;
};
diff --git a/varnish-cache/bin/varnishd/cache_vrt_re.c b/varnish-cache/bin/varnishd/cache_vrt_re.c
index e91f3c1..0e9052a 100644
--- a/varnish-cache/bin/varnishd/cache_vrt_re.c
+++ b/varnish-cache/bin/varnishd/cache_vrt_re.c
@@ -35,12 +35,14 @@
SVNID("$Id$")
#include <sys/types.h>
+#include <syslog.h>
+
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
-#include <regex.h>
+#include <pcre.h>
#include "shmlog.h"
#include "vrt.h"
@@ -48,14 +50,15 @@ SVNID("$Id$")
#include "cache.h"
void
-VRT_re_init(void **rep, const char *re, int sub)
+VRT_re_init(void **rep, const char *re)
{
- regex_t *t;
+ pcre *t;
+ const char *error;
+ int erroroffset;
- t = calloc(sizeof *t, 1);
- XXXAN(t);
/* This was already check-compiled by the VCL compiler */
- AZ(regcomp(t, re, REG_EXTENDED | REG_ICASE | (sub ? 0 : REG_NOSUB)));
+ t = pcre_compile(re, 0, &error, &erroroffset, NULL);
+ AN(t);
*rep = t;
}
@@ -64,23 +67,23 @@ VRT_re_fini(void *rep)
{
if (rep != NULL)
- regfree(rep);
+ pcre_free(rep);
}
int
VRT_re_match(const char *s, void *re)
{
- regex_t *t;
+ pcre *t;
int i;
if (s == NULL)
return (0);
AN(re);
t = re;
- i = regexec(t, s, 0, NULL, 0);
- if (i == 0)
+ i = pcre_exec(t, NULL, s, strlen(s), 0, 0, NULL, 0);
+ if (i >= 0)
return (1);
- assert(i == REG_NOMATCH);
+ assert(i == PCRE_ERROR_NOMATCH);
return (0);
}
@@ -88,8 +91,8 @@ const char *
VRT_regsub(const struct sess *sp, int all, const char *str, void *re,
const char *sub)
{
- regmatch_t pm[10];
- regex_t *t;
+ int ovector[30];
+ pcre *t;
int i, l;
txt res;
char *b0;
@@ -100,10 +103,11 @@ VRT_regsub(const struct sess *sp, int all, const char *str, void *re,
if (str == NULL)
return ("");
t = re;
- i = regexec(t, str, 10, pm, 0);
+ memset(&ovector, 0, sizeof(ovector));
+ i = pcre_exec(t, NULL, str, strlen(str), 0, 0, ovector, 30);
/* If it didn't match, we can return the original string */
- if (i == REG_NOMATCH)
+ if (i == PCRE_ERROR_NOMATCH)
return(str);
u = WS_Reserve(sp->http->ws, 0);
@@ -112,8 +116,7 @@ VRT_regsub(const struct sess *sp, int all, const char *str, void *re,
do {
/* Copy prefix to match */
- Tadd(&res, str, pm[0].rm_so);
-
+ Tadd(&res, str, ovector[0]);
for (s = sub ; *s != '\0'; s++ ) {
if (*s != '\\' || s[1] == '\0') {
if (res.b < res.e)
@@ -123,19 +126,20 @@ VRT_regsub(const struct sess *sp, int all, const char *str, void *re,
s++;
if (isdigit(*s)) {
x = *s - '0';
- l = pm[x].rm_eo - pm[x].rm_so;
- Tadd(&res, str + pm[x].rm_so, l);
+ l = ovector[2*x+1] - ovector[2*x];
+ Tadd(&res, str + ovector[2*x], l);
continue;
} else {
if (res.b < res.e)
*res.b++ = *s;
}
}
- str += pm[0].rm_eo;
+ str += ovector[1];
if (!all)
break;
- i = regexec(t, str, 10, pm, 0);
- } while (i != REG_NOMATCH);
+ memset(&ovector, 0, sizeof(ovector));
+ i = pcre_exec(t, NULL, str, strlen(str), 0, 0, ovector, 30);
+ } while (i != PCRE_ERROR_NOMATCH);
/* Copy suffix to match */
l = strlen(str) + 1;
diff --git a/varnish-cache/bin/varnishlog/Makefile.am b/varnish-cache/bin/varnishlog/Makefile.am
index 85c8b92..2dbd279 100644
--- a/varnish-cache/bin/varnishlog/Makefile.am
+++ b/varnish-cache/bin/varnishlog/Makefile.am
@@ -1,6 +1,6 @@
# $Id$
-INCLUDES = -I$(top_srcdir)/include
+INCLUDES = -I$(top_srcdir)/include @PCRE_CFLAGS@
bin_PROGRAMS = varnishlog
@@ -13,3 +13,4 @@ varnishlog_LDADD = \
$(top_builddir)/lib/libvarnishcompat/libvarnishcompat.la \
$(top_builddir)/lib/libvarnishapi/libvarnishapi.la \
${PTHREAD_LIBS}
+ @PCRE_LIBS@
diff --git a/varnish-cache/bin/varnishlog/varnishlog.c b/varnish-cache/bin/varnishlog/varnishlog.c
index 4e6245a..4c11981 100644
--- a/varnish-cache/bin/varnishlog/varnishlog.c
+++ b/varnish-cache/bin/varnishlog/varnishlog.c
@@ -36,7 +36,7 @@ SVNID("$Id$")
#include <errno.h>
#include <fcntl.h>
-#include <regex.h>
+#include <pcre.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
@@ -80,7 +80,7 @@ static enum shmlogtag last[65536];
#define F_MATCH (1 << 1)
static int match_tag = -1;
-static regex_t match_re;
+static pcre *match_re;
static void
h_order_finish(int fd)
@@ -116,6 +116,7 @@ h_order(void *priv, enum shmlogtag tag, unsigned fd, unsigned len,
unsigned spec, const char *ptr)
{
char type;
+ int ovector[30];
(void)priv;
@@ -132,7 +133,8 @@ h_order(void *priv, enum shmlogtag tag, unsigned fd, unsigned len,
assert(ob[fd] != NULL);
}
if (tag == match_tag &&
- !regexec(&match_re, ptr, 0, NULL, 0))
+ pcre_exec(match_re, NULL, ptr, len, 0, 0, ovector,
+ sizeof(ovector)/sizeof(ovector[0])) > 0)
flg[fd] |= F_MATCH;
if ((tag == SLT_BackendOpen || tag == SLT_SessionOpen ||
@@ -198,6 +200,8 @@ static void
do_order(struct VSL_data *vd, int argc, char **argv)
{
int i;
+ const char *error;
+ int erroroffset;
if (argc == 2) {
match_tag = name2tag(argv[0]);
@@ -205,11 +209,9 @@ do_order(struct VSL_data *vd, int argc, char **argv)
fprintf(stderr, "Tag \"%s\" unknown\n", argv[0]);
exit(2);
}
- i = regcomp(&match_re, argv[1], REG_EXTENDED | REG_NOSUB);
- if (i) {
- char buf[BUFSIZ];
- regerror(i, &match_re, buf, sizeof buf);
- fprintf(stderr, "%s\n", buf);
+ match_re = pcre_compile(argv[1], 0, &error, &erroroffset, NULL);
+ if (match_re == NULL) {
+ fprintf(stderr, "Invalid regex: %s\n", error);
exit(2);
}
}
diff --git a/varnish-cache/configure.ac b/varnish-cache/configure.ac
index 5c2d67f..4fc88a5 100644
--- a/varnish-cache/configure.ac
+++ b/varnish-cache/configure.ac
@@ -75,6 +75,37 @@ AC_SUBST(NET_LIBS)
AC_CHECK_LIBM
AC_SUBST(LIBM)
+PKG_PROG_PKG_CONFIG
+if test -n $PKG_CONFIG; then
+ PKG_CHECK_MODULES([PCRE], [libpcre])
+else
+ AC_CHECK_PROG(PCRE_CONFIG, pcre-config, pcre-config)
+ AC_ARG_WITH(pcre-config,
+ AS_HELP_STRING([--with-pcre-config=PATH],
+ [Location of PCRE pcre-config (auto)]),
+ [pcre_config="$withval"],
+ [pcre_config=""])
+
+ if test "x$pcre_config" != "x" ; then
+ AC_MSG_CHECKING(for $pcre_config)
+
+ if test -f $pcre_config ; then
+ PCRE_CONFIG=$pcre_config
+ AC_MSG_RESULT(yes)
+ else
+ AC_MSG_RESULT(no - searching PATH)
+ fi
+ fi
+ if test "x$PCRE_CONFIG" = "x"; then
+ AC_CHECK_PROGS(PCRE_CONFIG, pcre-config)
+ fi
+ PCRE_CFLAGS=`$PCRE_CONFIG --cflags`
+ PCRE_LIBS=`$PCRE_CONFIG --libs`
+fi
+AC_SUBST(PCRE_CFLAGS)
+AC_SUBST(PCRE_LIBS)
+
+
# Checks for header files.
AC_HEADER_STDC
AC_HEADER_SYS_WAIT
diff --git a/varnish-cache/include/vrt.h b/varnish-cache/include/vrt.h
index 150db3c..17dbf25 100644
--- a/varnish-cache/include/vrt.h
+++ b/varnish-cache/include/vrt.h
@@ -136,7 +136,7 @@ struct vrt_ref {
void VRT_acl_log(const struct sess *, const char *msg);
/* Regexp related */
-void VRT_re_init(void **, const char *, int sub);
+void VRT_re_init(void **, const char *);
void VRT_re_fini(void *);
int VRT_re_match(const char *, void *re);
const char *VRT_regsub(const struct sess *sp, int all, const char *,
diff --git a/varnish-cache/lib/libvarnishapi/Makefile.am b/varnish-cache/lib/libvarnishapi/Makefile.am
index b109811..4210d46 100644
--- a/varnish-cache/lib/libvarnishapi/Makefile.am
+++ b/varnish-cache/lib/libvarnishapi/Makefile.am
@@ -1,6 +1,8 @@
# $Id$
-INCLUDES = -I$(top_srcdir)/include
+INCLUDES = -I$(top_srcdir)/include @PCRE_CFLAGS@
+
+LIBS = @PCRE_LIBS@
lib_LTLIBRARIES = libvarnishapi.la
diff --git a/varnish-cache/lib/libvarnishapi/shmlog.c b/varnish-cache/lib/libvarnishapi/shmlog.c
index 37be28a..78be38a 100644
--- a/varnish-cache/lib/libvarnishapi/shmlog.c
+++ b/varnish-cache/lib/libvarnishapi/shmlog.c
@@ -40,7 +40,7 @@ SVNID("$Id$")
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
-#include <regex.h>
+#include <pcre.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -84,8 +84,8 @@ struct VSL_data {
#define M_SELECT (1 << 3)
int regflags;
- regex_t *regincl;
- regex_t *regexcl;
+ pcre *regincl;
+ pcre *regexcl;
unsigned long skip;
unsigned long keep;
@@ -170,7 +170,7 @@ VSL_New(void)
assert(VSL_S_BACKEND == M_BACKEND);
vd = calloc(sizeof *vd, 1);
assert(vd != NULL);
- vd->regflags = REG_EXTENDED | REG_NOSUB;
+ vd->regflags = 0;
vd->magic = VSL_MAGIC;
vd->fd = -1;
return (vd);
@@ -272,9 +272,9 @@ int
VSL_NextLog(struct VSL_data *vd, unsigned char **pp)
{
unsigned char *p;
- regmatch_t rm;
unsigned u, l;
int i;
+ int ovector[30];
CHECK_OBJ_NOTNULL(vd, VSL_MAGIC);
while (1) {
@@ -315,19 +315,23 @@ VSL_NextLog(struct VSL_data *vd, unsigned char **pp)
if (vd->c_opt && !(vd->map[u] & M_CLIENT))
continue;
if (vd->regincl != NULL) {
- rm.rm_so = 0;
- rm.rm_eo = l;
- i = regexec(vd->regincl,
- (char *)p + SHMLOG_DATA, 1, &rm, 0);
- if (i == REG_NOMATCH)
+ i = pcre_exec(vd->regincl,
+ NULL, /* We didn't study the pattern*/
+ (char *)p + SHMLOG_DATA,
+ SHMLOG_LEN(p) - SHMLOG_DATA, /* Length */
+ 0, 0, ovector,
+ sizeof(ovector)/sizeof(ovector[0]));
+ if (i == PCRE_ERROR_NOMATCH)
continue;
}
if (vd->regexcl != NULL) {
- rm.rm_so = 0;
- rm.rm_eo = l;
- i = regexec(vd->regexcl,
- (char *)p + SHMLOG_DATA, 1, &rm, 0);
- if (i != REG_NOMATCH)
+ i = pcre_exec(vd->regincl,
+ NULL, /* We didn't study the pattern*/
+ (char *)p + SHMLOG_DATA,
+ SHMLOG_LEN(p) - SHMLOG_DATA, /* Length */
+ 0, 0, ovector,
+ sizeof(ovector)/sizeof(ovector[0]));
+ if (i != PCRE_ERROR_NOMATCH)
continue;
}
*pp = p;
@@ -412,9 +416,9 @@ vsl_r_arg(struct VSL_data *vd, const char *opt)
static int
vsl_IX_arg(struct VSL_data *vd, const char *opt, int arg)
{
- int i;
- regex_t **rp;
- char buf[BUFSIZ];
+ pcre **rp;
+ const char *error;
+ int erroroffset;
CHECK_OBJ_NOTNULL(vd, VSL_MAGIC);
if (arg == 'I')
@@ -425,15 +429,9 @@ vsl_IX_arg(struct VSL_data *vd, const char *opt, int arg)
fprintf(stderr, "Option %c can only be given once", arg);
return (-1);
}
- *rp = calloc(sizeof(regex_t), 1);
+ *rp = pcre_compile(opt, vd->regflags, &error, &erroroffset, NULL);
if (*rp == NULL) {
- perror("malloc");
- return (-1);
- }
- i = regcomp(*rp, opt, vd->regflags);
- if (i) {
- regerror(i, *rp, buf, sizeof buf);
- fprintf(stderr, "%s", buf);
+ fprintf(stderr, "Illegal regex: %s\n", error);
return (-1);
}
return (1);
@@ -547,7 +545,7 @@ VSL_Arg(struct VSL_data *vd, int arg, const char *opt)
case 'i': case 'x': return (vsl_ix_arg(vd, opt, arg));
case 'r': return (vsl_r_arg(vd, opt));
case 'I': case 'X': return (vsl_IX_arg(vd, opt, arg));
- case 'C': vd->regflags = REG_ICASE; return (1);
+ case 'C': vd->regflags = PCRE_CASELESS; return (1);
case 's': return (vsl_s_arg(vd, opt));
case 'k': return (vsl_k_arg(vd, opt));
default:
diff --git a/varnish-cache/lib/libvcl/Makefile.am b/varnish-cache/lib/libvcl/Makefile.am
index 4bb2e4b..6d98e43 100644
--- a/varnish-cache/lib/libvcl/Makefile.am
+++ b/varnish-cache/lib/libvcl/Makefile.am
@@ -1,6 +1,8 @@
# $Id$
-INCLUDES = -I$(top_srcdir)/include
+INCLUDES = -I$(top_srcdir)/include @PCRE_CFLAGS@
+
+LDADD = @PCRE_LIBS@
lib_LTLIBRARIES = libvcl.la
diff --git a/varnish-cache/lib/libvcl/vcc_compile.h b/varnish-cache/lib/libvcl/vcc_compile.h
index 256da13..be44bfb 100644
--- a/varnish-cache/lib/libvcl/vcc_compile.h
+++ b/varnish-cache/lib/libvcl/vcc_compile.h
@@ -198,7 +198,7 @@ unsigned vcc_UintVal(struct tokenlist *tl);
double vcc_DoubleVal(struct tokenlist *tl);
/* vcc_string.c */
-char *vcc_regexp(struct tokenlist *tl, int sub);
+char *vcc_regexp(struct tokenlist *tl);
int vcc_StringVal(struct tokenlist *tl);
void vcc_ExpectedStringval(struct tokenlist *tl);
diff --git a/varnish-cache/lib/libvcl/vcc_parse.c b/varnish-cache/lib/libvcl/vcc_parse.c
index d6079f2..ef2b09a 100644
--- a/varnish-cache/lib/libvcl/vcc_parse.c
+++ b/varnish-cache/lib/libvcl/vcc_parse.c
@@ -225,7 +225,7 @@ Cond_String(const struct var *vp, struct tokenlist *tl)
tl->t->tok == '~' ? "" : "!");
vcc_NextToken(tl);
ExpectErr(tl, CSTR);
- p = vcc_regexp(tl, 0);
+ p = vcc_regexp(tl);
ERRCHK(tl);
vcc_NextToken(tl);
Fb(tl, 1, "%s, %s)\n", vp->rname, p);
diff --git a/varnish-cache/lib/libvcl/vcc_string.c b/varnish-cache/lib/libvcl/vcc_string.c
index 564e3da..7fe34b7 100644
--- a/varnish-cache/lib/libvcl/vcc_string.c
+++ b/varnish-cache/lib/libvcl/vcc_string.c
@@ -34,7 +34,7 @@ SVNID("$Id$")
#include <stdio.h>
#include <string.h>
-#include <regex.h>
+#include <pcre.h>
#include "vsb.h"
@@ -47,26 +47,25 @@ SVNID("$Id$")
/*--------------------------------------------------------------------*/
char *
-vcc_regexp(struct tokenlist *tl, int sub)
+vcc_regexp(struct tokenlist *tl)
{
char buf[BUFSIZ], *p;
- regex_t t;
- int i;
+ pcre *t;
+ const char *error;
+ int erroroffset;
Expect(tl, CSTR);
if (tl->err)
return (NULL);
memset(&t, 0, sizeof t);
- i = regcomp(&t, tl->t->dec, REG_EXTENDED | (sub ? 0 : REG_NOSUB));
- if (i != 0) {
- (void)regerror(i, &t, buf, sizeof buf);
+ t = pcre_compile(tl->t->dec, 0, &error, &erroroffset, NULL);
+ if (t == NULL) {
vsb_printf(tl->sb,
- "Regexp compilation error:\n\n%s\n\n", buf);
+ "Regexp compilation error:\n\n%s\n\n", error);
vcc_ErrWhere(tl, tl->t);
- regfree(&t);
return (NULL);
}
- regfree(&t);
+ pcre_free(t);
sprintf(buf, "VGC_re_%u", tl->recnt++);
p = TlAlloc(tl, strlen(buf) + 1);
strcpy(p, buf);
@@ -74,7 +73,7 @@ vcc_regexp(struct tokenlist *tl, int sub)
Fh(tl, 0, "static void *%s;\n", buf);
Fi(tl, 0, "\tVRT_re_init(&%s, ",buf);
EncToken(tl->fi, tl->t);
- Fi(tl, 0, ", %d);\n", sub);
+ Fi(tl, 0, ");\n");
Ff(tl, 0, "\tVRT_re_fini(%s);\n", buf);
return (p);
}
@@ -108,7 +107,7 @@ vcc_regsub(struct tokenlist *tl, int all)
Expect(tl, CSTR);
if (tl->err)
return (0);
- p = vcc_regexp(tl, 1);
+ p = vcc_regexp(tl);
vcc_NextToken(tl);
Fb(tl, 0, ", %s, ", p);
--
1.6.3.3
--
Tollef Fog Heen
Redpill Linpro -- Changing the game!
t: +47 21 54 41 73
More information about the varnish-dev
mailing list