[master] 502b7f143 Refactor vmodtoll and the .rst doc it produces.

Poul-Henning Kamp phk at FreeBSD.org
Tue Jan 22 13:12:08 UTC 2019


commit 502b7f1434a19bc6c2b0123445c3a642bd645322
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date:   Tue Jan 22 13:11:18 2019 +0000

    Refactor vmodtoll and the .rst doc it produces.
    
    Not what I came here for, but...

diff --git a/lib/libvcc/vmodtool.py b/lib/libvcc/vmodtool.py
index 32d4e6f2e..17956311b 100755
--- a/lib/libvcc/vmodtool.py
+++ b/lib/libvcc/vmodtool.py
@@ -147,10 +147,11 @@ def write_rst_file_warning(fo):
 
 
 def write_rst_hdr(fo, s, below="-", above=None):
-    if above is not None:
+    fo.write('\n')
+    if above:
         fo.write(above * len(s) + "\n")
     fo.write(s + "\n")
-    if below is not None:
+    if below:
         fo.write(below * len(s) + "\n")
 
 #######################################################################
@@ -245,19 +246,16 @@ class CType(object):
                 break
             assert w == ","
 
-    def vcl(self):
+    def vcl(self, terse=False):
         if self.vt in ("STRING_LIST", "STRANDS"):
             return "STRING"
+        if terse:
+            return self.vt
         if self.spec is None:
             return self.vt
         return self.vt + " {" + ", ".join(self.spec) + "}"
 
-    def synopsis(self):
-        if self.vt in ("STRING_LIST", "STRANDS"):
-            return "STRING"
-        return self.vt
-
-    def json(self, jl):
+    def jsonproto(self, jl):
         jl.append([self.vt])
         while jl[-1][-1] is None:
             jl[-1].pop(-1)
@@ -294,7 +292,7 @@ class arg(CType):
                 x = unquote(x)
         self.defval = x
 
-    def json(self, jl):
+    def jsonproto(self, jl):
         jl.append([self.vt, self.nm, self.defval, self.spec])
         if self.opt:
             jl[-1].append(True)
@@ -363,7 +361,7 @@ class ProtoType(object):
                 t.nm2 = t.nm
             self.args.append(t)
 
-    def vcl_proto(self, short, pfx=""):
+    def vcl_proto(self, terse, pfx=""):
         if isinstance(self.st, MethodStanza):
             pfx += pfx
         s = pfx
@@ -380,22 +378,19 @@ class ProtoType(object):
             s += self.name + "("
         ll = []
         for i in self.args:
-            if short:
-                t = i.synopsis()
-            else:
-                t = i.vcl()
+            t = i.vcl(terse)
             if t in PRIVS:
                 continue
             if i.nm is not None:
                 t += " " + i.nm
-            if not short:
+            if not terse:
                 if i.defval is not None:
                     t += "=" + i.defval
             if i.opt:
                 t = "[" + t + "]"
             ll.append(t)
         t = ",@".join(ll)
-        if len(s + t) > 68 and not short:
+        if len(s + t) > 68 and not terse:
             s += "\n" + pfx + pfx
             s += t.replace("@", "\n" + pfx + pfx)
             s += "\n" + pfx + ")"
@@ -409,15 +404,9 @@ class ProtoType(object):
             write_rst_hdr(fo, s, '-')
         else:
             s = self.vcl_proto(True)
-            if len(s) > 60:
-                s = self.name + "(...)"
             write_rst_hdr(fo, s, '-')
             fo.write("\n::\n\n" + self.vcl_proto(False, pfx="   ") + "\n")
 
-    def synopsis(self, fo, unused_man):
-        fo.write(self.vcl_proto(True, pfx="   ") + "\n")
-        fo.write("  \n")
-
     def cname(self, pfx=False):
         r = self.name.replace(".", "_")
         if pfx:
@@ -458,44 +447,49 @@ class ProtoType(object):
         s += "};\n"
         return s
 
-    def cstuff(self, args, where):
+    def cproto(self, eargs, where):
+        ''' Produce C language prototype '''
         s = ""
         if where == 'h':
             if self.argstruct:
                 s += self.argstructure()
-            s += lwrap(self.proto(args, self.cname(True)))
+            s += lwrap(self.proto(eargs, self.cname(True)))
         elif where == 'c':
-            s += lwrap(self.typedef(args))
+            s += lwrap(self.typedef(eargs))
         elif where == 'o':
             if self.argstruct:
                 s += self.argstructure()
-            s += lwrap(self.typedef(args))
+            s += lwrap(self.typedef(eargs))
         else:
             assert False
         return s
 
-    def json(self, jl, cfunc):
+    def jsonproto(self, jl, cfunc):
+        ''' Produce VCL prototype as JSON '''
         ll = []
-        self.retval.json(ll)
+        self.retval.jsonproto(ll)
         ll.append('Vmod_%s_Func.%s' % (self.st.vcc.modname, cfunc))
         if self.argstruct:
             ll.append(self.argstructname())
         else:
             ll.append("")
         for i in self.args:
-            i.json(ll)
+            i.jsonproto(ll)
         jl.append(ll)
 
 #######################################################################
 
 
 class Stanza(object):
-    def __init__(self, toks, l0, doc, vcc):
+
+    ''' Base class for all $-Stanzas '''
+
+    def __init__(self, vcc, toks, doc):
         self.toks = toks
-        self.line = l0
-        while doc and doc[0] == '':
+        doc = doc.split('\n')
+        while doc and not doc[0].strip():
             doc.pop(0)
-        while doc and doc[-1] == '':
+        while doc and not doc[-1].strip():
             doc.pop(-1)
         self.doc = doc
         self.vcc = vcc
@@ -507,9 +501,6 @@ class Stanza(object):
     def parse(self):
         assert "subclass should have defined" == "parse method"
 
-    def dump(self):
-        print(type(self), self.line)
-
     def syntax(self):
         err("Syntax error.\n" +
             "\tShould be: " + self.__doc__.strip() + "\n" +
@@ -517,29 +508,26 @@ class Stanza(object):
             warn=False)
 
     def rstfile(self, fo, man):
-        if self.rstlbl is not None:
-            fo.write(".. _" + self.rstlbl + ":\n\n")
-
+        if self.rstlbl:
+            fo.write("\n.. _" + self.rstlbl + ":\n")
         self.rsthead(fo, man)
-        fo.write("\n")
-        self.rstmid(fo, man)
-        fo.write("\n")
-        self.rsttail(fo, man)
-        fo.write("\n")
+        self.rstdoc(fo, man)
 
     def rsthead(self, fo, unused_man):
-        if self.proto is not None:
+        ''' Emit the systematic part of the documentation '''
+        if self.proto:
             self.proto.rsthead(fo)
+            fo.write("\n")
 
-    def rstmid(self, fo, unused_man):
+    def rstdoc(self, fo, unused_man):
+        ''' Emit the explanatory part of the documentation '''
         fo.write("\n".join(self.doc) + "\n")
 
-    def rsttail(self, unused_fo, unused_man):
-        return
-
     def synopsis(self, fo, man):
-        if self.proto is not None:
-            self.proto.synopsis(fo, man)
+        if man and self.proto:
+            fo.write(self.proto.vcl_proto(True, pfx="  ") + '\n  \n')
+        elif self.proto and self.rstlbl:
+            fo.write('   :ref:`%s`\n   \n' % self.rstlbl)
 
     def cstuff(self, unused_fo, unused_where):
         return
@@ -548,6 +536,7 @@ class Stanza(object):
         return
 
     def json(self, unused_jl):
+        ''' Add to the json we hand VCC '''
         return
 
 #######################################################################
@@ -575,49 +564,25 @@ class ModuleStanza(Stanza):
 
     def rsthead(self, fo, man):
 
