aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--scripts/qapi.py74
1 files changed, 47 insertions, 27 deletions
diff --git a/scripts/qapi.py b/scripts/qapi.py
index 471bbfc406..9d53255320 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -790,6 +790,11 @@ class QAPISchemaEntity(object):
def __init__(self, name, info):
assert isinstance(name, str)
self.name = name
+ # For explicitly defined entities, info points to the (explicit)
+ # definition. For builtins (and their arrays), info is None.
+ # For implicitly defined entities, info points to a place that
+ # triggered the implicit definition (there may be more than one
+ # such place).
self.info = info
def c_name(self):
@@ -903,6 +908,10 @@ class QAPISchemaEnumType(QAPISchemaType):
def check(self, schema):
assert len(set(self.values)) == len(self.values)
+ def is_implicit(self):
+ # See QAPISchema._make_implicit_enum_type()
+ return self.name[-4:] == 'Kind'
+
def c_type(self, is_param=False):
return c_name(self.name)
@@ -929,6 +938,9 @@ class QAPISchemaArrayType(QAPISchemaType):
self.element_type = schema.lookup_type(self._element_type_name)
assert self.element_type
+ def is_implicit(self):
+ return True
+
def json_type(self):
return 'array'
@@ -973,6 +985,10 @@ class QAPISchemaObjectType(QAPISchemaType):
self.variants.check(schema, members, seen)
self.members = members
+ def is_implicit(self):
+ # See QAPISchema._make_implicit_object_type()
+ return self.name[0] == ':'
+
def c_name(self):
assert not self.is_implicit()
return QAPISchemaType.c_name(self)
@@ -1120,7 +1136,9 @@ class QAPISchema(object):
try:
self.exprs = check_exprs(QAPISchemaParser(open(fname, "r")).exprs)
self._entity_dict = {}
+ self._predefining = True
self._def_predefineds()
+ self._predefining = False
self._def_exprs()
self.check()
except (QAPISchemaError, QAPIExprError), err:
@@ -1128,6 +1146,8 @@ class QAPISchema(object):
exit(1)
def _def_entity(self, ent):
+ # Only the predefined types are allowed to not have info
+ assert ent.info or self._predefining
assert ent.name not in self._entity_dict
self._entity_dict[ent.name] = ent
@@ -1148,7 +1168,7 @@ class QAPISchema(object):
# declared in the first file whether or not they are used. Nicer
# would be to use lazy instantiation, while figuring out how to
# avoid compilation issues with multiple qapi-types.h.
- self._make_array_type(name)
+ self._make_array_type(name, None)
def _def_predefineds(self):
for t in [('str', 'string', 'char' + pointer_suffix, 'NULL'),
@@ -1170,25 +1190,25 @@ class QAPISchema(object):
[], None)
self._def_entity(self.the_empty_object_type)
- def _make_implicit_enum_type(self, name, values):
+ def _make_implicit_enum_type(self, name, info, values):
name = name + 'Kind' # Use namespace reserved by add_name()
- self._def_entity(QAPISchemaEnumType(name, None, values, None))
+ self._def_entity(QAPISchemaEnumType(name, info, values, None))
return name
- def _make_array_type(self, element_type):
+ def _make_array_type(self, element_type, info):
# TODO fooList namespace is not reserved; user can create collisions,
# or abuse our type system with ['fooList'] for 2D array
name = element_type + 'List'
if not self.lookup_type(name):
- self._def_entity(QAPISchemaArrayType(name, None, element_type))
+ self._def_entity(QAPISchemaArrayType(name, info, element_type))
return name
- def _make_implicit_object_type(self, name, role, members):
+ def _make_implicit_object_type(self, name, info, role, members):
if not members:
return None
name = ':obj-%s-%s' % (name, role)
if not self.lookup_entity(name, QAPISchemaObjectType):
- self._def_entity(QAPISchemaObjectType(name, None, None,
+ self._def_entity(QAPISchemaObjectType(name, info, None,
members, None))
return name
@@ -1198,18 +1218,18 @@ class QAPISchema(object):
prefix = expr.get('prefix')
self._def_entity(QAPISchemaEnumType(name, info, data, prefix))
- def _make_member(self, name, typ):
+ def _make_member(self, name, typ, info):
optional = False
if name.startswith('*'):
name = name[1:]
optional = True
if isinstance(typ, list):
assert len(typ) == 1
- typ = self._make_array_type(typ[0])
+ typ = self._make_array_type(typ[0], info)
return QAPISchemaObjectTypeMember(name, typ, optional)
- def _make_members(self, data):
- return [self._make_member(key, value)
+ def _make_members(self, data, info):
+ return [self._make_member(key, value, info)
for (key, value) in data.iteritems()]
def _def_struct_type(self, expr, info):
@@ -1217,22 +1237,22 @@ class QAPISchema(object):
base = expr.get('base')
data = expr['data']
self._def_entity(QAPISchemaObjectType(name, info, base,
- self._make_members(data),
+ self._make_members(data, info),
None))
def _make_variant(self, case, typ):
return QAPISchemaObjectTypeVariant(case, typ)
- def _make_simple_variant(self, case, typ):
+ def _make_simple_variant(self, case, typ, info):
if isinstance(typ, list):
assert len(typ) == 1
- typ = self._make_array_type(typ[0])
- typ = self._make_implicit_object_type(typ, 'wrapper',
- [self._make_member('data', typ)])
+ typ = self._make_array_type(typ[0], info)
+ typ = self._make_implicit_object_type(
+ typ, info, 'wrapper', [self._make_member('data', typ, info)])
return QAPISchemaObjectTypeVariant(case, typ)
- def _make_implicit_tag(self, type_name, variants):
- typ = self._make_implicit_enum_type(type_name,
+ def _make_implicit_tag(self, type_name, info, variants):
+ typ = self._make_implicit_enum_type(type_name, info,
[v.name for v in variants])
return QAPISchemaObjectTypeMember('type', typ, False)
@@ -1246,12 +1266,12 @@ class QAPISchema(object):
variants = [self._make_variant(key, value)
for (key, value) in data.iteritems()]
else:
- variants = [self._make_simple_variant(key, value)
+ variants = [self._make_simple_variant(key, value, info)
for (key, value) in data.iteritems()]
- tag_member = self._make_implicit_tag(name, variants)
+ tag_member = self._make_implicit_tag(name, info, variants)
self._def_entity(
QAPISchemaObjectType(name, info, base,
- self._make_members(OrderedDict()),
+ self._make_members(OrderedDict(), info),
QAPISchemaObjectTypeVariants(tag_name,
tag_member,
variants)))
@@ -1261,7 +1281,7 @@ class QAPISchema(object):
data = expr['data']
variants = [self._make_variant(key, value)
for (key, value) in data.iteritems()]
- tag_member = self._make_implicit_tag(name, variants)
+ tag_member = self._make_implicit_tag(name, info, variants)
self._def_entity(
QAPISchemaAlternateType(name, info,
QAPISchemaObjectTypeVariants(None,
@@ -1275,11 +1295,11 @@ class QAPISchema(object):
gen = expr.get('gen', True)
success_response = expr.get('success-response', True)
if isinstance(data, OrderedDict):
- data = self._make_implicit_object_type(name, 'arg',
- self._make_members(data))
+ data = self._make_implicit_object_type(
+ name, info, 'arg', self._make_members(data, info))
if isinstance(rets, list):
assert len(rets) == 1
- rets = self._make_array_type(rets[0])
+ rets = self._make_array_type(rets[0], info)
self._def_entity(QAPISchemaCommand(name, info, data, rets, gen,
success_response))
@@ -1287,8 +1307,8 @@ class QAPISchema(object):
name = expr['event']
data = expr.get('data')
if isinstance(data, OrderedDict):
- data = self._make_implicit_object_type(name, 'arg',
- self._make_members(data))
+ data = self._make_implicit_object_type(
+ name, info, 'arg', self._make_members(data, info))
self._def_entity(QAPISchemaEvent(name, info, data))
def _def_exprs(self):