All of lore.kernel.org
 help / color / mirror / Atom feed
From: Markus Armbruster <armbru@redhat.com>
To: qemu-devel@nongnu.org
Cc: mdroth@linux.vnet.ibm.com, marcandre.lureau@redhat.com,
	eblake@redhat.com
Subject: [Qemu-devel] [PATCH v2 05/29] qapi: New classes QAPIGenC, QAPIGenH, QAPIGenDoc
Date: Sun, 11 Feb 2018 10:35:43 +0100	[thread overview]
Message-ID: <20180211093607.27351-6-armbru@redhat.com> (raw)
In-Reply-To: <20180211093607.27351-1-armbru@redhat.com>

These classes encapsulate accumulating and writing output.

Convert C code generation to QAPIGenC and QAPIGenH.  The conversion is
rather shallow: most of the output accumulation is not converted.
Left for later.

The indentation machinery uses a single global variable indent_level,
even though we generally interleave creation of a .c and its .h.  It
should become instance variable of QAPIGenC.  Also left for later.

Documentation generation isn't converted, and QAPIGenDoc isn't used.
This will change shortly.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
---
 scripts/qapi-commands.py   | 23 +++++------
 scripts/qapi-event.py      | 22 ++++++-----
 scripts/qapi-introspect.py | 18 +++++----
 scripts/qapi-types.py      | 22 ++++++-----
 scripts/qapi-visit.py      | 22 ++++++-----
 scripts/qapi.py            | 99 +++++++++++++++++++++++++---------------------
 6 files changed, 112 insertions(+), 94 deletions(-)

diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
index c3aa52fce1..8d38ade076 100644
--- a/scripts/qapi-commands.py
+++ b/scripts/qapi-commands.py
@@ -260,12 +260,10 @@ blurb = '''
  * Schema-defined QAPI/QMP commands
 '''
 
-(fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix,
-                            'qmp-marshal.c', 'qmp-commands.h',
-                            blurb, __doc__)
-
-fdef.write(mcgen('''
+genc = QAPIGenC(blurb, __doc__)
+genh = QAPIGenH(blurb, __doc__)
 
+genc.add(mcgen('''
 #include "qemu/osdep.h"
 #include "qemu-common.h"
 #include "qemu/module.h"
@@ -280,20 +278,23 @@ fdef.write(mcgen('''
 #include "%(prefix)sqmp-commands.h"
 
 ''',
-                 prefix=prefix))
+               prefix=prefix))
 
