summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2020-01-14 16:42:27 +0000
committerPeter Maydell <peter.maydell@linaro.org>2020-01-14 16:42:27 +0000
commite021e6fe5294939f286021b3f870666ccb979aa2 (patch)
tree606b0534cb354f1b82017d408b41c2ac2555f320 /scripts
parent3a63b24a1bbf166e6f455fe43a6bbd8dea413d92 (diff)
parent3bef3aaec91815b75a78a4c12ca92ac3cec53faf (diff)
downloadqemu-e021e6fe5294939f286021b3f870666ccb979aa2.zip
Merge remote-tracking branch 'remotes/armbru/tags/pull-qapi-2020-01-14' into staging
QAPI patches for 2020-01-14 # gpg: Signature made Tue 14 Jan 2020 10:15:22 GMT # gpg: using RSA key 354BC8B3D7EB2A6B68674E5F3870B400EB918653 # gpg: issuer "armbru@redhat.com" # gpg: Good signature from "Markus Armbruster <armbru@redhat.com>" [full] # gpg: aka "Markus Armbruster <armbru@pond.sub.org>" [full] # Primary key fingerprint: 354B C8B3 D7EB 2A6B 6867 4E5F 3870 B400 EB91 8653 * remotes/armbru/tags/pull-qapi-2020-01-14: qapi: Simplify QAPISchemaModularCVisitor qapi: Fix code generation for empty modules qapi: Proper intermediate representation for modules qapi: Generate command registration stuff into separate files tests/Makefile.include: Fix missing test-qapi-emit-events.[ch] qapi: Tweak "command returns a nice type" check for clarity Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'scripts')
-rw-r--r--scripts/qapi/commands.py17
-rw-r--r--scripts/qapi/events.py2
-rw-r--r--scripts/qapi/gen.py28
-rw-r--r--scripts/qapi/schema.py92
-rw-r--r--scripts/qapi/types.py5
-rw-r--r--scripts/qapi/visit.py8
6 files changed, 93 insertions, 59 deletions
diff --git a/scripts/qapi/commands.py b/scripts/qapi/commands.py
index ab98e504f3..afa55b055c 100644
--- a/scripts/qapi/commands.py
+++ b/scripts/qapi/commands.py
@@ -239,7 +239,7 @@ class QAPISchemaGenCommandVisitor(QAPISchemaModularCVisitor):
def __init__(self, prefix):
QAPISchemaModularCVisitor.__init__(
self, prefix, 'qapi-commands',
- ' * Schema-defined QAPI/QMP commands', __doc__)
+ ' * Schema-defined QAPI/QMP commands', None, __doc__)
self._regy = QAPIGenCCode(None)
self._visited_ret_types = {}
@@ -263,18 +263,25 @@ class QAPISchemaGenCommandVisitor(QAPISchemaModularCVisitor):
commands=commands, visit=visit))
self._genh.add(mcgen('''
#include "%(types)s.h"
-#include "qapi/qmp/dispatch.h"
''',
types=types))
def visit_end(self):
- (genc, genh) = self._module[self._main_module]
- genh.add(mcgen('''
+ self._add_system_module('init', ' * QAPI Commands initialization')
+ self._genh.add(mcgen('''
+#include "qapi/qmp/dispatch.h"
+
void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds);
''',
c_prefix=c_name(self._prefix, protect=False)))
- genc.add(gen_registry(self._regy.get_content(), self._prefix))
+ self._genc.preamble_add(mcgen('''
+#include "qemu/osdep.h"
+#include "%(prefix)sqapi-commands.h"
+#include "%(prefix)sqapi-init-commands.h"
+''',
+ prefix=self._prefix))
+ self._genc.add(gen_registry(self._regy.get_content(), self._prefix))
def visit_command(self, name, info, ifcond, arg_type, ret_type, gen,
success_response, boxed, allow_oob, allow_preconfig,
diff --git a/scripts/qapi/events.py b/scripts/qapi/events.py
index 10fc509fa9..2bde3e6128 100644
--- a/scripts/qapi/events.py
+++ b/scripts/qapi/events.py
@@ -140,7 +140,7 @@ class QAPISchemaGenEventVisitor(QAPISchemaModularCVisitor):
def __init__(self, prefix):
QAPISchemaModularCVisitor.__init__(
self, prefix, 'qapi-events',
- ' * Schema-defined QAPI/QMP events', __doc__)
+ ' * Schema-defined QAPI/QMP events', None, __doc__)
self._event_enum_name = c_name(prefix + 'QAPIEvent', protect=False)
self._event_enum_members = []
self._event_emit_name = c_name(prefix + 'qapi_event_emit')
diff --git a/scripts/qapi/gen.py b/scripts/qapi/gen.py
index 112b6d94c5..95afae0615 100644
--- a/scripts/qapi/gen.py
+++ b/scripts/qapi/gen.py
@@ -201,10 +201,11 @@ class QAPISchemaMonolithicCVisitor(QAPISchemaVisitor):
class QAPISchemaModularCVisitor(QAPISchemaVisitor):
- def __init__(self, prefix, what, blurb, pydoc):
+ def __init__(self, prefix, what, user_blurb, builtin_blurb, pydoc):
self._prefix = prefix
self._what = what
- self._blurb = blurb
+ self._user_blurb = user_blurb
+ self._builtin_blurb = builtin_blurb
self._pydoc = pydoc
self._genc = None
self._genh = None
@@ -245,7 +246,7 @@ class QAPISchemaModularCVisitor(QAPISchemaVisitor):
genc = QAPIGenC(basename + '.c', blurb, self._pydoc)
genh = QAPIGenH(basename + '.h', blurb, self._pydoc)
self._module[name] = (genc, genh)
- self._set_module(name)
+ self._genc, self._genh = self._module[name]
def _add_user_module(self, name, blurb):
assert self._is_user_module(name)
@@ -256,9 +257,6 @@ class QAPISchemaModularCVisitor(QAPISchemaVisitor):
def _add_system_module(self, name, blurb):
self._add_module(name and './' + name, blurb)
- def _set_module(self, name):
- self._genc, self._genh = self._module[name]
-
def write(self, output_dir, opt_builtins=False):
for name in self._module:
if self._is_builtin_module(name) and not opt_builtins:
@@ -271,15 +269,17 @@ class QAPISchemaModularCVisitor(QAPISchemaVisitor):
pass
def visit_module(self, name):
- if name in self._module:
- self._set_module(name)
- elif self._is_builtin_module(name):
- # The built-in module has not been created. No code may
- # be generated.
- self._genc = None
- self._genh = None
+ if name is None:
+ if self._builtin_blurb:
+ self._add_system_module(None, self._builtin_blurb)
+ self._begin_system_module(name)
+ else:
+ # The built-in module has not been created. No code may
+ # be generated.
+ self._genc = None
+ self._genh = None
else:
- self._add_user_module(name, self._blurb)
+ self._add_user_module(name, self._user_blurb)
self._begin_user_module(name)
def visit_include(self, name, info):
diff --git a/scripts/qapi/schema.py b/scripts/qapi/schema.py
index cf0045f34e..0bfc5256fb 100644
--- a/scripts/qapi/schema.py
+++ b/scripts/qapi/schema.py
@@ -50,9 +50,6 @@ class QAPISchemaEntity(object):
def check(self, schema):
assert not self._checked
- if self.info:
- self._module = os.path.relpath(self.info.fname,
- os.path.dirname(schema.fname))
seen = {}
for f in self.features:
f.check_clash(self.info, seen)
@@ -68,15 +65,18 @@ class QAPISchemaEntity(object):
if self.doc:
self.doc.check()
- @property
- def ifcond(self):
+ def _set_module(self, schema, info):
assert self._checked
- return self._ifcond
+ self._module = schema.module_by_fname(info and info.fname)
+ self._module.add_entity(self)
+
+ def set_module(self, schema):
+ self._set_module(schema, self.info)
@property
- def module(self):
+ def ifcond(self):
assert self._checked
- return self._module
+ return self._ifcond
def is_implicit(self):
return not self.info
@@ -135,15 +135,29 @@ class QAPISchemaVisitor(object):
pass
-class QAPISchemaInclude(QAPISchemaEntity):
+class QAPISchemaModule(object):
+ def __init__(self, name):
+ self.name = name
+ self._entity_list = []
+
+ def add_entity(self, ent):
+ self._entity_list.append(ent)
+
+ def visit(self, visitor):
+ visitor.visit_module(self.name)
+ for entity in self._entity_list:
+ if visitor.visit_needed(entity):
+ entity.visit(visitor)
- def __init__(self, fname, info):
+
+class QAPISchemaInclude(QAPISchemaEntity):
+ def __init__(self, sub_module, info):
QAPISchemaEntity.__init__(self, None, info, None)
- self.fname = fname
+ self._sub_module = sub_module
def visit(self, visitor):
QAPISchemaEntity.visit(self, visitor)
- visitor.visit_include(self.fname, self.info)
+ visitor.visit_include(self._sub_module.name, self.info)
class QAPISchemaType(QAPISchemaEntity):
@@ -276,16 +290,14 @@ class QAPISchemaArrayType(QAPISchemaType):
self.info and self.info.defn_meta)
assert not isinstance(self.element_type, QAPISchemaArrayType)
+ def set_module(self, schema):
+ self._set_module(schema, self.element_type.info)
+
@property
def ifcond(self):
assert self._checked
return self.element_type.ifcond
- @property
- def module(self):
- assert self._checked
- return self.element_type.module
-
def is_implicit(self):
return True
@@ -711,10 +723,11 @@ class QAPISchemaCommand(QAPISchemaEntity):
self.ret_type = schema.resolve_type(
self._ret_type_name, self.info, "command's 'returns'")
if self.name not in self.info.pragma.returns_whitelist:
- if not (isinstance(self.ret_type, QAPISchemaObjectType)
- or (isinstance(self.ret_type, QAPISchemaArrayType)
- and isinstance(self.ret_type.element_type,
- QAPISchemaObjectType))):
+ typ = self.ret_type
+ if isinstance(typ, QAPISchemaArrayType):
+ typ = self.ret_type.element_type
+ assert typ
+ if not isinstance(typ, QAPISchemaObjectType):
raise QAPISemError(
self.info,
"command's 'returns' cannot take %s"
@@ -782,6 +795,10 @@ class QAPISchema(object):
self.docs = parser.docs
self._entity_list = []
self._entity_dict = {}
+ self._module_dict = {}
+ self._schema_dir = os.path.dirname(fname)
+ self._make_module(None) # built-ins
+ self._make_module(fname)
self._predefining = True
self._def_predefineds()
self._predefining = False
@@ -825,14 +842,26 @@ class QAPISchema(object):
info, "%s uses unknown type '%s'" % (what, name))
return typ
+ def _module_name(self, fname):
+ if fname is None:
+ return None
+ return os.path.relpath(fname, self._schema_dir)
+
+ def _make_module(self, fname):
+ name = self._module_name(fname)
+ if not name in self._module_dict:
+ self._module_dict[name] = QAPISchemaModule(name)
+ return self._module_dict[name]
+
+ def module_by_fname(self, fname):
+ name = self._module_name(fname)
+ assert name in self._module_dict
+ return self._module_dict[name]
+
def _def_include(self, expr, info, doc):
include = expr['include']
assert doc is None
- main_info = info
- while main_info.parent:
- main_info = main_info.parent
- fname = os.path.relpath(include, os.path.dirname(main_info.fname))
- self._def_entity(QAPISchemaInclude(fname, info))
+ self._def_entity(QAPISchemaInclude(self._make_module(include), info))
def _def_builtin_type(self, name, json_type, c_type):
self._def_entity(QAPISchemaBuiltinType(name, json_type, c_type))
@@ -1064,15 +1093,12 @@ class QAPISchema(object):
ent.check(self)
ent.connect_doc()
ent.check_doc()
+ for ent in self._entity_list:
+ ent.set_module(self)
def visit(self, visitor):
visitor.visit_begin(self)
module = None
- visitor.visit_module(module)
- for entity in self._entity_list:
- if visitor.visit_needed(entity):
- if entity.module != module:
- module = entity.module
- visitor.visit_module(module)
- entity.visit(visitor)
+ for mod in self._module_dict.values():
+ mod.visit(visitor)
visitor.visit_end()
diff --git a/scripts/qapi/types.py b/scripts/qapi/types.py
index d8751daa04..99dcaf7074 100644
--- a/scripts/qapi/types.py
+++ b/scripts/qapi/types.py
@@ -243,8 +243,9 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
def __init__(self, prefix):
QAPISchemaModularCVisitor.__init__(
self, prefix, 'qapi-types', ' * Schema-defined QAPI types',
- __doc__)
- self._add_system_module(None, ' * Built-in QAPI types')
+ ' * Built-in QAPI types', __doc__)
+
+ def _begin_system_module(self, name):
self._genc.preamble_add(mcgen('''
#include "qemu/osdep.h"
#include "qapi/dealloc-visitor.h"
diff --git a/scripts/qapi/visit.py b/scripts/qapi/visit.py
index c72f2bc5c0..4efce62b0c 100644
--- a/scripts/qapi/visit.py
+++ b/scripts/qapi/visit.py
@@ -285,8 +285,9 @@ class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor):
def __init__(self, prefix):
QAPISchemaModularCVisitor.__init__(
self, prefix, 'qapi-visit', ' * Schema-defined QAPI visitors',
- __doc__)
- self._add_system_module(None, ' * Built-in QAPI visitors')
+ ' * Built-in QAPI visitors', __doc__)
+
+ def _begin_system_module(self, name):
self._genc.preamble_add(mcgen('''
#include "qemu/osdep.h"
#include "qapi/error.h"
@@ -296,8 +297,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor):
#include "qapi/visitor.h"
#include "qapi/qapi-builtin-types.h"
-''',
- prefix=prefix))
+'''))
def _begin_user_module(self, name):
types = self._module_basename('qapi-types', name)