-        write_rst_hdr(fo, self.vcc.sympfx + self.vcc.modname, "=", "=")
-        fo.write("\n")
-
-        write_rst_hdr(fo, self.vcc.moddesc, "-", "-")
-
-        fo.write("\n")
-        fo.write(":Manual section: " + self.vcc.mansection + "\n")
+        if man:
+            write_rst_hdr(fo, self.vcc.sympfx + self.vcc.modname, "=", "=")
+            write_rst_hdr(fo, self.vcc.moddesc, "-", "-")
+            fo.write("\n")
+            fo.write(":Manual section: " + self.vcc.mansection + "\n")
+        else:
+            write_rst_hdr(fo,
+                          self.vcc.sympfx + self.vcc.modname +
+                          ' - ' + self.vcc.moddesc,
+                          "=", "=")
 
         if self.vcc.auto_synopsis:
-            fo.write("\n")
             write_rst_hdr(fo, "SYNOPSIS", "=")
             fo.write("\n")
-            fo.write("\n::\n\n")
-            fo.write('   import %s [from "path"] ;\n' % self.vcc.modname)
-            fo.write("   \n")
+            fo.write(".. parsed-literal::\n\n")
+            fo.write('  import %s [from "path"]\n' % self.vcc.modname)
+            fo.write("  \n")
             for c in self.vcc.contents:
                 c.synopsis(fo, man)
-            fo.write("\n")
-
-    def rsttail(self, fo, man):
-
-        if man:
-            return
-
-        write_rst_hdr(fo, "CONTENTS", "=")
-        fo.write("\n")
-
-        ll = []
-        for i in self.vcc.contents[1:]:
-            j = i.rstlbl
-            if j is not None:
-                ll.append([j.split("_", 1)[1], j])
-            if i.methods is None:
-                continue
-            for x in i.methods:
-                j = x.rstlbl
-                ll.append([j.split("_", 1)[1], j])
-
-        ll.sort()
-        for i in ll:
-            fo.write("* :ref:`%s`\n" % i[1])
-        fo.write("\n")
-
 
 class ABIStanza(Stanza):
 
@@ -699,13 +664,16 @@ class EventStanza(Stanza):
 
 
 class FunctionStanza(Stanza):
+
+    ''' $Function TYPE name ( ARGUMENSTS ) '''
+
     def parse(self):
         self.proto = ProtoType(self)
         self.rstlbl = "func_" + self.proto.name
         self.vcc.contents.append(self)
 
     def cstuff(self, fo, where):
-        fo.write(self.proto.cstuff(['VRT_CTX'], where))
+        fo.write(self.proto.cproto(['VRT_CTX'], where))
 
     def cstruct(self, fo, define):
         if define:
@@ -715,10 +683,13 @@ class FunctionStanza(Stanza):
 
     def json(self, jl):
         jl.append(["$FUNC", "%s" % self.proto.name])
-        self.proto.json(jl[-1], self.proto.cname())
+        self.proto.jsonproto(jl[-1], self.proto.cname())
 
 
 class ObjectStanza(Stanza):
+
+    ''' $Object TYPE class ( ARGUMENSTS ) '''
+
     def parse(self):
         self.proto = ProtoType(self, retval=False)
         self.proto.obj = "x" + self.proto.name
@@ -737,29 +708,34 @@ class ObjectStanza(Stanza):
 
     def rsthead(self, fo, man):
         self.proto.rsthead(fo)
-
-        fo.write("\n" + "\n".join(self.doc) + "\n\n")
-
+        fo.write("\n" + "\n".join(self.doc) + "\n")
         for i in self.methods:
             i.rstfile(fo, man)
 
-    def rstmid(self, unused_fo, unused_man):
+    def rstdoc(self, unused_fo, unused_man):
         return
 
     def synopsis(self, fo, man):