-fdecl.write(mcgen('''
+genh.add(mcgen('''
 #include "%(prefix)sqapi-types.h"
 #include "qapi/qmp/dispatch.h"
 
 void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds);
 ''',
-                  prefix=prefix, c_prefix=c_name(prefix, protect=False)))
+               prefix=prefix, c_prefix=c_name(prefix, protect=False)))
 
 schema = QAPISchema(input_file)
 vis = QAPISchemaGenCommandVisitor()
 schema.visit(vis)
-fdef.write(vis.defn)
-fdecl.write(vis.decl)
+genc.add(vis.defn)
+genh.add(vis.decl)
 
-close_output(fdef, fdecl)
+if do_c:
+    genc.write(output_dir, prefix + 'qmp-marshal.c')
+if do_h:
+    genh.write(output_dir, prefix + 'qmp-commands.h')
diff --git a/scripts/qapi-event.py b/scripts/qapi-event.py
index edb9ddb650..bd7a9be3dc 100644
--- a/scripts/qapi-event.py
+++ b/scripts/qapi-event.py
@@ -176,11 +176,10 @@ blurb = '''
  * Schema-defined QAPI/QMP events
 '''
 
-(fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix,
-                            'qapi-event.c', 'qapi-event.h',
-                            blurb, __doc__)
+genc = QAPIGenC(blurb, __doc__)
+genh = QAPIGenH(blurb, __doc__)
 
-fdef.write(mcgen('''
+genc.add(mcgen('''
 #include "qemu/osdep.h"
 #include "qemu-common.h"
 #include "%(prefix)sqapi-event.h"
@@ -191,21 +190,24 @@ fdef.write(mcgen('''
 #include "qapi/qmp-event.h"
 
 ''',
-                 prefix=prefix))
+               prefix=prefix))
 
-fdecl.write(mcgen('''
+genh.add(mcgen('''
 #include "qapi/util.h"
 #include "%(prefix)sqapi-types.h"
 
 ''',
-                  prefix=prefix))
+               prefix=prefix))
 
 event_enum_name = c_name(prefix + 'QAPIEvent', protect=False)
 
 schema = QAPISchema(input_file)
 vis = QAPISchemaGenEventVisitor()
 schema.visit(vis)
-fdef.write(vis.defn)
-fdecl.write(vis.decl)
+genc.add(vis.defn)
+genh.add(vis.decl)
 
-close_output(fdef, fdecl)
+if do_c:
+    genc.write(output_dir, prefix + 'qapi-event.c')
+if do_h:
+    genh.write(output_dir, prefix + 'qapi-event.h')
diff --git a/scripts/qapi-introspect.py b/scripts/qapi-introspect.py
index ebe8706f41..3d65690fe3 100644
--- a/scripts/qapi-introspect.py
+++ b/scripts/qapi-introspect.py
@@ -181,21 +181,23 @@ blurb = '''
  * QAPI/QMP schema introspection
 '''
 
-(fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix,
-                            'qmp-introspect.c', 'qmp-introspect.h',
-                            blurb, __doc__)
+genc = QAPIGenC(blurb, __doc__)
+genh = QAPIGenH(blurb, __doc__)
 
-fdef.write(mcgen('''
+genc.add(mcgen('''
 #include "qemu/osdep.h"
 #include "%(prefix)sqmp-introspect.h"
 
 ''',
-                 prefix=prefix))
+               prefix=prefix))
 
 schema = QAPISchema(input_file)
 vis = QAPISchemaGenIntrospectVisitor(opt_unmask)
 schema.visit(vis)
-fdef.write(vis.defn)
-fdecl.write(vis.decl)
+genc.add(vis.defn)
+genh.add(vis.decl)
 
-close_output(fdef, fdecl)
+if do_c:
+    genc.write(output_dir, prefix + 'qmp-introspect.c')
+if do_h:
+    genh.write(output_dir, prefix + 'qmp-introspect.h')
diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py
index 4db8424da1..c0ac879beb 100644
--- a/scripts/qapi-types.py
+++ b/scripts/qapi-types.py
@@ -180,7 +180,7 @@ class QAPISchemaGenTypeVisitor(QAPISchemaVisitor):
         self.decl = ''
         self.defn = ''
         self._fwdecl = ''
-        self._btin = guardstart('QAPI_TYPES_BUILTIN')
+        self._btin = '\n' + guardstart('QAPI_TYPES_BUILTIN')
 
     def visit_end(self):
         self.decl = self._fwdecl + self.decl
@@ -256,26 +256,28 @@ blurb = '''
  * Schema-defined QAPI types
 '''
 
-(fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix,
-                            'qapi-types.c', 'qapi-types.h',
-                            blurb, __doc__)
+genc = QAPIGenC(blurb, __doc__)
+genh = QAPIGenH(blurb, __doc__)
 
-fdef.write(mcgen('''
+genc.add(mcgen('''
 #include "qemu/osdep.h"
 #include "qapi/dealloc-visitor.h"
 #include "%(prefix)sqapi-types.h"
 #include "%(prefix)sqapi-visit.h"
 ''',
-                 prefix=prefix))
+               prefix=prefix))
 
-fdecl.write(mcgen('''
+genh.add(mcgen('''
 #include "qapi/util.h"
 '''))
 
 schema = QAPISchema(input_file)
 vis = QAPISchemaGenTypeVisitor()
 schema.visit(vis)
-fdef.write(vis.defn)
-fdecl.write(vis.decl)
+genc.add(vis.defn)
+genh.add(vis.decl)
 
-close_output(fdef, fdecl)
+if do_c:
+    genc.write(output_dir, prefix + 'qapi-types.c')
+if do_h:
+    genh.write(output_dir, prefix + 'qapi-types.h')
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index 3c1a0e2544..888c686303 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -339,30 +339,32 @@ blurb = '''
  * Schema-defined QAPI visitors
 '''
 
-(fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix,
-                            'qapi-visit.c', 'qapi-visit.h',
-                            blurb, __doc__)
+genc = QAPIGenC(blurb, __doc__)
+genh = QAPIGenH(blurb, __doc__)
 
-fdef.write(mcgen('''
+genc.add(mcgen('''
 #include "qemu/osdep.h"
 #include "qemu-common.h"
 #include "qapi/error.h"
 #include "qapi/qmp/qerror.h"
 #include "%(prefix)sqapi-visit.h"
 ''',
-                 prefix=prefix))
+               prefix=prefix))
 
-fdecl.write(mcgen('''
+genh.add(mcgen('''
 #include "qapi/visitor.h"
 #include "%(prefix)sqapi-types.h"
 
 ''',
-                  prefix=prefix))
+               prefix=prefix))
 
 schema = QAPISchema(input_file)
 vis = QAPISchemaGenVisitVisitor()
 schema.visit(vis)
-fdef.write(vis.defn)
-fdecl.write(vis.decl)
+genc.add(vis.defn)
+genh.add(vis.decl)
 
-close_output(fdef, fdecl)
+if do_c:
+    genc.write(output_dir, prefix + 'qapi-visit.c')
+if do_h:
+    genh.write(output_dir, prefix + 'qapi-visit.h')
diff --git a/scripts/qapi.py b/scripts/qapi.py
index 26c45cee34..9693fd1851 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -2,7 +2,7 @@
 # QAPI helper library
 #
 # Copyright IBM, Corp. 2011
-# Copyright (c) 2013-2016 Red Hat Inc.
+# Copyright (c) 2013-2018 Red Hat Inc.
 #
 # Authors:
 #  Anthony Liguori <aliguori@us.ibm.com>
@@ -22,10 +22,6 @@ try:
     from collections import OrderedDict
 except:
     from ordereddict import OrderedDict
-try:
-    from StringIO import StringIO
-except ImportError:
-    from io import StringIO
 
 builtin_types = {
     'null':     'QTYPE_QNULL',
@@ -1831,7 +1827,6 @@ def guardname(filename):
 
 def guardstart(name):
     return mcgen('''
-
 #ifndef %(name)s
 #define %(name)s
 
@@ -1843,7 +1838,6 @@ def guardend(name):
     return mcgen('''
 
 #endif /* %(name)s */
-
 ''',
                  name=guardname(name))
 
@@ -1980,17 +1974,53 @@ def parse_command_line(extra_options='', extra_long_options=[]):
 
     return (fname, output_dir, do_c, do_h, prefix, extra_opts)
 
+
 #
-# Generate output files with boilerplate
+# Accumulate and write output
 #
 
+class QAPIGen(object):
+
+    def __init__(self):
+        self._preamble = ''
+        self._body = ''
+
+    def preamble_add(self, text):
+        self._preamble += text
+
+    def add(self, text):
+        self._body += text
+
+    def _top(self, fname):
+        return ''
+
+    def _bottom(self, fname):
+        return ''
+
+    def write(self, output_dir, fname):
+        if output_dir:
+            try:
+                os.makedirs(output_dir)
+            except os.error as e:
+                if e.errno != errno.EEXIST:
+                    raise
+        f = open(os.path.join(output_dir, fname), 'w')
+        f.write(self._top(fname) + self._preamble + self._body
+                + self._bottom(fname))
+        f.close()
+
+
+class QAPIGenC(QAPIGen):
+
+    def __init__(self, blurb, pydoc):
+        QAPIGen.__init__(self)
+        self._blurb = blurb.strip('\n')
+        self._copyright = '\n * '.join(re.findall(r'^Copyright .*', pydoc,
+                                                  re.MULTILINE))
 
-def open_output(output_dir, do_c, do_h, prefix, c_file, h_file, blurb, doc):
-    guard = guardname(prefix + h_file)
-    c_file = output_dir + prefix + c_file
-    h_file = output_dir + prefix + h_file
-    copyright = '\n * '.join(re.findall(r'^Copyright .*', doc, re.MULTILINE))
-    comment = mcgen('''/* AUTOMATICALLY GENERATED, DO NOT MODIFY */
+    def _top(self, fname):
+        return mcgen('''
+/* AUTOMATICALLY GENERATED, DO NOT MODIFY */
 
 /*
 %(blurb)s
@@ -2002,40 +2032,19 @@ def open_output(output_dir, do_c, do_h, prefix, c_file, h_file, blurb, doc):
  */
 
 ''',
-                    blurb=blurb.strip('\n'), copyright=copyright)
+                     blurb=self._blurb, copyright=self._copyright)
 
-    if output_dir:
-        try:
-            os.makedirs(output_dir)
-        except os.error as e:
-            if e.errno != errno.EEXIST:
-                raise
 
-    def maybe_open(really, name, opt):
-        if really:
-            return open(name, opt)
-        else:
-            return StringIO()
+class QAPIGenH(QAPIGenC):
 
-    fdef = maybe_open(do_c, c_file, 'w')
-    fdecl = maybe_open(do_h, h_file, 'w')
+    def _top(self, fname):
+        return QAPIGenC._top(self, fname) + guardstart(fname)
 
-    fdef.write(comment)
-    fdecl.write(comment)
-    fdecl.write(mcgen('''
-#ifndef %(guard)s
-#define %(guard)s
+    def _bottom(self, fname):
+        return guardend(fname)
 
-''',
-                      guard=guard))
 
-    return (fdef, fdecl)
-
-
-def close_output(fdef, fdecl):
-    fdecl.write(mcgen('''
-
-#endif
-'''))
-    fdecl.close()
-    fdef.close()
+class QAPIGenDoc(QAPIGen):
+    def _top(self, fname):
+        return (QAPIGen._top(self, fname)
+                + '@c AUTOMATICALLY GENERATED, DO NOT MODIFY\n\n')
-- 
2.13.6

  parent reply	other threads:[~2018-02-11  9:36 UTC|newest]

Thread overview: 110+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-02-11  9:35 [Qemu-devel] [PATCH v2 00/29] Modularize generated QAPI code Markus Armbruster
2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 01/29] Include qapi/qmp/qerror.h exactly where needed Markus Armbruster
2018-02-12 16:55   ` Eric Blake
2018-02-13 15:24   ` Marc-Andre Lureau
2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 02/29] qapi: Streamline boilerplate comment generation Markus Armbruster
2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 03/29] qapi: Generate up-to-date copyright notice Markus Armbruster
2018-02-12 19:40   ` Eric Blake
2018-02-16 22:53   ` Michael Roth
2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 04/29] qapi: Rename variable holding the QAPISchemaGenFOOVisitor Markus Armbruster
2018-02-12 16:59   ` Eric Blake
2018-02-13 15:24   ` Marc-Andre Lureau
2018-02-16 22:56   ` Michael Roth
2018-02-11  9:35 ` Markus Armbruster [this message]
2018-02-17  0:59   ` [Qemu-devel] [PATCH v2 05/29] qapi: New classes QAPIGenC, QAPIGenH, QAPIGenDoc Michael Roth
2018-02-23 17:18     ` Markus Armbruster
2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 06/29] qapi: Reduce use of global variables in generators some Markus Armbruster
2018-02-17  1:22   ` Michael Roth
2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 07/29] qapi: Turn generators into modules Markus Armbruster
2018-02-17  1:29   ` Michael Roth
2018-02-27 15:53   ` Eric Blake
2018-02-27 16:01     ` Daniel P. Berrangé
2018-04-13 12:49       ` Markus Armbruster
2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 08/29] qapi-gen: New common driver for code and doc generators Markus Armbruster
2018-02-12 19:42   ` Eric Blake
2018-02-23 17:20     ` Markus Armbruster
2018-02-26 20:02       ` Eric Blake
2018-02-18 22:16   ` Michael Roth
2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 09/29] qapi-gen: Convert from getopt to argparse Markus Armbruster
2018-02-12 19:44   ` Eric Blake
2018-02-13 15:24   ` Marc-Andre Lureau
2018-02-18 22:31   ` Michael Roth
2018-02-23 17:21     ` Markus Armbruster
2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 10/29] qapi: Touch generated files only when they change Markus Armbruster
2018-02-12 19:48   ` Eric Blake
2018-02-13 15:22     ` Marc-Andre Lureau
2018-02-23 17:22       ` Markus Armbruster
2018-02-18 22:43   ` Michael Roth
2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 11/29] qapi: Improve include file name reporting in error messages Markus Armbruster
2018-02-18 23:11   ` Michael Roth
2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 12/29] qapi/common: Eliminate QAPISchema.exprs Markus Armbruster
2018-02-18 23:13   ` Michael Roth
2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 13/29] qapi: Lift error reporting from QAPISchema.__init__() to callers Markus Armbruster
2018-02-12 19:52   ` Eric Blake
2018-02-18 23:17   ` Michael Roth
2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 14/29] qapi: Concentrate QAPISchemaParser.exprs updates in .__init__() Markus Armbruster
2018-02-12 19:56   ` Eric Blake
2018-02-18 23:32   ` Michael Roth
2018-02-23 17:29     ` Markus Armbruster
2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 15/29] qapi: Record 'include' directives in parse tree Markus Armbruster
2018-02-12 20:03   ` Eric Blake
2018-02-18 23:57   ` Michael Roth
2018-02-23 17:31     ` Markus Armbruster
2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 16/29] qapi: Generate in source order Markus Armbruster
2018-02-12 20:06   ` Eric Blake
2018-02-19  0:01   ` Michael Roth
2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 17/29] qapi: Record 'include' directives in intermediate representation Markus Armbruster
2018-02-12 20:34   ` Eric Blake
2018-02-23 17:33     ` Markus Armbruster
2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 18/29] qapi: Rename generated qmp-marshal.c to qmp-commands.c Markus Armbruster
2018-02-12 20:56   ` Eric Blake
2018-02-13 15:25   ` Marc-Andre Lureau
2018-02-19  0:21   ` Michael Roth
2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 19/29] qapi: Make code-generating visitors use QAPIGen more Markus Armbruster
2018-02-12 21:06   ` Eric Blake
2018-02-13 15:25   ` Marc-Andre Lureau
2018-02-19 15:52   ` Michael Roth
2018-02-23 17:35     ` Markus Armbruster
2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 20/29] qapi/types qapi/visit: Generate built-in stuff into separate files Markus Armbruster
2018-02-12 21:44   ` Eric Blake
2018-02-23 17:36     ` Markus Armbruster
2018-02-13 15:25   ` Marc-Andre Lureau
2018-02-19 19:30   ` Michael Roth
2018-02-11  9:35 ` [Qemu-devel] [PATCH v2 21/29] qapi/common: Fix guardname() for funny filenames Markus Armbruster
2018-02-19 18:18   ` Michael Roth
2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 22/29] qapi: Generate separate .h, .c for each module Markus Armbruster
2018-02-12 22:06   ` Eric Blake
2018-02-23 17:41     ` Markus Armbruster
2018-02-26 22:39       ` Eric Blake
2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 23/29] Include less of the generated modular QAPI headers Markus Armbruster
2018-02-12 22:13   ` Eric Blake
2018-02-23 17:47     ` Markus Armbruster
2018-02-13 15:54   ` Marc-Andre Lureau
2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 24/29] qapi: Empty out qapi-schema.json Markus Armbruster
2018-02-12 22:26   ` Eric Blake
2018-02-23 17:50     ` Markus Armbruster
2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 25/29] docs/devel/writing-qmp-commands: Update for modular QAPI Markus Armbruster
2018-02-12 22:27   ` Eric Blake
2018-02-13 16:00   ` Marc-Andre Lureau
2018-02-19 19:33   ` Michael Roth
2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 26/29] docs: Correct outdated information on QAPI Markus Armbruster
2018-02-12 22:29   ` Eric Blake
2018-02-13 16:03   ` Marc-Andre Lureau
2018-02-19 19:35   ` Michael Roth
2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 27/29] qapi: Move qapi-schema.json to qapi/, rename generated files Markus Armbruster
2018-02-12 22:36   ` Eric Blake
2018-02-23 17:51     ` Markus Armbruster
2018-02-13 16:08   ` Marc-Andre Lureau
2018-02-19 19:37   ` Michael Roth
2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 28/29] Fix up dangling references to qmp-commands.* in comment and doc Markus Armbruster
2018-02-12 22:47   ` Eric Blake
2018-02-13 16:12   ` Marc-Andre Lureau
2018-02-19 19:38   ` Michael Roth
2018-02-11  9:36 ` [Qemu-devel] [PATCH v2 29/29] qapi: Don't create useless directory qapi-generated Markus Armbruster
2018-02-12 22:48   ` Eric Blake
2018-02-13 16:15   ` Marc-Andre Lureau
2018-02-19 19:38   ` Michael Roth
2018-02-11 10:16 ` [Qemu-devel] [PATCH v2 00/29] Modularize generated QAPI code no-reply
2018-02-26 22:57 ` [Qemu-devel] [PATCH v2 23.5/29] watchdog: Consolidate QAPI into single file Eric Blake
2018-02-26 23:10   ` Eric Blake
2018-02-27 14:19 ` [Qemu-devel] [PATCH v2 00/29] Modularize generated QAPI code Eric Blake

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20180211093607.27351-6-armbru@redhat.com \
    --to=armbru@redhat.com \
    --cc=eblake@redhat.com \
    --cc=marcandre.lureau@redhat.com \
    --cc=mdroth@linux.vnet.ibm.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.