Commit dccd2814 authored by Poul-Henning Kamp's avatar Poul-Henning Kamp

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
parent 35db7bbb
......@@ -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);
}
}
......@@ -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);
......
......@@ -41,4 +41,5 @@ VCC_TYPE(IP)
VCC_TYPE(HEADER)
VCC_TYPE(BYTES)
VCC_TYPE(REAL)
VCC_TYPE(ENUM)
/*lint -restore */
......@@ -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):
......
......@@ -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
})
......@@ -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");
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment