From 03c3b81d7a037792020e7ec989fcb1c3fb8ee92e Mon Sep 17 00:00:00 2001 From: Markus Armbruster Date: Fri, 9 Mar 2018 07:53:43 -0500 Subject: [PATCH] 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. Backports commit 47a6ea9aab1d857015684cda387ffba05a036721 from qemu --- qemu/scripts/qapi-event.py | 22 ++++---- qemu/scripts/qapi-types.py | 24 +++++---- qemu/scripts/qapi-visit.py | 24 +++++---- qemu/scripts/qapi.py | 105 ++++++++++++++++++++----------------- 4 files changed, 97 insertions(+), 78 deletions(-) diff --git a/qemu/scripts/qapi-event.py b/qemu/scripts/qapi-event.py index b98f2f42..0384d1a2 100644 --- a/qemu/scripts/qapi-event.py +++ b/qemu/scripts/qapi-event.py @@ -173,11 +173,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-common.h" #include "%(prefix)sqapi-event.h" #include "%(prefix)sqapi-visit.h" @@ -187,20 +186,23 @@ fdef.write(mcgen(''' #include "qapi/qmp-event.h" ''', - prefix=prefix)) + prefix=prefix)) -fdecl.write(mcgen(''' +genh.add(mcgen(''' #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/qemu/scripts/qapi-types.py b/qemu/scripts/qapi-types.py index 3d1dd8a1..7828a081 100644 --- a/qemu/scripts/qapi-types.py +++ b/qemu/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,22 +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)) + +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/qemu/scripts/qapi-visit.py b/qemu/scripts/qapi-visit.py index ce82e242..3c72bd0d 100644 --- a/qemu/scripts/qapi-visit.py +++ b/qemu/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 "%(prefix)sqapi-visit.h" ''', - prefix=prefix)) + prefix=prefix)) -fdecl.write(mcgen(''' +genh.add(mcgen(''' #include "qapi/visitor.h" #include "qapi/qmp/qerror.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/qemu/scripts/qapi.py b/qemu/scripts/qapi.py index 72aa293c..d03848b8 100644 --- a/qemu/scripts/qapi.py +++ b/qemu/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 @@ -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', @@ -1840,7 +1836,6 @@ def guardname(filename): def guardstart(name): return mcgen(''' - #ifndef %(name)s #define %(name)s @@ -1852,7 +1847,6 @@ def guardend(name): return mcgen(''' #endif /* %(name)s */ - ''', name=guardname(name)) @@ -1985,17 +1979,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 @@ -2007,40 +2037,19 @@ 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): + 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') -#endif -''')) - fdecl.close() - fdef.close()