-        self.proto.synopsis(fo, man)
-        for i in self.methods:
-            i.proto.synopsis(fo, man)
+        if man and self.proto:
+            fo.write(self.proto.vcl_proto(True, pfx="  ") + '\n  \n')
+            for i in self.methods:
+                if i.proto:
+                    fo.write(i.proto.vcl_proto(True, pfx="   ") + '\n   \n')
+        elif self.proto and self.rstlbl:
+            fo.write('  :ref:`%s`\n  \n' % self.rstlbl)
+            for i in self.methods:
+                if i.proto and i.rstlbl:
+                    fo.write('    :ref:`%s`\n  \n' % i.rstlbl)
 
     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.cstuff(
+        fo.write(self.init.cproto(
             ['VRT_CTX', 'struct %s **' % sn, 'const char *'], w))
-        fo.write(self.fini.cstuff(['struct %s **' % sn], w))
+        fo.write(self.fini.cproto(['struct %s **' % sn], w))
         for i in self.methods:
-            fo.write(i.proto.cstuff(['VRT_CTX', 'struct %s *' % sn], w))
+            fo.write(i.proto.cproto(['VRT_CTX', 'struct %s *' % sn], w))
         fo.write("\n")
 
     def cstruct(self, fo, define):
@@ -784,26 +760,24 @@ class ObjectStanza(Stanza):
 
         l2 = ["$INIT"]
         ll.append(l2)
-        self.init.json(l2, self.init.name)
+        self.init.jsonproto(l2, self.init.name)
 
         l2 = ["$FINI"]
         ll.append(l2)
-        self.fini.json(l2, self.fini.name)
+        self.fini.jsonproto(l2, self.fini.name)
 
         for i in self.methods:
             i.json(ll)
 
         jl.append(ll)
 
-    def dump(self):
-        super(ObjectStanza, self).dump()
-        for i in self.methods:
-            i.dump()
-
 #######################################################################
 
 
 class MethodStanza(Stanza):
+
+    ''' $Method TYPE . method ( ARGUMENSTS ) '''
+
     def parse(self):
         p = self.vcc.contents[-1]
         assert isinstance(p, ObjectStanza)
@@ -824,7 +798,7 @@ class MethodStanza(Stanza):
 
     def json(self, jl):
         jl.append(["$METHOD", self.proto.name[len(self.pfx)+1:]])
-        self.proto.json(jl[-1], self.proto.cname())
+        self.proto.jsonproto(jl[-1], self.proto.cname())
 
 
 #######################################################################
@@ -877,12 +851,11 @@ class vcc(object):
             ss = re.split('\n([^\t ])', s.pop(0), maxsplit=1)
             toks = self.tokenize(ss[0])
             inputline = '$' + ' '.join(toks)
-            c = ss[0].split()
-            d = "".join(ss[1:])
-            m = DISPATCH.get(toks[0])
-            if m is None:
+            docstr = "".join(ss[1:])
+            stanzaclass = DISPATCH.get(toks[0])
+            if stanzaclass is None:
                 err("Unknown stanza $%s" % toks[0], warn=False)
-            m(toks, [c[0], " ".join(c[1:])], d.split('\n'), self)
+            stanzaclass(self, toks, docstr)
             inputline = None
 
     def tokenize(self, txt, seps=None, quotes=None):
@@ -922,41 +895,43 @@ class vcc(object):
         #    print("\t", [i])
         return out
 
-
-    def rst_copyright(self, fo):
-        write_rst_hdr(fo, "COPYRIGHT", "=")
-        fo.write("\n::\n\n")
-        a = self.copyright
-        a = a.replace("\n#", "\n ")
-        if a[:2] == "#\n":
-            a = a[2:]
-        if a[:3] == "#-\n":
-            a = a[3:]
-        fo.write(a + "\n")
-
     def rstfile(self, man=False):
+        ''' Produce rst documentation '''
         fn = os.path.join(self.rstdir, "vmod_" + self.modname)
         if man:
             fn += ".man"
         fn += ".rst"
         fo = self.openfile(fn)
         write_rst_file_warning(fo)
-        fo.write(".. role:: ref(emphasis)\n\n")
+        if man:
+            fo.write(".. role:: ref(emphasis)\n")
+        else:
+            fo.write('\n:tocdepth: 1\n')
 
         for i in self.contents:
             i.rstfile(fo, man)
 
         if self.copyright:
-            self.rst_copyright(fo)
+            write_rst_hdr(fo, "COPYRIGHT", "=")
+            fo.write("\n::\n\n")
+            a = self.copyright
+            a = a.replace("\n#", "\n ")
+            if a[:2] == "#\n":
+                a = a[2:]
+            if a[:3] == "#-\n":
+                a = a[3:]
+            fo.write(a + "\n")
 
         fo.close()
 
     def amboilerplate(self):
+        ''' Produce boilplate for autocrap tools '''
         fo = self.openfile("automake_boilerplate.am")
         fo.write(AMBOILERPLATE.replace("XXX", self.modname))
         fo.close()
 
-    def hfile(self):
+    def mkhfile(self):
+        ''' Produce vcc_if.h file '''
         fn = self.pfx + ".h"
         fo = self.openfile(fn)
         write_c_file_warning(fo)
@@ -998,30 +973,23 @@ class vcc(object):
         for j in self.contents:
             j.json(jl)
 
-        bz = bytearray(json.dumps(jl, separators=(",", ":")),
-                       encoding="ascii") + b"\0"
-        fo.write("\nstatic const char Vmod_Json[%d] = {\n" % len(bz))
-        t = "\t"
-        for i in bz:
-            t += "%d," % i
-            if len(t) >= 69:
-                fo.write(t + "\n")
-                t = "\t"
-        if len(t) > 1:
-            fo.write(t[:-1])
-        fo.write("\n};\n\n")
-        for i in json.dumps(jl, indent=2, separators=(',', ': ')).split("\n"):
-            j = "// " + i
-            if len(j) > 72:
-                fo.write(j[:72] + "[...]\n")
+        fo.write("\nstatic const char Vmod_Json[] = {\n")
+        t = '\t"'
+        for i in json.dumps(jl, indent=2, separators=(",", ": ")):
+            if i == '\n':
+                fo.write(t + '\\n"\n')
+                t = '\t"'
             else:
-                fo.write(j + "\n")
-        fo.write("\n")
+                if i in '"\\':
+                    t += '\\'
+                t += i
+        fo.write(t + '\\n"\n};\n')
 
     def vmod_data(self, fo):
         vmd = "Vmod_%s_Data" % self.modname
+        fo.write('\n')
         for i in (714, 759, 765):
-            fo.write("\n/*lint -esym(%d, %s) */\n" % (i, vmd))
+            fo.write("/*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:
@@ -1039,7 +1007,8 @@ class vcc(object):
         fo.write("\t.file_id =\t\"%s\",\n" % self.file_id)
         fo.write("};\n")
 
-    def cfile(self):
+    def mkcfile(self):
+        ''' Produce vcc_if.c file '''
         fno = self.pfx + ".c"
         fo = self.openfile(fno)
         fnx = fno + ".tmp2"
@@ -1102,8 +1071,8 @@ def runmain(inputvcc, rstdir, outputprefix):
 
     v.rstfile(man=False)
     v.rstfile(man=True)
-    v.hfile()
-    v.cfile()
+    v.mkhfile()
+    v.mkcfile()
     if opts.boilerplate:
         v.amboilerplate()
 
diff --git a/lib/libvmod_blob/vmod.vcc b/lib/libvmod_blob/vmod.vcc
index a5b6ae4fd..ab545480e 100644
--- a/lib/libvmod_blob/vmod.vcc
+++ b/lib/libvmod_blob/vmod.vcc
@@ -6,9 +6,8 @@
 #          Geoffrey Simmons <geoffrey.simmons at uplex.de>
 #
 
-$Module blob 3 "Utilities for the VCL blob type, encoding and decoding"
-
 $ABI strict
+$Module blob 3 "Utilities for the VCL blob type, encoding and decoding"
 
 DESCRIPTION
 ===========
diff --git a/lib/libvmod_debug/vmod.vcc b/lib/libvmod_debug/vmod.vcc
index 5faa718bf..65464fd32 100644
--- a/lib/libvmod_debug/vmod.vcc
+++ b/lib/libvmod_debug/vmod.vcc
@@ -26,9 +26,9 @@
 # SUCH DAMAGE.
 #
 
-$Module debug 3 "Development, test and debug"
 $ABI strict
 $Prefix xyzzy
+$Module debug 3 "Development, test and debug"
 $Synopsis auto
 DESCRIPTION
 ===========
diff --git a/lib/libvmod_directors/vmod.vcc b/lib/libvmod_directors/vmod.vcc
index 54b111fba..a98352983 100644
--- a/lib/libvmod_directors/vmod.vcc
+++ b/lib/libvmod_directors/vmod.vcc
@@ -32,8 +32,8 @@
 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 # SUCH DAMAGE.
 
-$Module directors 3 "Varnish Directors Module"
 $ABI strict
+$Module directors 3 "Varnish Directors Module"
 
 DESCRIPTION
 ===========
diff --git a/lib/libvmod_proxy/vmod.vcc b/lib/libvmod_proxy/vmod.vcc
index 79aa4b678..2d0663582 100644
--- a/lib/libvmod_proxy/vmod.vcc
+++ b/lib/libvmod_proxy/vmod.vcc
@@ -25,8 +25,8 @@
 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 # SUCH DAMAGE.
 
-$Module proxy 3 "Varnish Module to extract TLV attributes from PROXYv2"
 $ABI strict
+$Module proxy 3 "Varnish Module to extract TLV attributes from PROXYv2"
 
 DESCRIPTION
 ===========
diff --git a/lib/libvmod_purge/vmod.vcc b/lib/libvmod_purge/vmod.vcc
index e158aac69..c8d8185cc 100644
--- a/lib/libvmod_purge/vmod.vcc
+++ b/lib/libvmod_purge/vmod.vcc
@@ -25,8 +25,8 @@
 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 # SUCH DAMAGE.
 
-$Module purge 3 "Varnish Purge Module"
 $ABI strict
+$Module purge 3 "Varnish Purge Module"
 
 DESCRIPTION
 ===========
diff --git a/lib/libvmod_std/vmod.vcc b/lib/libvmod_std/vmod.vcc
index fc5ef3736..0ae941c12 100644
--- a/lib/libvmod_std/vmod.vcc
+++ b/lib/libvmod_std/vmod.vcc
@@ -25,8 +25,8 @@
 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 # SUCH DAMAGE.
 
-$Module std 3 "Varnish Standard Module"
 $ABI strict
+$Module std 3 "Varnish Standard Module"
 
 DESCRIPTION
 ===========
diff --git a/lib/libvmod_unix/vmod.vcc b/lib/libvmod_unix/vmod.vcc
index e227e9f99..38e48a7d3 100644
--- a/lib/libvmod_unix/vmod.vcc
+++ b/lib/libvmod_unix/vmod.vcc
@@ -5,9 +5,8 @@
 # Authors: Geoffrey Simmons <geoffrey.simmons at uplex.de>
 #
 
-$Module unix 3 "Utilities for Unix domain sockets"
-
 $ABI strict
+$Module unix 3 "Utilities for Unix domain sockets"
 
 DESCRIPTION
 ===========
diff --git a/lib/libvmod_vtc/vmod.vcc b/lib/libvmod_vtc/vmod.vcc
index 248f4b2d6..e1644fffc 100644
--- a/lib/libvmod_vtc/vmod.vcc
+++ b/lib/libvmod_vtc/vmod.vcc
@@ -25,8 +25,8 @@
 # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 # SUCH DAMAGE.
 
-$Module vtc 3 "Utility module for varnishtest"
 $ABI strict
+$Module vtc 3 "Utility module for varnishtest"
 
 DESCRIPTION
 ===========


More information about the varnish-commit mailing list