aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarkus Armbruster <armbru@redhat.com>2018-02-26 13:19:40 -0600
committerEric Blake <eblake@redhat.com>2018-03-02 13:14:09 -0600
commit47a6ea9aab1d857015684cda387ffba05a036721 (patch)
treecb0682a858e5a545bdb525c1b96364a91e6d22c6
parentd46eec4260540d83bafba91608842ab03dabf339 (diff)
downloadqemu-47a6ea9aab1d857015684cda387ffba05a036721.zip
qemu-47a6ea9aab1d857015684cda387ffba05a036721.tar.gz
qemu-47a6ea9aab1d857015684cda387ffba05a036721.tar.bz2
qapi: New classes QAPIGenC, QAPIGenH, QAPIGenDoc
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> Message-Id: <20180211093607.27351-6-armbru@redhat.com> Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com> [eblake: fix nits spotted by Michael] Signed-off-by: Eric Blake <eblake@redhat.com>
-rw-r--r--scripts/qapi-commands.py23
-rw-r--r--scripts/qapi-event.py22
-rw-r--r--scripts/qapi-introspect.py18
-rw-r--r--scripts/qapi-types.py22
-rw-r--r--scripts/qapi-visit.py24
-rw-r--r--scripts/qapi.py98
6 files changed, 113 insertions, 94 deletions
diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
index 114c5ad..8435a89 100644
--- a/scripts/qapi-commands.py
+++ b/scripts/qapi-commands.py
@@ -258,12 +258,10 @@ class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
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"
@@ -278,20 +276,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 9de5c67..e063f6b 100644
--- a/scripts/qapi-event.py
+++ b/scripts/qapi-event.py
@@ -174,11 +174,10 @@ class QAPISchemaGenEventVisitor(QAPISchemaVisitor):
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"
@@ -189,21 +188,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 7a01a8f..0638acd 100644
--- a/scripts/qapi-introspect.py
+++ b/scripts/qapi-introspect.py
@@ -179,21 +179,23 @@ for o, a in opts:
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 524d220..1eb59b1 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
@@ -254,26 +254,28 @@ for o, a in opts:
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 0e78cf3..51eeaa1 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -272,7 +272,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
def visit_begin(self, schema):
self.decl = ''
self.defn = ''
- self._btin = guardstart('QAPI_VISIT_BUILTIN')
+ self._btin = '\n' + guardstart('QAPI_VISIT_BUILTIN')
def visit_end(self):
# To avoid header dependency hell, we always generate
@@ -337,30 +337,32 @@ for o, a in opts:
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 d2695cd..f12cddd 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 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 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
+ self._copyright = '\n * '.join(re.findall(r'^Copyright .*', pydoc,
+ re.MULTILINE))
+
+ def _top(self, fname):
+ return mcgen('''
+/* AUTOMATICALLY GENERATED, DO NOT MODIFY */
/*
%(blurb)s
@@ -2002,40 +2032,20 @@ def open_output(output_dir, do_c, do_h, prefix, c_file, h_file, blurb, doc):
*/
''',
- blurb=blurb, 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()
- fdef = maybe_open(do_c, c_file, 'w')
- fdecl = maybe_open(do_h, h_file, 'w')
+class QAPIGenH(QAPIGenC):
- fdef.write(comment)
- fdecl.write(comment)
- fdecl.write(mcgen('''
-#ifndef %(guard)s
-#define %(guard)s
-
-''',
- guard=guard))
+ def _top(self, fname):
+ return QAPIGenC._top(self, fname) + guardstart(fname)
- return (fdef, fdecl)
+ def _bottom(self, fname):
+ return guardend(fname)
-def close_output(fdef, fdecl):
- fdecl.write(mcgen('''
+class QAPIGenDoc(QAPIGen):
-#endif
-'''))
- fdecl.close()
- fdef.close()
+ def _top(self, fname):
+ return (QAPIGen._top(self, fname)
+ + '@c AUTOMATICALLY GENERATED, DO NOT MODIFY\n\n')