
martin at varnish-cache
May 10, 2012, 1:42 AM
Post #1 of 1
(46 views)
Permalink
|
|
[master] 0351ac9 Move lib/libvmod_std/vmod.py to lib/libvcl/vmodtool.py
|
|
commit 0351ac952b100d311d77dd77036c2976e5937661 Author: Martin Blix Grydeland <martin [at] varnish-software> Date: Tue Feb 28 14:41:49 2012 +0100 Move lib/libvmod_std/vmod.py to lib/libvcl/vmodtool.py Move it to a more natural home, as it is not really about libvmod_std, and give it a name that matches it's function (inspired from libtool) diff --git a/lib/libvcl/Makefile.am b/lib/libvcl/Makefile.am index f135e43..ad16981 100644 --- a/lib/libvcl/Makefile.am +++ b/lib/libvcl/Makefile.am @@ -31,7 +31,8 @@ libvcl_la_SOURCES = \ vcc_xref.c EXTRA_DIST = \ - generate.py + generate.py \ + vmodtool.py vcc_obj.c vcc_fixed_token.c vcc_token_defs.h: \ $(srcdir)/generate.py $(top_srcdir)/include/vrt.h diff --git a/lib/libvcl/vmodtool.py b/lib/libvcl/vmodtool.py new file mode 100755 index 0000000..041edcb --- /dev/null +++ b/lib/libvcl/vmodtool.py @@ -0,0 +1,321 @@ +#!/usr/local/bin/python +#- +# Copyright (c) 2010-2011 Varnish Software AS +# All rights reserved. +# +# Author: Poul-Henning Kamp <phk [at] phk> +# +# 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 = { + 'IP': "struct sockaddr_storage *", + 'STRING': "const char *", + 'STRING_LIST': "const char *, ...", + 'BOOL': "unsigned", + 'BACKEND': "struct director *", + 'ENUM': "const char *", + 'TIME': "double", + 'REAL': "double", + 'DURATION': "double", + 'INT': "int", + 'HEADER': "enum gethdr_e, const char *", + 'PRIV_VCL': "struct vmod_priv *", + 'PRIV_CALL': "struct vmod_priv *", + 'VOID': "void", +} + +####################################################################### + +initname = "" +modname = "???" +pstruct = "" +pinit = "" +tdl = "" +plist = "" +slist = "" + +def do_func(fname, rval, args, vargs): + global pstruct + global pinit + global plist + global slist + global tdl + #print(fname, rval, args) + + # C argument list + cargs = "(struct sess *" + for i in args: + 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 + '\\0' + for i in vargs: + s += i + '\\0' + slist += '\t"' + s + '",\n' + +####################################################################### + +def partition(string, separator): + if (hasattr(string,"partition")): + return string.partition(separator) + i = string.find(separator) + if i >= 0: + return (string[:i],separator,string[i+len(separator):]) + return (string, '', '') + +####################################################################### + +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' + return s + +####################################################################### + +f = open(specfile, "r") + +def nextline(): + while True: + l0 = f.readline() + if l0 == "": + return l0 + l0 = re.sub("#.*$", "", l0) + l0 = re.sub("\s\s*", " ", l0.strip()) + if l0 != "": + return l0 + +while True: + l0 = nextline() + if l0 == "": + break; + l = partition(l0, " ") + + if l[0] == "Module": + modname = l[2].strip(); + if not is_c_name(modname): + raise Exception("Module name '%s' is illegal" % modname) + continue + + if l[0] == "Init": + initname = l[2].strip(); + if not is_c_name(initname): + raise Exception("Init name '%s' is illegal" % initname) + continue + + if l[0] != "Function": + raise Exception("Expected 'Function' line, got '%s'" % l[0]) + + # Find the return type of the function + l = partition(l[2].strip(), " ") + rt_type = l[0] + if rt_type not in ctypes: + raise Exception("Return type '%s' not a valid type" % rt_type) + + # Find the function name + l = partition(l[2].strip(), "(") + + fname = l[0].strip() + if not is_c_name(fname): + raise Exception("Function name '%s' is illegal" % fname) + + if l[1] != '(': + raise Exception("Missing '('") + + l = l[2] + + while -1 == l.find(")"): + l1 = nextline() + if l1 == "": + raise Exception("End Of Input looking for ')'") + l = l + l1 + + if -1 != l.find("("): + raise Exception("Nesting trouble with '(...)' ") + + if l[-1:] != ')': + raise Exception("Junk after ')'") + + l = l[:-1] + + args = list() + vargs = list() + + for i in re.finditer("([A-Z_]+)\s*({[^}]+})?(,|$)", l): + at = i.group(1) + tq = i.group(2) + if at not in ctypes: + raise Exception( + "Argument type '%s' not a valid type" % at) + + 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): + while True: + l = partition(s, "\n") + if len(l[0]) == 0: + break + fc.write('\t"' + l[0] + '\\n"\n') + s = l[2] + +####################################################################### + +if initname != "": + plist += "int " + initname + plist += "(struct vmod_priv *, const struct VCL_conf *);\n" + pstruct += "\tvmod_init_f\t*_init;\n" + pinit += "\t" + initname + ",\n" + slist += '\t"INIT\\0Vmod_Func_' + modname + '._init",\n' + +####################################################################### + +def file_header(fo): + fo.write("""/* + * NB: This file is machine generated, DO NOT EDIT! + * + * Edit vmod.vcc and run vmod.py instead + */ + +""") + +####################################################################### + +fc = open("vcc_if.c", "w") +fh = open("vcc_if.h", "w") + +file_header(fc) +file_header(fh) + +fh.write('struct sess;\n') +fh.write('struct VCL_conf;\n') +fh.write('struct vmod_priv;\n') +fh.write("\n"); + +fh.write(plist) + + +fc.write('#include "config.h"\n') +fc.write('\n') +fc.write('#include "vrt.h"\n') +fc.write('#include "vcc_if.h"\n') +fc.write('#include "vmod_abi.h"\n') +fc.write("\n"); + +fc.write("\n"); + +fc.write(tdl); +fc.write("\n"); + +fc.write('const char Vmod_Name[] = "' + modname + '";\n') + +fc.write("const struct Vmod_Func_" + modname + " {\n") +fc.write(pstruct + "} Vmod_Func = {\n" + pinit + "};\n") +fc.write("\n"); + +fc.write("const int Vmod_Len = sizeof(Vmod_Func);\n") +fc.write("\n"); + +fc.write('const char Vmod_Proto[] =\n') +dumps(tdl); +fc.write('\t"\\n"\n') +dumps("struct Vmod_Func_" + modname + " {\n") +dumps(pstruct + "} Vmod_Func_" + modname + ";\n") +fc.write('\t;\n') +fc.write("\n"); + +fc.write('const char * const Vmod_Spec[] = {\n' + slist + '\t0\n};\n') + +fc.write('const char Vmod_Varnish_ABI[] = VMOD_ABI_Version;\n') + +fh.write('extern const void * const Vmod_Id;\n') +fc.write('const void * const Vmod_Id = &Vmod_Id;\n') + +fc.write("\n") + diff --git a/lib/libvmod_std/Makefile.am b/lib/libvmod_std/Makefile.am index c4128ea..a872837 100644 --- a/lib/libvmod_std/Makefile.am +++ b/lib/libvmod_std/Makefile.am @@ -9,6 +9,7 @@ dist_man_MANS = vmod_std.3 vmoddir = $(pkglibdir)/vmods vmod_srcdir = $(top_srcdir)/lib/libvmod_std +vmodtool = $(top_srcdir)/lib/libvcl/vmodtool.py vmod_LTLIBRARIES = libvmod_std.la libvmod_std_la_LDFLAGS = -module -export-dynamic -avoid-version @@ -20,10 +21,10 @@ libvmod_std_la_SOURCES = \ vmod_std_fileread.c \ vmod_std_conversions.c -vcc_if.c vcc_if.h: $(vmod_srcdir)/vmod.py $(vmod_srcdir)/vmod.vcc - @PYTHON@ $(vmod_srcdir)/vmod.py $(vmod_srcdir)/vmod.vcc +vcc_if.c vcc_if.h: $(vmodtool) $(vmod_srcdir)/vmod.vcc + @PYTHON@ $(vmodtool) $(vmod_srcdir)/vmod.vcc -EXTRA_DIST = vmod.py vmod.vcc +EXTRA_DIST = vmod.vcc CLEANFILES = $(builddir)/vcc_if.c $(builddir)/vcc_if.h diff --git a/lib/libvmod_std/vmod.py b/lib/libvmod_std/vmod.py deleted file mode 100755 index 041edcb..0000000 --- a/lib/libvmod_std/vmod.py +++ /dev/null @@ -1,321 +0,0 @@ -#!/usr/local/bin/python -#- -# Copyright (c) 2010-2011 Varnish Software AS -# All rights reserved. -# -# Author: Poul-Henning Kamp <phk [at] phk> -# -# 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 = { - 'IP': "struct sockaddr_storage *", - 'STRING': "const char *", - 'STRING_LIST': "const char *, ...", - 'BOOL': "unsigned", - 'BACKEND': "struct director *", - 'ENUM': "const char *", - 'TIME': "double", - 'REAL': "double", - 'DURATION': "double", - 'INT': "int", - 'HEADER': "enum gethdr_e, const char *", - 'PRIV_VCL': "struct vmod_priv *", - 'PRIV_CALL': "struct vmod_priv *", - 'VOID': "void", -} - -####################################################################### - -initname = "" -modname = "???" -pstruct = "" -pinit = "" -tdl = "" -plist = "" -slist = "" - -def do_func(fname, rval, args, vargs): - global pstruct - global pinit - global plist - global slist - global tdl - #print(fname, rval, args) - - # C argument list - cargs = "(struct sess *" - for i in args: - 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 + '\\0' - for i in vargs: - s += i + '\\0' - slist += '\t"' + s + '",\n' - -####################################################################### - -def partition(string, separator): - if (hasattr(string,"partition")): - return string.partition(separator) - i = string.find(separator) - if i >= 0: - return (string[:i],separator,string[i+len(separator):]) - return (string, '', '') - -####################################################################### - -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' - return s - -####################################################################### - -f = open(specfile, "r") - -def nextline(): - while True: - l0 = f.readline() - if l0 == "": - return l0 - l0 = re.sub("#.*$", "", l0) - l0 = re.sub("\s\s*", " ", l0.strip()) - if l0 != "": - return l0 - -while True: - l0 = nextline() - if l0 == "": - break; - l = partition(l0, " ") - - if l[0] == "Module": - modname = l[2].strip(); - if not is_c_name(modname): - raise Exception("Module name '%s' is illegal" % modname) - continue - - if l[0] == "Init": - initname = l[2].strip(); - if not is_c_name(initname): - raise Exception("Init name '%s' is illegal" % initname) - continue - - if l[0] != "Function": - raise Exception("Expected 'Function' line, got '%s'" % l[0]) - - # Find the return type of the function - l = partition(l[2].strip(), " ") - rt_type = l[0] - if rt_type not in ctypes: - raise Exception("Return type '%s' not a valid type" % rt_type) - - # Find the function name - l = partition(l[2].strip(), "(") - - fname = l[0].strip() - if not is_c_name(fname): - raise Exception("Function name '%s' is illegal" % fname) - - if l[1] != '(': - raise Exception("Missing '('") - - l = l[2] - - while -1 == l.find(")"): - l1 = nextline() - if l1 == "": - raise Exception("End Of Input looking for ')'") - l = l + l1 - - if -1 != l.find("("): - raise Exception("Nesting trouble with '(...)' ") - - if l[-1:] != ')': - raise Exception("Junk after ')'") - - l = l[:-1] - - args = list() - vargs = list() - - for i in re.finditer("([A-Z_]+)\s*({[^}]+})?(,|$)", l): - at = i.group(1) - tq = i.group(2) - if at not in ctypes: - raise Exception( - "Argument type '%s' not a valid type" % at) - - 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): - while True: - l = partition(s, "\n") - if len(l[0]) == 0: - break - fc.write('\t"' + l[0] + '\\n"\n') - s = l[2] - -####################################################################### - -if initname != "": - plist += "int " + initname - plist += "(struct vmod_priv *, const struct VCL_conf *);\n" - pstruct += "\tvmod_init_f\t*_init;\n" - pinit += "\t" + initname + ",\n" - slist += '\t"INIT\\0Vmod_Func_' + modname + '._init",\n' - -####################################################################### - -def file_header(fo): - fo.write("""/* - * NB: This file is machine generated, DO NOT EDIT! - * - * Edit vmod.vcc and run vmod.py instead - */ - -""") - -####################################################################### - -fc = open("vcc_if.c", "w") -fh = open("vcc_if.h", "w") - -file_header(fc) -file_header(fh) - -fh.write('struct sess;\n') -fh.write('struct VCL_conf;\n') -fh.write('struct vmod_priv;\n') -fh.write("\n"); - -fh.write(plist) - - -fc.write('#include "config.h"\n') -fc.write('\n') -fc.write('#include "vrt.h"\n') -fc.write('#include "vcc_if.h"\n') -fc.write('#include "vmod_abi.h"\n') -fc.write("\n"); - -fc.write("\n"); - -fc.write(tdl); -fc.write("\n"); - -fc.write('const char Vmod_Name[] = "' + modname + '";\n') - -fc.write("const struct Vmod_Func_" + modname + " {\n") -fc.write(pstruct + "} Vmod_Func = {\n" + pinit + "};\n") -fc.write("\n"); - -fc.write("const int Vmod_Len = sizeof(Vmod_Func);\n") -fc.write("\n"); - -fc.write('const char Vmod_Proto[] =\n') -dumps(tdl); -fc.write('\t"\\n"\n') -dumps("struct Vmod_Func_" + modname + " {\n") -dumps(pstruct + "} Vmod_Func_" + modname + ";\n") -fc.write('\t;\n') -fc.write("\n"); - -fc.write('const char * const Vmod_Spec[] = {\n' + slist + '\t0\n};\n') - -fc.write('const char Vmod_Varnish_ABI[] = VMOD_ABI_Version;\n') - -fh.write('extern const void * const Vmod_Id;\n') -fc.write('const void * const Vmod_Id = &Vmod_Id;\n') - -fc.write("\n") - _______________________________________________ varnish-commit mailing list varnish-commit [at] varnish-cache https://www.varnish-cache.org/lists/mailman/listinfo/varnish-commit
|