[master] dccd281 Add an "ENUM" type as a possible argument to VMOD functions.
Poul-Henning Kamp
phk at varnish-cache.org
Mon Jan 31 22:50:42 CET 2011
commit dccd2814066fc9c228b3e44887062c3d6c54ee2b
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date: Mon Jan 31 21:49:03 2011 +0000
Add an "ENUM" type as a possible argument to VMOD functions.
VCC expects an ID, and complains if it is not on the list of
valid values. The value is passed as a "const char *"
More and better error messages from vmod.py
diff --git a/bin/varnishtest/tests/m00000.vtc b/bin/varnishtest/tests/m00000.vtc
index 7ad2054..7874836 100644
--- a/bin/varnishtest/tests/m00000.vtc
+++ b/bin/varnishtest/tests/m00000.vtc
@@ -13,6 +13,7 @@ varnish v1 -vcl+backend {
sub vcl_deliver {
set resp.http.foo = std.toupper(resp.http.foo);
set resp.http.bar = std.tolower(resp.http.bar);
+ set resp.http.who = std.author(phk);
std.log("VCL initiated log");
std.syslog(8 + 7, "Somebody runs varnishtest");
}
@@ -26,3 +27,10 @@ client c1 {
expect resp.http.foo == "BAR"
expect resp.http.bar == "foo"
} -run
+
+varnish v1 -badvcl {
+ import std from "${topbuild}/lib/libvmod_std/.libs/libvmod_std.so.1" ;
+ sub vcl_deliver {
+ set resp.http.who = std.author(jfk);
+ }
+}
diff --git a/lib/libvcl/vcc_expr.c b/lib/libvcl/vcc_expr.c
index ff3fb48..1a5b074 100644
--- a/lib/libvcl/vcc_expr.c
+++ b/lib/libvcl/vcc_expr.c
@@ -550,6 +550,32 @@ vcc_Eval_Func(struct vcc *tl, struct expr **e, const struct symbol *sym)
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')
+ SkipToken(tl, ',');
} else {
vcc_expr0(tl, &e1, fmt);
ERRCHK(tl);
diff --git a/lib/libvcl/vcc_types.h b/lib/libvcl/vcc_types.h
index 94399e7..aeaec90 100644
--- a/lib/libvcl/vcc_types.h
+++ b/lib/libvcl/vcc_types.h
@@ -41,4 +41,5 @@ VCC_TYPE(IP)
VCC_TYPE(HEADER)
VCC_TYPE(BYTES)
VCC_TYPE(REAL)
+VCC_TYPE(ENUM)
/*lint -restore */
diff --git a/lib/libvmod_std/vmod.py b/lib/libvmod_std/vmod.py
index f751e82..7d751cb 100755
--- a/lib/libvmod_std/vmod.py
+++ b/lib/libvmod_std/vmod.py
@@ -53,6 +53,7 @@ ctypes = {
'STRING_LIST': "const char *, ...",
'BOOL': "unsigned",
'BACKEND': "struct director *",
+ 'ENUM': "const char *",
'TIME': "double",
'REAL': "double",
'DURATION': "double",
@@ -73,7 +74,7 @@ tdl = ""
plist = ""
slist = ""
-def do_func(fname, rval, args):
+def do_func(fname, rval, args, vargs):
global pstruct
global pinit
global plist
@@ -81,27 +82,33 @@ def do_func(fname, rval, args):
global tdl
#print(fname, rval, args)
- proto = ctypes[rval] + " vmod_" + fname + "(struct sess *"
- sproto = ctypes[rval] + " td_" + modname + "_" + fname + "(struct sess *"
- s=", "
+ # C argument list
+ cargs = "(struct sess *"
for i in args:
- proto += s + ctypes[i]
- sproto += s + ctypes[i]
- proto += ")"
- sproto += ")"
+ cargs += ", " + i
+ cargs += ")"
+ # Prototypes for vmod implementation and interface typedef
+ proto = ctypes[rval] + " vmod_" + fname + cargs
+ sproto = ctypes[rval] + " td_" + modname + "_" + fname + cargs
+
+ # append to lists of prototypes
plist += proto + ";\n"
tdl += "typedef " + sproto + ";\n"
+ # Append to struct members
pstruct += "\ttd_" + modname + "_" + fname + "\t*" + fname + ";\n"
+
+ # Append to struct initializer
pinit += "\tvmod_" + fname + ",\n"
+ # Compose the vmod spec-string
s = modname + '.' + fname + "\\0"
s += "Vmod_Func_" + modname + "." + fname + "\\0"
- s += rval
- for i in args:
- s += '\\0' + i
- slist += '\t"' + s + '\\0",\n'
+ s += rval + '\\0'
+ for i in vargs:
+ s += i + '\\0'
+ slist += '\t"' + s + '",\n'
#######################################################################
@@ -115,6 +122,30 @@ def partition(string, separator):
#######################################################################
+def is_c_name(s):
+ return None != re.match("^[a-z][a-z0-9_]*$", s)
+
+#######################################################################
+
+def parse_enum(tq):
+ assert tq[0] == '{'
+ assert tq[-1] == '}'
+ f = tq[1:-1].split(',')
+ s="ENUM\\0"
+ b=dict()
+ for i in f:
+ i = i.strip()
+ if not is_c_name(i):
+ raise Exception("Enum value '%s' is illegal" % i)
+ if i in b:
+ raise Exception("Duplicate Enum value '%s'" % i)
+ b[i] = True
+ s = s + i.strip() + '\\0'
+ s = s + '\\0'
+ return s
+
+#######################################################################
+
f = open(specfile, "r")
def nextline():
@@ -127,9 +158,6 @@ def nextline():
if l0 != "":
return l0
-def is_c_name(s):
- return None != re.match("^[a-z][a-z0-9_]*$", s)
-
while True:
l0 = nextline()
if l0 == "":
@@ -184,6 +212,7 @@ while True:
l = l[:-1]
args = list()
+ vargs = list()
for i in re.finditer("([A-Z_]+)\s*({[^}]+})?(,|$)", l):
at = i.group(1)
@@ -191,9 +220,22 @@ while True:
if at not in ctypes:
raise Exception(
"Argument type '%s' not a valid type" % at)
- args.append(at)
- do_func(fname, rt_type, args)
+ args.append(ctypes[at])
+
+ if at == "ENUM":
+ if tq == None:
+ raise Exception(
+ "Argument type '%s' needs qualifier {...}" % at)
+ at=parse_enum(tq)
+
+ elif tq != None:
+ raise Exception(
+ "Argument type '%s' cannot be qualified with {...}" % at)
+
+ vargs.append(at)
+
+ do_func(fname, rt_type, args, vargs)
#######################################################################
def dumps(s):
diff --git a/lib/libvmod_std/vmod.vcc b/lib/libvmod_std/vmod.vcc
index ffb99b0..b2923dc 100644
--- a/lib/libvmod_std/vmod.vcc
+++ b/lib/libvmod_std/vmod.vcc
@@ -34,3 +34,9 @@ Function REAL random(REAL, REAL)
Function VOID log(STRING_LIST)
Function VOID syslog(INT, STRING_LIST)
Function STRING fileread(PRIV_CALL, STRING)
+Function STRING author(ENUM {
+ phk,
+ des,
+ kristian,
+ mithrandir
+})
diff --git a/lib/libvmod_std/vmod_std.c b/lib/libvmod_std/vmod_std.c
index c6a51ea..2807af1 100644
--- a/lib/libvmod_std/vmod_std.c
+++ b/lib/libvmod_std/vmod_std.c
@@ -161,3 +161,18 @@ vmod_syslog(struct sess *sp, int fac, const char *fmt, ...)
if (p != NULL)
syslog(fac, "%s", buf);
}
+
+const char * __match_proto__()
+vmod_author(struct sess *sp, const char *id)
+{
+ (void)sp;
+ if (!strcmp(id, "phk"))
+ return ("Poul-Henning");
+ if (!strcmp(id, "des"))
+ return ("Dag-Erling");
+ if (!strcmp(id, "kristian"))
+ return ("Kristian");
+ if (!strcmp(id, "mithrandir"))
+ return ("Tollef");
+ WRONG("Illegal VMOD enum");
+}
More information about the varnish-commit
mailing list