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>
This commit is contained in:
parent
d46eec4260
commit
47a6ea9aab
@ -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')
|
||||
|
@ -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')
|
||||
|
@ -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')
|
||||
|
@ -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')
|
||||
|
@ -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')
|
||||
|
106
scripts/qapi.py
106
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 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 __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
|
||||
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)
|
||||
|
||||
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')
|
||||
|
||||
fdef.write(comment)
|
||||
fdecl.write(comment)
|
||||
fdecl.write(mcgen('''
|
||||
#ifndef %(guard)s
|
||||
#define %(guard)s
|
||||
|
||||
''',
|
||||
guard=guard))
|
||||
|
||||
return (fdef, fdecl)
|
||||
blurb=self._blurb, copyright=self._copyright)
|
||||
|
||||
|
||||
def close_output(fdef, fdecl):
|
||||
fdecl.write(mcgen('''
|
||||
class QAPIGenH(QAPIGenC):
|
||||
|
||||
#endif
|
||||
'''))
|
||||
fdecl.close()
|
||||
fdef.close()
|
||||
def _top(self, fname):
|
||||
return QAPIGenC._top(self, fname) + guardstart(fname)
|
||||
|
||||
def _bottom(self, fname):
|
||||
return guardend(fname)
|
||||
|
||||
|
||||
class QAPIGenDoc(QAPIGen):
|
||||
|
||||
def _top(self, fname):
|
||||
return (QAPIGen._top(self, fname)
|
||||
+ '@c AUTOMATICALLY GENERATED, DO NOT MODIFY\n\n')
|
||||
|
Loading…
Reference in New Issue
Block a user