[master] e446c07 More restructuring

Poul-Henning Kamp phk at FreeBSD.org
Fri Mar 2 14:16:08 UTC 2018


commit e446c076a8ccbc8db7832add1776748b7b6fc5b0
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Fri Mar 2 10:59:34 2018 +0000

    More restructuring

diff --git a/lib/libvcc/vmodtool.py b/lib/libvcc/vmodtool.py
index e995ab3..aee9756 100755
--- a/lib/libvcc/vmodtool.py
+++ b/lib/libvcc/vmodtool.py
@@ -45,8 +45,6 @@ import random
 import copy
 import json
 
-strict_abi = True
-
 AMBOILERPLATE = '''
 # Boilerplate generated by vmodtool.py - changes will be overwritten
 
@@ -166,9 +164,18 @@ def lwrap(s, width=64):
         p = "    "
     if len(s) > 0:
         ll.append(p + s)
-    return ll
+    return "\n".join(ll) + "\n"
 
 
+def fmt_cstruct(fo, mn, x):
+    """
+    Align fields in C struct
+    """
+    a = "\ttd_" + mn + "_" + x
+    while len(a.expandtabs()) < 40:
+        a += "\t"
+    fo.write("%s*%s;\n" % (a, x))
+
 #######################################################################
 
 
@@ -184,21 +191,11 @@ def err(str, warn=True):
     else:
         print("WARNING: " + str, file=sys.stderr)
 
-
-def fmt_cstruct(fo, mn, x):
-    a = "\ttd_" + mn + "_" + x
-    while len(a.expandtabs()) < 40:
-        a += "\t"
-    fo.write("%s*%s;\n" % (a, x))
-
 #######################################################################
 
 
-enum_values = {}
-
-
 class ctype(object):
-    def __init__(self, wl):
+    def __init__(self, wl, enums):
         self.nm = None
         self.defval = None
         self.spec = None
@@ -210,7 +207,7 @@ class ctype(object):
         if len(wl) > 0 and wl[0] == "{":
             if self.vt != "ENUM":
                 err("Only ENUMs take {...} specs", warn=False)
-            self.add_spec(wl)
+            self.add_spec(wl, enums)
 
     def __str__(self):
         s = "<" + self.vt
@@ -222,15 +219,7 @@ class ctype(object):
             s += " SPEC=" + str(self.spec)
         return s + ">"
 
-    def set_defval(self, x):
-        if self.vt == "ENUM":
-            if x[0] == '"' and x[-1] == '"':
-                x = x[1:-1]
-            elif x[0] == "'" and x[-1] == "'":
-                x = x[1:-1]
-        self.defval = x
-
-    def add_spec(self, wl):
+    def add_spec(self, wl, enums):
         assert self.vt == "ENUM"
         assert wl.pop(0) == "{"
         self.spec = []
@@ -242,7 +231,7 @@ class ctype(object):
                 x = x[1:-1]
             assert len(x) > 0
             self.spec.append(x)
-            enum_values[x] = True
+            enums[x] = True
             w = wl.pop(0)
             if w == "}":
                 break
@@ -261,10 +250,48 @@ class ctype(object):
         return self.vt
 
     def json(self, jl):
-        jl.append([self.vt, self.nm, self.defval, self.spec])
+        jl.append([self.vt])
         while jl[-1][-1] is None:
                 jl[-1].pop(-1)
 
+#######################################################################
+
+
+class arg(ctype):
+    def __init__(self, wl, argnames, enums, end):
+        super(arg, self).__init__(wl, enums)
+
+        if wl[0] == end:
+            return
+
+        x = wl.pop(0)
+        if x in argnames:
+            err("Duplicate argument name '%s'" % x, warn=False)
+        argnames[x] = True
+        self.nm = x
+
+        if wl[0] == end:
+            return
+
+        x = wl.pop(0)
+        if x != "=":
+            err("Expected '=' got '%s'" % x, warn=False)
+
+        x = wl.pop(0)
+        if self.vt == "ENUM":
+            if x[0] == '"' and x[-1] == '"':
+                x = x[1:-1]
+            elif x[0] == "'" and x[-1] == "'":
+                x = x[1:-1]
+        self.defval = x
+
+    def json(self, jl):
+        jl.append([self.vt, self.nm, self.defval, self.spec])
+        while jl[-1][-1] is None:
+            jl[-1].pop(-1)
+
+#######################################################################
+
 
 def lex(l):
     wl = []
@@ -309,65 +336,49 @@ def lex(l):
         err("Syntax error at char", i, "'%s'" % c, warn=False)
     return wl
 
+#######################################################################
+
 
 class prototype(object):
     def __init__(self, st, retval=True, prefix=""):
-        global inputline
         self.st = st
         self.obj = None
-        inputline = st.line[1]
+        self.args = []
         wl = lex(st.line[1])
 
         if retval:
-            self.retval = ctype(wl)
+            self.retval = ctype(wl, st.vcc.enums)
+        else:
+            self.retval = ctype(['VOID'], st.vcc.enums)
 
         self.bname = wl.pop(0)
         if not re.match("^[a-zA-Z.][a-zA-Z0-9_]*$", self.bname):
             err("%s(): Illegal name\n" % self.nname, warn=False)
 
-        self.prefix = prefix
-        self.name = self.prefix + self.bname
-        self.vcc = st.vcc
+        self.name = prefix + self.bname
         if not re.match('^[a-zA-Z_][a-zA-Z0-9_]*$', self.cname()):
             err("%s(): Illegal C-name\n" % self.cname(), warn=False)
 
-        x = wl.pop(0)
-        if x != "(":
-            err("Syntax error: Expected '(', got '%s'" % x, warn=False)
+        if len(wl) == 2 and wl[0] == '(' and wl[1] == ')':
+                return
 
-        x = wl.pop(-1)
-        if x != ")":
-            err("Syntax error: Expected ')', got '%s'" % x, warn=False)
+        if wl[0] != "(":
+            err("Syntax error: Expected '(', got '%s'" % wl[0], warn=False)
+        wl[0] = ','
+
+        if wl[-1] != ")":
+            err("Syntax error: Expected ')', got '%s'" % wl[-1], warn=False)
+        wl[-1] = ','
 
         names = {}
-        self.args = []
         while len(wl) > 0:
-            t = ctype(wl)
-            self.args.append(t)
-            if not len(wl):
-                break
             x = wl.pop(0)
-            if x == ",":
-                continue
-            if x in names:
-                err("%s(): Duplicate argument name" % x, warn=False)
-            names[x] = True
-            t.nm = x
-            if not len(wl):
-                break
-            if wl[0] == "=":
-                wl.pop(0)
-                t.set_defval(wl.pop(0))
-            if not len(wl):
+            if x != ',':
+                err("Expected ',' found '%s'" % x, warn=False)
+            if len(wl) == 0:
                 break
-            assert wl.pop(0) == ","
-        inputline = None
-
-    def cname(self, pfx=False):
-        r = self.name.replace(".", "_")
-        if pfx:
-            return self.vcc.sympfx + r
-        return r
+            t = arg(wl, names, st.vcc.enums, ',')
+            self.args.append(t)
 
     def vcl_proto(self, short, pfx=""):
         if type(self.st) == s_method:
@@ -420,28 +431,39 @@ class prototype(object):
         fo.write(self.vcl_proto(True, pfx="   ") + "\n")
         fo.write("  \n")
 
-    def c_ret(self):
-        return self.retval.ct
+    def cname(self, pfx=False):
+        r = self.name.replace(".", "_")
+        if pfx:
+            return self.st.vcc.sympfx + r
+        return r
 
-    def c_args(self, a=[]):
-        ll = list(a)
+    def proto(self, args, name):
+        s = self.retval.ct + " " + name + '('
+        ll = args
         for i in self.args:
             ll.append(i.ct)
-        return ", ".join(ll)
-
-    def c_fn(self, args=[], h=False):
-        s = fn = ''
-        if not h:
-            s += 'typedef '
-            fn += 'td_' + self.vcc.modname + '_'
-        fn += self.cname(pfx=h)
-        s += '%s %s(%s);' % (self.c_ret(), fn, self.c_args(args))
-        return "\n".join(lwrap(s)) + "\n"
+        s += ", ".join(ll)
+        return s + ');'
+
+    def typedef(self, args):
+        tn = 'td_' + self.st.vcc.modname + '_' + self.cname()
+        return "typedef " + self.proto(args, name=tn)
+
+    def cstuff(self, args, where):
+        if where == 'h':
+                s = self.proto(args, self.cname(True))
+        elif where == 'c':
+                s = self.typedef(args)
+        elif where == 'o':
+                s = self.typedef(args)
+        else:
+            assert False
+        return lwrap(s)
 
     def json(self, jl, cfunc):
         ll = []
         self.retval.json(ll)
-        ll.append('Vmod_%s_Func.%s' % (self.vcc.modname, cfunc))
+        ll.append('Vmod_%s_Func.%s' % (self.st.vcc.modname, cfunc))
         for i in self.args:
             i.json(ll)
         jl.append(ll)
@@ -492,13 +514,10 @@ class stanza(object):
         if self.proto is not None:
             self.proto.synopsis(fo, man)
 
-    def hfile(self, fo):
+    def cstuff(self, fo, where):
         return
 
-    def cstruct(self, fo):
-        return
-
-    def cstruct_init(self, fo):
+    def cstruct(self, fo, define):
         return
 
     def json(self, jl):
@@ -566,11 +585,10 @@ class s_module(stanza):
 
 class s_abi(stanza):
     def parse(self):
-        global strict_abi
         if self.line[1] not in ('strict', 'vrt'):
             err("Valid ABI types are 'strict' or 'vrt', got '%s'\n" %
                 self.line[1])
-        strict_abi = self.line[1] == 'strict'
+        self.vcc.strict_abi = self.line[1] == 'strict'
         self.vcc.contents.append(self)
 
 
@@ -590,14 +608,15 @@ class s_event(stanza):
             err("Not emitting .RST for $Event %s\n" %
                 self.event_func)
 
-    def hfile(self, fo):
-        fo.write("vmod_event_f %s;\n" % self.event_func)
-
-    def cstruct(self, fo):
-        fo.write("\tvmod_event_f\t\t\t*_event;\n")
+    def cstuff(self, fo, where):
+        if where == 'h':
+            fo.write("vmod_event_f %s;\n" % self.event_func)
 
-    def cstruct_init(self, fo):
-        fo.write("\t%s,\n" % self.event_func)
+    def cstruct(self, fo, define):
+        if define:
+            fo.write("\tvmod_event_f\t\t\t*_event;\n")
+        else:
+            fo.write("\t%s,\n" % self.event_func)
 
     def json(self, jl):
         jl.append([
@@ -612,17 +631,15 @@ class s_function(stanza):
         self.rstlbl = "func_" + self.proto.name
         self.vcc.contents.append(self)
 
-    def hfile(self, fo):
-        fo.write(self.proto.c_fn(['VRT_CTX'], True))
-
-    def cfile(self, fo):
-        fo.write(self.proto.c_fn(['VRT_CTX']))
+    def cstuff(self, fo, where):
+        if where in ('h', 'c'):
+            fo.write(self.proto.cstuff(['VRT_CTX'], where))
 
-    def cstruct(self, fo):
-        fmt_cstruct(fo, self.vcc.modname, self.proto.cname())
-
-    def cstruct_init(self, fo):
-        fo.write("\t" + self.proto.cname(pfx=True) + ",\n")
+    def cstruct(self, fo, define):
+        if define:
+            fmt_cstruct(fo, self.vcc.modname, self.proto.cname())
+        else:
+            fo.write("\t" + self.proto.cname(pfx=True) + ",\n")
 
     def json(self, jl):
         jl.append(["$FUNC", "%s" % self.proto.name])
@@ -632,7 +649,6 @@ class s_function(stanza):
 class s_object(stanza):
     def parse(self):
         self.proto = prototype(self, retval=False)
-        self.proto.retval = ctype(['VOID'])
         self.proto.obj = "x" + self.proto.name
 
         self.init = copy.copy(self.proto)
@@ -662,35 +678,27 @@ class s_object(stanza):
         for i in self.methods:
             i.proto.synopsis(fo, man)
 
-    def chfile(self, fo, h):
+    def cstuff(self, fo, w):
         sn = self.vcc.sympfx + self.vcc.modname + "_" + self.proto.name
         fo.write("struct %s;\n" % sn)
 
-        fo.write(self.init.c_fn(
-            ['VRT_CTX', 'struct %s **' % sn, 'const char *'], h))
-        fo.write(self.fini.c_fn(['struct %s **' % sn], h))
+        fo.write(self.init.cstuff(
+            ['VRT_CTX', 'struct %s **' % sn, 'const char *'], w))
+        fo.write(self.fini.cstuff(['struct %s **' % sn], w))
         for i in self.methods:
-            fo.write(i.proto.c_fn(['VRT_CTX', 'struct %s *' % sn], h))
+            fo.write(i.proto.cstuff(['VRT_CTX', 'struct %s *' % sn], w))
         fo.write("\n")
 
-    def hfile(self, fo):
-        self.chfile(fo, True)
-
-    def cfile(self, fo):
-        self.chfile(fo, False)
-
-    def cstruct(self, fo):
-        fmt_cstruct(fo, self.vcc.modname, self.init.name)
-        fmt_cstruct(fo, self.vcc.modname, self.fini.name)
-        for i in self.methods:
-            i.cstruct(fo)
-
-    def cstruct_init(self, fo):
-        p = "\t" + self.vcc.sympfx
-        fo.write(p + self.init.name + ",\n")
-        fo.write(p + self.fini.name + ",\n")
+    def cstruct(self, fo, define):
+        if define:
+            fmt_cstruct(fo, self.vcc.modname, self.init.name)
+            fmt_cstruct(fo, self.vcc.modname, self.fini.name)
+        else:
+            p = "\t" + self.vcc.sympfx
+            fo.write(p + self.init.name + ",\n")
+            fo.write(p + self.fini.name + ",\n")
         for i in self.methods:
-            i.cstruct_init(fo)
+            i.cstruct(fo, define)
         fo.write("\n")
 
     def json(self, jl):
@@ -719,6 +727,8 @@ class s_object(stanza):
         for i in self.methods:
             i.dump()
 
+#######################################################################
+
 
 class s_method(stanza):
     def parse(self):
@@ -730,11 +740,11 @@ class s_method(stanza):
         self.rstlbl = "func_" + self.proto.name
         p.methods.append(self)
 
-    def cstruct(self, fo):
-        fmt_cstruct(fo, self.vcc.modname, self.proto.cname())
-
-    def cstruct_init(self, fo):
-        fo.write('\t' + self.proto.cname(pfx=True) + ",\n")
+    def cstruct(self, fo, define):
+        if define:
+            fmt_cstruct(fo, self.vcc.modname, self.proto.cname())
+        else:
+            fo.write('\t' + self.proto.cname(pfx=True) + ",\n")
 
     def json(self, jl):
         jl.append(["$METHOD", self.proto.name[len(self.pfx)+1:]])
@@ -763,6 +773,8 @@ class vcc(object):
         self.contents = []
         self.commit_files = []
         self.copyright = ""
+        self.enums = {}
+        self.strict_abi = True
 
     def openfile(self, fn):
         self.commit_files.append(fn)
@@ -773,6 +785,7 @@ class vcc(object):
             os.rename(i + ".tmp", i)
 
     def parse(self):
+        global inputline
         a = "\n" + open(self.inputfile, "r").read()
         s = a.split("\n$")
         self.copyright = s.pop(0).strip()
@@ -783,11 +796,13 @@ class vcc(object):
                 i += 1
             else:
                 i = len(ss)
+            inputline = ss[:i]
             c = ss[:i].split()
             m = dispatch.get(c[0])
             if m is None:
                 err("Unknown stanze $%s" % ss[:i])
             m([c[0], " ".join(c[1:])], ss[i:].split('\n'), self)
+            inputline = None
 
     def rst_copyright(self, fo):
         write_rst_hdr(fo, "COPYRIGHT", "=")
@@ -818,8 +833,7 @@ class vcc(object):
         fo.close()
 
     def amboilerplate(self):
-        fn = "automake_boilerplate.am"
-        fo = self.openfile(fn)
+        fo = self.openfile("automake_boilerplate.am")
         fo.write(AMBOILERPLATE.replace("XXX", self.modname))
         fo.close()
 
@@ -835,30 +849,28 @@ class vcc(object):
         fo.write("#endif\n")
         fo.write("\n")
 
-        for j in sorted(enum_values):
+        for j in sorted(self.enums):
             fo.write("extern VCL_ENUM %senum_%s;\n" % (self.sympfx, j))
         fo.write("\n")
 
         for j in self.contents:
-            j.hfile(fo)
+            j.cstuff(fo, 'h')
         fo.close()
 
     def cstruct(self, fo, csn):
-
         fo.write("\n%s {\n" % csn)
         for j in self.contents:
-            j.cstruct(fo)
-        fo.write("\n")
-        for j in sorted(enum_values):
+            j.cstruct(fo, True)
+        for j in sorted(self.enums):
             fo.write("\tVCL_ENUM\t\t\t*enum_%s;\n" % j)
         fo.write("};\n")
 
     def cstruct_init(self, fo, csn):
         fo.write("\nstatic const %s Vmod_Func = {\n" % csn)
         for j in self.contents:
-            j.cstruct_init(fo)
+            j.cstruct(fo, False)
         fo.write("\n")
-        for j in sorted(enum_values):
+        for j in sorted(self.enums):
             fo.write("\t&%senum_%s,\n" % (self.sympfx, j))
         fo.write("};\n")
 
@@ -887,14 +899,13 @@ class vcc(object):
                 fo.write(j + "\n")
         fo.write("\n")
 
-    def api(self, fo):
+    def vmod_data(self, fo):
+        vmd = "Vmod_%s_Data" % self.modname
         for i in (714, 759, 765):
-            fo.write("\n/*lint -esym(%d, Vmod_%s_Data) */\n" %
-                     (i, self.modname))
-        fo.write("\nextern const struct vmod_data Vmod_%s_Data;\n" %
-                 (self.modname))
-        fo.write("\nconst struct vmod_data Vmod_%s_Data = {\n" % self.modname)
-        if strict_abi:
+            fo.write("\n/*lint -esym(%d, %s) */\n" % (i, vmd))
+        fo.write("\nextern const struct vmod_data %s;\n" % vmd)
+        fo.write("\nconst struct vmod_data %s = {\n" % vmd)
+        if self.strict_abi:
             fo.write("\t.vrt_major =\t0,\n")
             fo.write("\t.vrt_minor =\t0,\n")
         else:
@@ -917,59 +928,55 @@ class vcc(object):
         fo.write("};\n")
 
     def cfile(self):
-        fn = self.pfx + ".c"
-        fo = self.openfile(fn)
-        write_c_file_warning(fo)
+        fno = self.pfx + ".c"
+        fo = self.openfile(fno)
+        fnx = fno + ".tmp2"
+        fx = open(fnx, "w")
 
-        fn2 = fn + ".tmp2"
+        write_c_file_warning(fo)
 
         fo.write('#include "config.h"\n')
         fo.write('#include <stdio.h>\n')
         for i in ["vdef", "vrt", self.pfx, "vmod_abi"]:
             fo.write('#include "%s.h"\n' % i)
-
         fo.write("\n")
 
-        for j in sorted(enum_values):
+        for j in sorted(self.enums):
             fo.write('VCL_ENUM %senum_%s = "%s";\n' % (self.sympfx, j, j))
         fo.write("\n")
 
-        fx = open(fn2, "w")
-
         for i in self.contents:
             if type(i) == s_object:
-                i.cfile(fo)
-                i.cfile(fx)
+                i.cstuff(fo, 'c')
+                i.cstuff(fx, 'c')
 
         fx.write("/* Functions */\n")
         for i in self.contents:
             if type(i) == s_function:
-                i.cfile(fo)
-                i.cfile(fx)
+                i.cstuff(fo, 'c')
+                i.cstuff(fx, 'c')
 
         csn = "Vmod_%s_Func" % self.modname
+        scsn = "struct " + csn
 
-        self.cstruct(fo, "struct " + csn)
-
-        self.cstruct(fx, "struct " + csn)
+        self.cstruct(fo, scsn)
+        self.cstruct(fx, scsn)
 
-        fo.write("\n/*lint -esym(754, Vmod_" + self.modname + "_Func::*) */\n")
-        self.cstruct_init(fo, "struct " + csn)
+        fo.write("\n/*lint -esym(754, " + csn + "::*) */\n")
+        self.cstruct_init(fo, scsn)
 
         fx.close()
 
         fo.write("\nstatic const char Vmod_Proto[] =\n")
-        fi = open(fn2)
-        for i in fi:
+        for i in open(fnx):
             fo.write('\t"%s\\n"\n' % i.rstrip())
-        fi.close()
         fo.write('\t"static struct %s %s;";\n' % (csn, csn))
 
-        os.remove(fn2)
+        os.remove(fnx)
 
         self.json(fo)
 
-        self.api(fo)
+        self.vmod_data(fo)
 
         fo.close()
 


More information about the varnish-commit mailing list