mirror of https://github.com/xemu-project/xemu.git
qapi: Add feature flags to remaining definitions
In v4.1.0, we added feature flags just to struct types (commit 6a8c0b5102^..f3ed93d545), to satisfy an immediate need (commitc9d4070991
"file-posix: Add dynamic-auto-read-only QAPI feature"). In v4.2.0, we added them to commands (commit23394b4c39
"qapi: Add feature flags to commands") to satisfy another immediate need (commit d76744e65e "qapi: Allow introspecting fix for savevm's cooperation with blockdev"). Add them to the remaining definitions: enumeration types, union types, alternate types, and events. Signed-off-by: Markus Armbruster <armbru@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Message-Id: <20200317115459.31821-13-armbru@redhat.com>
This commit is contained in:
parent
e4405b3069
commit
013b4efc9b
|
@ -172,7 +172,8 @@ Syntax:
|
||||||
ENUM = { 'enum': STRING,
|
ENUM = { 'enum': STRING,
|
||||||
'data': [ ENUM-VALUE, ... ],
|
'data': [ ENUM-VALUE, ... ],
|
||||||
'*prefix': STRING,
|
'*prefix': STRING,
|
||||||
'*if': COND }
|
'*if': COND,
|
||||||
|
'*features': FEATURES }
|
||||||
ENUM-VALUE = STRING
|
ENUM-VALUE = STRING
|
||||||
| { 'name': STRING, '*if': COND }
|
| { 'name': STRING, '*if': COND }
|
||||||
|
|
||||||
|
@ -207,6 +208,9 @@ the job satisfactorily.
|
||||||
The optional 'if' member specifies a conditional. See "Configuring
|
The optional 'if' member specifies a conditional. See "Configuring
|
||||||
the schema" below for more on this.
|
the schema" below for more on this.
|
||||||
|
|
||||||
|
The optional 'features' member specifies features. See "Features"
|
||||||
|
below for more on this.
|
||||||
|
|
||||||
|
|
||||||
=== Type references and array types ===
|
=== Type references and array types ===
|
||||||
|
|
||||||
|
@ -279,12 +283,14 @@ below for more on this.
|
||||||
Syntax:
|
Syntax:
|
||||||
UNION = { 'union': STRING,
|
UNION = { 'union': STRING,
|
||||||
'data': BRANCHES,
|
'data': BRANCHES,
|
||||||
'*if': COND }
|
'*if': COND,
|
||||||
|
'*features': FEATURES }
|
||||||
| { 'union': STRING,
|
| { 'union': STRING,
|
||||||
'data': BRANCHES,
|
'data': BRANCHES,
|
||||||
'base': ( MEMBERS | STRING ),
|
'base': ( MEMBERS | STRING ),
|
||||||
'discriminator': STRING,
|
'discriminator': STRING,
|
||||||
'*if': COND }
|
'*if': COND,
|
||||||
|
'*features': FEATURES }
|
||||||
BRANCHES = { BRANCH, ... }
|
BRANCHES = { BRANCH, ... }
|
||||||
BRANCH = STRING : TYPE-REF
|
BRANCH = STRING : TYPE-REF
|
||||||
| STRING : { 'type': TYPE-REF, '*if': COND }
|
| STRING : { 'type': TYPE-REF, '*if': COND }
|
||||||
|
@ -391,13 +397,17 @@ is identical on the wire to:
|
||||||
The optional 'if' member specifies a conditional. See "Configuring
|
The optional 'if' member specifies a conditional. See "Configuring
|
||||||
the schema" below for more on this.
|
the schema" below for more on this.
|
||||||
|
|
||||||
|
The optional 'features' member specifies features. See "Features"
|
||||||
|
below for more on this.
|
||||||
|
|
||||||
|
|
||||||
=== Alternate types ===
|
=== Alternate types ===
|
||||||
|
|
||||||
Syntax:
|
Syntax:
|
||||||
ALTERNATE = { 'alternate': STRING,
|
ALTERNATE = { 'alternate': STRING,
|
||||||
'data': ALTERNATIVES,
|
'data': ALTERNATIVES,
|
||||||
'*if': COND }
|
'*if': COND,
|
||||||
|
'*features': FEATURES }
|
||||||
ALTERNATIVES = { ALTERNATIVE, ... }
|
ALTERNATIVES = { ALTERNATIVE, ... }
|
||||||
ALTERNATIVE = STRING : STRING
|
ALTERNATIVE = STRING : STRING
|
||||||
| STRING : { 'type': STRING, '*if': COND }
|
| STRING : { 'type': STRING, '*if': COND }
|
||||||
|
@ -441,6 +451,9 @@ following example objects:
|
||||||
The optional 'if' member specifies a conditional. See "Configuring
|
The optional 'if' member specifies a conditional. See "Configuring
|
||||||
the schema" below for more on this.
|
the schema" below for more on this.
|
||||||
|
|
||||||
|
The optional 'features' member specifies features. See "Features"
|
||||||
|
below for more on this.
|
||||||
|
|
||||||
|
|
||||||
=== Commands ===
|
=== Commands ===
|
||||||
|
|
||||||
|
@ -584,6 +597,9 @@ started with --preconfig.
|
||||||
The optional 'if' member specifies a conditional. See "Configuring
|
The optional 'if' member specifies a conditional. See "Configuring
|
||||||
the schema" below for more on this.
|
the schema" below for more on this.
|
||||||
|
|
||||||
|
The optional 'features' member specifies features. See "Features"
|
||||||
|
below for more on this.
|
||||||
|
|
||||||
|
|
||||||
=== Events ===
|
=== Events ===
|
||||||
|
|
||||||
|
@ -595,7 +611,8 @@ Syntax:
|
||||||
'data': STRING,
|
'data': STRING,
|
||||||
'boxed': true,
|
'boxed': true,
|
||||||
)
|
)
|
||||||
'*if': COND }
|
'*if': COND,
|
||||||
|
'*features': FEATURES }
|
||||||
|
|
||||||
Member 'event' names the event. This is the event name used in the
|
Member 'event' names the event. This is the event name used in the
|
||||||
Client JSON Protocol.
|
Client JSON Protocol.
|
||||||
|
@ -628,6 +645,9 @@ complex type. See section "Code generated for events" for examples.
|
||||||
The optional 'if' member specifies a conditional. See "Configuring
|
The optional 'if' member specifies a conditional. See "Configuring
|
||||||
the schema" below for more on this.
|
the schema" below for more on this.
|
||||||
|
|
||||||
|
The optional 'features' member specifies features. See "Features"
|
||||||
|
below for more on this.
|
||||||
|
|
||||||
|
|
||||||
=== Features ===
|
=== Features ===
|
||||||
|
|
||||||
|
@ -966,8 +986,9 @@ schema, along with the SchemaInfo type. This text attempts to give an
|
||||||
overview how things work. For details you need to consult the QAPI
|
overview how things work. For details you need to consult the QAPI
|
||||||
schema.
|
schema.
|
||||||
|
|
||||||
SchemaInfo objects have common members "name", "meta-type", and
|
SchemaInfo objects have common members "name", "meta-type",
|
||||||
additional variant members depending on the value of meta-type.
|
"features", and additional variant members depending on the value of
|
||||||
|
meta-type.
|
||||||
|
|
||||||
Each SchemaInfo object describes a wire ABI entity of a certain
|
Each SchemaInfo object describes a wire ABI entity of a certain
|
||||||
meta-type: a command, event or one of several kinds of type.
|
meta-type: a command, event or one of several kinds of type.
|
||||||
|
@ -980,19 +1001,21 @@ not. Therefore, the SchemaInfo for types have auto-generated
|
||||||
meaningless names. For readability, the examples in this section use
|
meaningless names. For readability, the examples in this section use
|
||||||
meaningful type names instead.
|
meaningful type names instead.
|
||||||
|
|
||||||
|
Optional member "features" exposes the entity's feature strings as a
|
||||||
|
JSON array of strings.
|
||||||
|
|
||||||
To examine a type, start with a command or event using it, then follow
|
To examine a type, start with a command or event using it, then follow
|
||||||
references by name.
|
references by name.
|
||||||
|
|
||||||
QAPI schema definitions not reachable that way are omitted.
|
QAPI schema definitions not reachable that way are omitted.
|
||||||
|
|
||||||
The SchemaInfo for a command has meta-type "command", and variant
|
The SchemaInfo for a command has meta-type "command", and variant
|
||||||
members "arg-type", "ret-type", "allow-oob", and "features". On the
|
members "arg-type", "ret-type" and "allow-oob". On the wire, the
|
||||||
wire, the "arguments" member of a client's "execute" command must
|
"arguments" member of a client's "execute" command must conform to the
|
||||||
conform to the object type named by "arg-type". The "return" member
|
object type named by "arg-type". The "return" member that the server
|
||||||
that the server passes in a success response conforms to the type
|
passes in a success response conforms to the type named by "ret-type".
|
||||||
named by "ret-type". When "allow-oob" is true, it means the command
|
When "allow-oob" is true, it means the command supports out-of-band
|
||||||
supports out-of-band execution. It defaults to false. "features"
|
execution. It defaults to false.
|
||||||
exposes the command's feature strings as a JSON array of strings.
|
|
||||||
|
|
||||||
If the command takes no arguments, "arg-type" names an object type
|
If the command takes no arguments, "arg-type" names an object type
|
||||||
without members. Likewise, if the command returns nothing, "ret-type"
|
without members. Likewise, if the command returns nothing, "ret-type"
|
||||||
|
@ -1027,8 +1050,7 @@ Example: the SchemaInfo for EVENT_C from section Events
|
||||||
|
|
||||||
The SchemaInfo for struct and union types has meta-type "object".
|
The SchemaInfo for struct and union types has meta-type "object".
|
||||||
|
|
||||||
The SchemaInfo for a struct type has variant members "members" and
|
The SchemaInfo for a struct type has variant member "members".
|
||||||
"features".
|
|
||||||
|
|
||||||
The SchemaInfo for a union type additionally has variant members "tag"
|
The SchemaInfo for a union type additionally has variant members "tag"
|
||||||
and "variants".
|
and "variants".
|
||||||
|
|
|
@ -89,12 +89,18 @@
|
||||||
#
|
#
|
||||||
# @meta-type: the entity's meta type, inherited from @base.
|
# @meta-type: the entity's meta type, inherited from @base.
|
||||||
#
|
#
|
||||||
|
# @features: names of features associated with the entity, in no
|
||||||
|
# particular order.
|
||||||
|
# (since 4.1 for object types, 4.2 for commands, 5.0 for
|
||||||
|
# the rest)
|
||||||
|
#
|
||||||
# Additional members depend on the value of @meta-type.
|
# Additional members depend on the value of @meta-type.
|
||||||
#
|
#
|
||||||
# Since: 2.5
|
# Since: 2.5
|
||||||
##
|
##
|
||||||
{ 'union': 'SchemaInfo',
|
{ 'union': 'SchemaInfo',
|
||||||
'base': { 'name': 'str', 'meta-type': 'SchemaMetaType' },
|
'base': { 'name': 'str', 'meta-type': 'SchemaMetaType',
|
||||||
|
'*features': [ 'str' ] },
|
||||||
'discriminator': 'meta-type',
|
'discriminator': 'meta-type',
|
||||||
'data': {
|
'data': {
|
||||||
'builtin': 'SchemaInfoBuiltin',
|
'builtin': 'SchemaInfoBuiltin',
|
||||||
|
@ -174,9 +180,6 @@
|
||||||
# and may even differ from the order of the values of the
|
# and may even differ from the order of the values of the
|
||||||
# enum type of the @tag.
|
# enum type of the @tag.
|
||||||
#
|
#
|
||||||
# @features: names of features associated with the type, in no particular
|
|
||||||
# order. (since: 4.1)
|
|
||||||
#
|
|
||||||
# Values of this type are JSON object on the wire.
|
# Values of this type are JSON object on the wire.
|
||||||
#
|
#
|
||||||
# Since: 2.5
|
# Since: 2.5
|
||||||
|
@ -184,8 +187,7 @@
|
||||||
{ 'struct': 'SchemaInfoObject',
|
{ 'struct': 'SchemaInfoObject',
|
||||||
'data': { 'members': [ 'SchemaInfoObjectMember' ],
|
'data': { 'members': [ 'SchemaInfoObjectMember' ],
|
||||||
'*tag': 'str',
|
'*tag': 'str',
|
||||||
'*variants': [ 'SchemaInfoObjectVariant' ],
|
'*variants': [ 'SchemaInfoObjectVariant' ] } }
|
||||||
'*features': [ 'str' ] } }
|
|
||||||
|
|
||||||
##
|
##
|
||||||
# @SchemaInfoObjectMember:
|
# @SchemaInfoObjectMember:
|
||||||
|
@ -266,17 +268,13 @@
|
||||||
# @allow-oob: whether the command allows out-of-band execution,
|
# @allow-oob: whether the command allows out-of-band execution,
|
||||||
# defaults to false (Since: 2.12)
|
# defaults to false (Since: 2.12)
|
||||||
#
|
#
|
||||||
# @features: names of features associated with the command, in no particular
|
|
||||||
# order. (since 4.2)
|
|
||||||
#
|
|
||||||
# TODO: @success-response (currently irrelevant, because it's QGA, not QMP)
|
# TODO: @success-response (currently irrelevant, because it's QGA, not QMP)
|
||||||
#
|
#
|
||||||
# Since: 2.5
|
# Since: 2.5
|
||||||
##
|
##
|
||||||
{ 'struct': 'SchemaInfoCommand',
|
{ 'struct': 'SchemaInfoCommand',
|
||||||
'data': { 'arg-type': 'str', 'ret-type': 'str',
|
'data': { 'arg-type': 'str', 'ret-type': 'str',
|
||||||
'*allow-oob': 'bool',
|
'*allow-oob': 'bool' } }
|
||||||
'*features': [ 'str' ] } }
|
|
||||||
|
|
||||||
##
|
##
|
||||||
# @SchemaInfoEvent:
|
# @SchemaInfoEvent:
|
||||||
|
|
|
@ -243,7 +243,7 @@ class QAPISchemaGenDocVisitor(QAPISchemaVisitor):
|
||||||
def write(self, output_dir):
|
def write(self, output_dir):
|
||||||
self._gen.write(output_dir)
|
self._gen.write(output_dir)
|
||||||
|
|
||||||
def visit_enum_type(self, name, info, ifcond, members, prefix):
|
def visit_enum_type(self, name, info, ifcond, features, members, prefix):
|
||||||
doc = self.cur_doc
|
doc = self.cur_doc
|
||||||
self._gen.add(texi_type('Enum', doc, ifcond,
|
self._gen.add(texi_type('Enum', doc, ifcond,
|
||||||
texi_members(doc, 'Values',
|
texi_members(doc, 'Values',
|
||||||
|
@ -257,7 +257,7 @@ class QAPISchemaGenDocVisitor(QAPISchemaVisitor):
|
||||||
self._gen.add(texi_type('Object', doc, ifcond,
|
self._gen.add(texi_type('Object', doc, ifcond,
|
||||||
texi_members(doc, 'Members', base, variants)))
|
texi_members(doc, 'Members', base, variants)))
|
||||||
|
|
||||||
def visit_alternate_type(self, name, info, ifcond, variants):
|
def visit_alternate_type(self, name, info, ifcond, features, variants):
|
||||||
doc = self.cur_doc
|
doc = self.cur_doc
|
||||||
self._gen.add(texi_type('Alternate', doc, ifcond,
|
self._gen.add(texi_type('Alternate', doc, ifcond,
|
||||||
texi_members(doc, 'Members')))
|
texi_members(doc, 'Members')))
|
||||||
|
@ -270,7 +270,7 @@ class QAPISchemaGenDocVisitor(QAPISchemaVisitor):
|
||||||
texi_arguments(doc,
|
texi_arguments(doc,
|
||||||
arg_type if boxed else None)))
|
arg_type if boxed else None)))
|
||||||
|
|
||||||
def visit_event(self, name, info, ifcond, arg_type, boxed):
|
def visit_event(self, name, info, ifcond, features, arg_type, boxed):
|
||||||
doc = self.cur_doc
|
doc = self.cur_doc
|
||||||
self._gen.add(texi_msg('Event', doc, ifcond,
|
self._gen.add(texi_msg('Event', doc, ifcond,
|
||||||
texi_arguments(doc,
|
texi_arguments(doc,
|
||||||
|
|
|
@ -189,7 +189,7 @@ void %(event_emit)s(%(event_enum)s event, QDict *qdict);
|
||||||
event_emit=self._event_emit_name,
|
event_emit=self._event_emit_name,
|
||||||
event_enum=self._event_enum_name))
|
event_enum=self._event_enum_name))
|
||||||
|
|
||||||
def visit_event(self, name, info, ifcond, arg_type, boxed):
|
def visit_event(self, name, info, ifcond, features, arg_type, boxed):
|
||||||
with ifcontext(ifcond, self._genh, self._genc):
|
with ifcontext(ifcond, self._genh, self._genc):
|
||||||
self._genh.add(gen_event_send_decl(name, arg_type, boxed))
|
self._genh.add(gen_event_send_decl(name, arg_type, boxed))
|
||||||
self._genc.add(gen_event_send(name, arg_type, boxed,
|
self._genc.add(gen_event_send(name, arg_type, boxed,
|
||||||
|
|
|
@ -219,7 +219,6 @@ def check_struct(expr, info):
|
||||||
|
|
||||||
check_type(members, info, "'data'", allow_dict=name)
|
check_type(members, info, "'data'", allow_dict=name)
|
||||||
check_type(expr.get('base'), info, "'base'")
|
check_type(expr.get('base'), info, "'base'")
|
||||||
check_features(expr.get('features'), info)
|
|
||||||
|
|
||||||
|
|
||||||
def check_union(expr, info):
|
def check_union(expr, info):
|
||||||
|
@ -267,7 +266,6 @@ def check_command(expr, info):
|
||||||
raise QAPISemError(info, "'boxed': true requires 'data'")
|
raise QAPISemError(info, "'boxed': true requires 'data'")
|
||||||
check_type(args, info, "'data'", allow_dict=not boxed)
|
check_type(args, info, "'data'", allow_dict=not boxed)
|
||||||
check_type(rets, info, "'returns'", allow_array=True)
|
check_type(rets, info, "'returns'", allow_array=True)
|
||||||
check_features(expr.get('features'), info)
|
|
||||||
|
|
||||||
|
|
||||||
def check_event(expr, info):
|
def check_event(expr, info):
|
||||||
|
@ -319,18 +317,18 @@ def check_exprs(exprs):
|
||||||
|
|
||||||
if meta == 'enum':
|
if meta == 'enum':
|
||||||
check_keys(expr, info, meta,
|
check_keys(expr, info, meta,
|
||||||
['enum', 'data'], ['if', 'prefix'])
|
['enum', 'data'], ['if', 'features', 'prefix'])
|
||||||
check_enum(expr, info)
|
check_enum(expr, info)
|
||||||
elif meta == 'union':
|
elif meta == 'union':
|
||||||
check_keys(expr, info, meta,
|
check_keys(expr, info, meta,
|
||||||
['union', 'data'],
|
['union', 'data'],
|
||||||
['base', 'discriminator', 'if'])
|
['base', 'discriminator', 'if', 'features'])
|
||||||
normalize_members(expr.get('base'))
|
normalize_members(expr.get('base'))
|
||||||
normalize_members(expr['data'])
|
normalize_members(expr['data'])
|
||||||
check_union(expr, info)
|
check_union(expr, info)
|
||||||
elif meta == 'alternate':
|
elif meta == 'alternate':
|
||||||
check_keys(expr, info, meta,
|
check_keys(expr, info, meta,
|
||||||
['alternate', 'data'], ['if'])
|
['alternate', 'data'], ['if', 'features'])
|
||||||
normalize_members(expr['data'])
|
normalize_members(expr['data'])
|
||||||
check_alternate(expr, info)
|
check_alternate(expr, info)
|
||||||
elif meta == 'struct':
|
elif meta == 'struct':
|
||||||
|
@ -348,13 +346,14 @@ def check_exprs(exprs):
|
||||||
check_command(expr, info)
|
check_command(expr, info)
|
||||||
elif meta == 'event':
|
elif meta == 'event':
|
||||||
check_keys(expr, info, meta,
|
check_keys(expr, info, meta,
|
||||||
['event'], ['data', 'boxed', 'if'])
|
['event'], ['data', 'boxed', 'if', 'features'])
|
||||||
normalize_members(expr.get('data'))
|
normalize_members(expr.get('data'))
|
||||||
check_event(expr, info)
|
check_event(expr, info)
|
||||||
else:
|
else:
|
||||||
assert False, 'unexpected meta type'
|
assert False, 'unexpected meta type'
|
||||||
|
|
||||||
check_if(expr, info, meta)
|
check_if(expr, info, meta)
|
||||||
|
check_features(expr.get('features'), info)
|
||||||
check_flags(expr, info)
|
check_flags(expr, info)
|
||||||
|
|
||||||
return exprs
|
return exprs
|
||||||
|
|
|
@ -144,7 +144,7 @@ const QLitObject %(c_name)s = %(c_string)s;
|
||||||
return '[' + self._use_type(typ.element_type) + ']'
|
return '[' + self._use_type(typ.element_type) + ']'
|
||||||
return self._name(typ.name)
|
return self._name(typ.name)
|
||||||
|
|
||||||
def _gen_qlit(self, name, mtype, obj, ifcond):
|
def _gen_qlit(self, name, mtype, obj, ifcond, features):
|
||||||
extra = {}
|
extra = {}
|
||||||
if mtype not in ('command', 'event', 'builtin', 'array'):
|
if mtype not in ('command', 'event', 'builtin', 'array'):
|
||||||
if not self._unmask:
|
if not self._unmask:
|
||||||
|
@ -154,6 +154,8 @@ const QLitObject %(c_name)s = %(c_string)s;
|
||||||
name = self._name(name)
|
name = self._name(name)
|
||||||
obj['name'] = name
|
obj['name'] = name
|
||||||
obj['meta-type'] = mtype
|
obj['meta-type'] = mtype
|
||||||
|
if features:
|
||||||
|
obj['features'] = [(f.name, {'if': f.ifcond}) for f in features]
|
||||||
if ifcond:
|
if ifcond:
|
||||||
extra['if'] = ifcond
|
extra['if'] = ifcond
|
||||||
if extra:
|
if extra:
|
||||||
|
@ -178,18 +180,18 @@ const QLitObject %(c_name)s = %(c_string)s;
|
||||||
{'if': variant.ifcond})
|
{'if': variant.ifcond})
|
||||||
|
|
||||||
def visit_builtin_type(self, name, info, json_type):
|
def visit_builtin_type(self, name, info, json_type):
|
||||||
self._gen_qlit(name, 'builtin', {'json-type': json_type}, [])
|
self._gen_qlit(name, 'builtin', {'json-type': json_type}, [], None)
|
||||||
|
|
||||||
def visit_enum_type(self, name, info, ifcond, members, prefix):
|
def visit_enum_type(self, name, info, ifcond, features, members, prefix):
|
||||||
self._gen_qlit(name, 'enum',
|
self._gen_qlit(name, 'enum',
|
||||||
{'values':
|
{'values':
|
||||||
[(m.name, {'if': m.ifcond}) for m in members]},
|
[(m.name, {'if': m.ifcond}) for m in members]},
|
||||||
ifcond)
|
ifcond, features)
|
||||||
|
|
||||||
def visit_array_type(self, name, info, ifcond, element_type):
|
def visit_array_type(self, name, info, ifcond, element_type):
|
||||||
element = self._use_type(element_type)
|
element = self._use_type(element_type)
|
||||||
self._gen_qlit('[' + element + ']', 'array', {'element-type': element},
|
self._gen_qlit('[' + element + ']', 'array', {'element-type': element},
|
||||||
ifcond)
|
ifcond, None)
|
||||||
|
|
||||||
def visit_object_type_flat(self, name, info, ifcond, members, variants,
|
def visit_object_type_flat(self, name, info, ifcond, members, variants,
|
||||||
features):
|
features):
|
||||||
|
@ -197,16 +199,15 @@ const QLitObject %(c_name)s = %(c_string)s;
|
||||||
if variants:
|
if variants:
|
||||||
obj.update(self._gen_variants(variants.tag_member.name,
|
obj.update(self._gen_variants(variants.tag_member.name,
|
||||||
variants.variants))
|
variants.variants))
|
||||||
if features:
|
|
||||||
obj['features'] = [(f.name, {'if': f.ifcond}) for f in features]
|
|
||||||
|
|
||||||
self._gen_qlit(name, 'object', obj, ifcond)
|
self._gen_qlit(name, 'object', obj, ifcond, features)
|
||||||
|
|
||||||
def visit_alternate_type(self, name, info, ifcond, variants):
|
def visit_alternate_type(self, name, info, ifcond, features, variants):
|
||||||
self._gen_qlit(name, 'alternate',
|
self._gen_qlit(name, 'alternate',
|
||||||
{'members': [
|
{'members': [
|
||||||
({'type': self._use_type(m.type)}, {'if': m.ifcond})
|
({'type': self._use_type(m.type)}, {'if': m.ifcond})
|
||||||
for m in variants.variants]}, ifcond)
|
for m in variants.variants]},
|
||||||
|
ifcond, features)
|
||||||
|
|
||||||
def visit_command(self, name, info, ifcond, arg_type, ret_type, gen,
|
def visit_command(self, name, info, ifcond, arg_type, ret_type, gen,
|
||||||
success_response, boxed, allow_oob, allow_preconfig,
|
success_response, boxed, allow_oob, allow_preconfig,
|
||||||
|
@ -217,16 +218,12 @@ const QLitObject %(c_name)s = %(c_string)s;
|
||||||
'ret-type': self._use_type(ret_type)}
|
'ret-type': self._use_type(ret_type)}
|
||||||
if allow_oob:
|
if allow_oob:
|
||||||
obj['allow-oob'] = allow_oob
|
obj['allow-oob'] = allow_oob
|
||||||
|
self._gen_qlit(name, 'command', obj, ifcond, features)
|
||||||
|
|
||||||
if features:
|
def visit_event(self, name, info, ifcond, features, arg_type, boxed):
|
||||||
obj['features'] = [(f.name, {'if': f.ifcond}) for f in features]
|
|
||||||
|
|
||||||
self._gen_qlit(name, 'command', obj, ifcond)
|
|
||||||
|
|
||||||
def visit_event(self, name, info, ifcond, arg_type, boxed):
|
|
||||||
arg_type = arg_type or self._schema.the_empty_object_type
|
arg_type = arg_type or self._schema.the_empty_object_type
|
||||||
self._gen_qlit(name, 'event', {'arg-type': self._use_type(arg_type)},
|
self._gen_qlit(name, 'event', {'arg-type': self._use_type(arg_type)},
|
||||||
ifcond)
|
ifcond, features)
|
||||||
|
|
||||||
|
|
||||||
def gen_introspect(schema, output_dir, prefix, opt_unmask):
|
def gen_introspect(schema, output_dir, prefix, opt_unmask):
|
||||||
|
|
|
@ -109,7 +109,7 @@ class QAPISchemaVisitor:
|
||||||
def visit_builtin_type(self, name, info, json_type):
|
def visit_builtin_type(self, name, info, json_type):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def visit_enum_type(self, name, info, ifcond, members, prefix):
|
def visit_enum_type(self, name, info, ifcond, features, members, prefix):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def visit_array_type(self, name, info, ifcond, element_type):
|
def visit_array_type(self, name, info, ifcond, element_type):
|
||||||
|
@ -123,7 +123,7 @@ class QAPISchemaVisitor:
|
||||||
features):
|
features):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def visit_alternate_type(self, name, info, ifcond, variants):
|
def visit_alternate_type(self, name, info, ifcond, features, variants):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def visit_command(self, name, info, ifcond, arg_type, ret_type, gen,
|
def visit_command(self, name, info, ifcond, arg_type, ret_type, gen,
|
||||||
|
@ -131,7 +131,7 @@ class QAPISchemaVisitor:
|
||||||
features):
|
features):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def visit_event(self, name, info, ifcond, arg_type, boxed):
|
def visit_event(self, name, info, ifcond, features, arg_type, boxed):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@ -234,8 +234,8 @@ class QAPISchemaBuiltinType(QAPISchemaType):
|
||||||
class QAPISchemaEnumType(QAPISchemaType):
|
class QAPISchemaEnumType(QAPISchemaType):
|
||||||
meta = 'enum'
|
meta = 'enum'
|
||||||
|
|
||||||
def __init__(self, name, info, doc, ifcond, members, prefix):
|
def __init__(self, name, info, doc, ifcond, features, members, prefix):
|
||||||
super().__init__(name, info, doc, ifcond)
|
super().__init__(name, info, doc, ifcond, features)
|
||||||
for m in members:
|
for m in members:
|
||||||
assert isinstance(m, QAPISchemaEnumMember)
|
assert isinstance(m, QAPISchemaEnumMember)
|
||||||
m.set_defined_in(name)
|
m.set_defined_in(name)
|
||||||
|
@ -271,15 +271,16 @@ class QAPISchemaEnumType(QAPISchemaType):
|
||||||
|
|
||||||
def visit(self, visitor):
|
def visit(self, visitor):
|
||||||
super().visit(visitor)
|
super().visit(visitor)
|
||||||
visitor.visit_enum_type(self.name, self.info, self.ifcond,
|
visitor.visit_enum_type(
|
||||||
self.members, self.prefix)
|
self.name, self.info, self.ifcond, self.features,
|
||||||
|
self.members, self.prefix)
|
||||||
|
|
||||||
|
|
||||||
class QAPISchemaArrayType(QAPISchemaType):
|
class QAPISchemaArrayType(QAPISchemaType):
|
||||||
meta = 'array'
|
meta = 'array'
|
||||||
|
|
||||||
def __init__(self, name, info, element_type):
|
def __init__(self, name, info, element_type):
|
||||||
super().__init__(name, info, None, None)
|
super().__init__(name, info, None)
|
||||||
assert isinstance(element_type, str)
|
assert isinstance(element_type, str)
|
||||||
self._element_type_name = element_type
|
self._element_type_name = element_type
|
||||||
self.element_type = None
|
self.element_type = None
|
||||||
|
@ -325,8 +326,8 @@ class QAPISchemaArrayType(QAPISchemaType):
|
||||||
|
|
||||||
|
|
||||||
class QAPISchemaObjectType(QAPISchemaType):
|
class QAPISchemaObjectType(QAPISchemaType):
|
||||||
def __init__(self, name, info, doc, ifcond,
|
def __init__(self, name, info, doc, ifcond, features,
|
||||||
base, local_members, variants, features):
|
base, local_members, variants):
|
||||||
# struct has local_members, optional base, and no variants
|
# struct has local_members, optional base, and no variants
|
||||||
# flat union has base, variants, and no local_members
|
# flat union has base, variants, and no local_members
|
||||||
# simple union has local_members, variants, and no base
|
# simple union has local_members, variants, and no base
|
||||||
|
@ -622,8 +623,8 @@ class QAPISchemaObjectTypeVariant(QAPISchemaObjectTypeMember):
|
||||||
class QAPISchemaAlternateType(QAPISchemaType):
|
class QAPISchemaAlternateType(QAPISchemaType):
|
||||||
meta = 'alternate'
|
meta = 'alternate'
|
||||||
|
|
||||||
def __init__(self, name, info, doc, ifcond, variants):
|
def __init__(self, name, info, doc, ifcond, features, variants):
|
||||||
super().__init__(name, info, doc, ifcond)
|
super().__init__(name, info, doc, ifcond, features)
|
||||||
assert isinstance(variants, QAPISchemaObjectTypeVariants)
|
assert isinstance(variants, QAPISchemaObjectTypeVariants)
|
||||||
assert variants.tag_member
|
assert variants.tag_member
|
||||||
variants.set_defined_in(name)
|
variants.set_defined_in(name)
|
||||||
|
@ -683,16 +684,16 @@ class QAPISchemaAlternateType(QAPISchemaType):
|
||||||
|
|
||||||
def visit(self, visitor):
|
def visit(self, visitor):
|
||||||
super().visit(visitor)
|
super().visit(visitor)
|
||||||
visitor.visit_alternate_type(self.name, self.info, self.ifcond,
|
visitor.visit_alternate_type(
|
||||||
self.variants)
|
self.name, self.info, self.ifcond, self.features, self.variants)
|
||||||
|
|
||||||
|
|
||||||
class QAPISchemaCommand(QAPISchemaEntity):
|
class QAPISchemaCommand(QAPISchemaEntity):
|
||||||
meta = 'command'
|
meta = 'command'
|
||||||
|
|
||||||
def __init__(self, name, info, doc, ifcond, arg_type, ret_type,
|
def __init__(self, name, info, doc, ifcond, features,
|
||||||
gen, success_response, boxed, allow_oob, allow_preconfig,
|
arg_type, ret_type,
|
||||||
features):
|
gen, success_response, boxed, allow_oob, allow_preconfig):
|
||||||
super().__init__(name, info, doc, ifcond, features)
|
super().__init__(name, info, doc, ifcond, features)
|
||||||
assert not arg_type or isinstance(arg_type, str)
|
assert not arg_type or isinstance(arg_type, str)
|
||||||
assert not ret_type or isinstance(ret_type, str)
|
assert not ret_type or isinstance(ret_type, str)
|
||||||
|
@ -755,8 +756,8 @@ class QAPISchemaCommand(QAPISchemaEntity):
|
||||||
class QAPISchemaEvent(QAPISchemaEntity):
|
class QAPISchemaEvent(QAPISchemaEntity):
|
||||||
meta = 'event'
|
meta = 'event'
|
||||||
|
|
||||||
def __init__(self, name, info, doc, ifcond, arg_type, boxed):
|
def __init__(self, name, info, doc, ifcond, features, arg_type, boxed):
|
||||||
super().__init__(name, info, doc, ifcond)
|
super().__init__(name, info, doc, ifcond, features)
|
||||||
assert not arg_type or isinstance(arg_type, str)
|
assert not arg_type or isinstance(arg_type, str)
|
||||||
self._arg_type_name = arg_type
|
self._arg_type_name = arg_type
|
||||||
self.arg_type = None
|
self.arg_type = None
|
||||||
|
@ -787,8 +788,9 @@ class QAPISchemaEvent(QAPISchemaEntity):
|
||||||
|
|
||||||
def visit(self, visitor):
|
def visit(self, visitor):
|
||||||
super().visit(visitor)
|
super().visit(visitor)
|
||||||
visitor.visit_event(self.name, self.info, self.ifcond,
|
visitor.visit_event(
|
||||||
self.arg_type, self.boxed)
|
self.name, self.info, self.ifcond, self.features,
|
||||||
|
self.arg_type, self.boxed)
|
||||||
|
|
||||||
|
|
||||||
class QAPISchema:
|
class QAPISchema:
|
||||||
|
@ -893,7 +895,7 @@ class QAPISchema:
|
||||||
('null', 'null', 'QNull' + pointer_suffix)]:
|
('null', 'null', 'QNull' + pointer_suffix)]:
|
||||||
self._def_builtin_type(*t)
|
self._def_builtin_type(*t)
|
||||||
self.the_empty_object_type = QAPISchemaObjectType(
|
self.the_empty_object_type = QAPISchemaObjectType(
|
||||||
'q_empty', None, None, None, None, [], None, [])
|
'q_empty', None, None, None, None, None, [], None)
|
||||||
self._def_entity(self.the_empty_object_type)
|
self._def_entity(self.the_empty_object_type)
|
||||||
|
|
||||||
qtypes = ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist',
|
qtypes = ['none', 'qnull', 'qnum', 'qstring', 'qdict', 'qlist',
|
||||||
|
@ -901,10 +903,11 @@ class QAPISchema:
|
||||||
qtype_values = self._make_enum_members(
|
qtype_values = self._make_enum_members(
|
||||||
[{'name': n} for n in qtypes], None)
|
[{'name': n} for n in qtypes], None)
|
||||||
|
|
||||||
self._def_entity(QAPISchemaEnumType('QType', None, None, None,
|
self._def_entity(QAPISchemaEnumType('QType', None, None, None, None,
|
||||||
qtype_values, 'QTYPE'))
|
qtype_values, 'QTYPE'))
|
||||||
|
|
||||||
def _make_features(self, features, info):
|
def _make_features(self, expr, info):
|
||||||
|
features = expr.get('features', [])
|
||||||
return [QAPISchemaFeature(f['name'], info, f.get('if'))
|
return [QAPISchemaFeature(f['name'], info, f.get('if'))
|
||||||
for f in features]
|
for f in features]
|
||||||
|
|
||||||
|
@ -916,7 +919,8 @@ class QAPISchema:
|
||||||
# See also QAPISchemaObjectTypeMember.describe()
|
# See also QAPISchemaObjectTypeMember.describe()
|
||||||
name = name + 'Kind' # reserved by check_defn_name_str()
|
name = name + 'Kind' # reserved by check_defn_name_str()
|
||||||
self._def_entity(QAPISchemaEnumType(
|
self._def_entity(QAPISchemaEnumType(
|
||||||
name, info, None, ifcond, self._make_enum_members(values, info),
|
name, info, None, ifcond, None,
|
||||||
|
self._make_enum_members(values, info),
|
||||||
None))
|
None))
|
||||||
return name
|
return name
|
||||||
|
|
||||||
|
@ -944,8 +948,8 @@ class QAPISchema:
|
||||||
# TODO kill simple unions or implement the disjunction
|
# TODO kill simple unions or implement the disjunction
|
||||||
assert (ifcond or []) == typ._ifcond # pylint: disable=protected-access
|
assert (ifcond or []) == typ._ifcond # pylint: disable=protected-access
|
||||||
else:
|
else:
|
||||||
self._def_entity(QAPISchemaObjectType(name, info, None, ifcond,
|
self._def_entity(QAPISchemaObjectType(
|
||||||
None, members, None, []))
|
name, info, None, ifcond, None, None, members, None))
|
||||||
return name
|
return name
|
||||||
|
|
||||||
def _def_enum_type(self, expr, info, doc):
|
def _def_enum_type(self, expr, info, doc):
|
||||||
|
@ -953,8 +957,9 @@ class QAPISchema:
|
||||||
data = expr['data']
|
data = expr['data']
|
||||||
prefix = expr.get('prefix')
|
prefix = expr.get('prefix')
|
||||||
ifcond = expr.get('if')
|
ifcond = expr.get('if')
|
||||||
|
features = self._make_features(expr, info)
|
||||||
self._def_entity(QAPISchemaEnumType(
|
self._def_entity(QAPISchemaEnumType(
|
||||||
name, info, doc, ifcond,
|
name, info, doc, ifcond, features,
|
||||||
self._make_enum_members(data, info), prefix))
|
self._make_enum_members(data, info), prefix))
|
||||||
|
|
||||||
def _make_member(self, name, typ, ifcond, info):
|
def _make_member(self, name, typ, ifcond, info):
|
||||||
|
@ -976,12 +981,11 @@ class QAPISchema:
|
||||||
base = expr.get('base')
|
base = expr.get('base')
|
||||||
data = expr['data']
|
data = expr['data']
|
||||||
ifcond = expr.get('if')
|
ifcond = expr.get('if')
|
||||||
features = expr.get('features', [])
|
features = self._make_features(expr, info)
|
||||||
self._def_entity(QAPISchemaObjectType(
|
self._def_entity(QAPISchemaObjectType(
|
||||||
name, info, doc, ifcond, base,
|
name, info, doc, ifcond, features, base,
|
||||||
self._make_members(data, info),
|
self._make_members(data, info),
|
||||||
None,
|
None))
|
||||||
self._make_features(features, info)))
|
|
||||||
|
|
||||||
def _make_variant(self, case, typ, ifcond, info):
|
def _make_variant(self, case, typ, ifcond, info):
|
||||||
return QAPISchemaObjectTypeVariant(case, info, typ, ifcond)
|
return QAPISchemaObjectTypeVariant(case, info, typ, ifcond)
|
||||||
|
@ -1000,6 +1004,7 @@ class QAPISchema:
|
||||||
data = expr['data']
|
data = expr['data']
|
||||||
base = expr.get('base')
|
base = expr.get('base')
|
||||||
ifcond = expr.get('if')
|
ifcond = expr.get('if')
|
||||||
|
features = self._make_features(expr, info)
|
||||||
tag_name = expr.get('discriminator')
|
tag_name = expr.get('discriminator')
|
||||||
tag_member = None
|
tag_member = None
|
||||||
if isinstance(base, dict):
|
if isinstance(base, dict):
|
||||||
|
@ -1020,21 +1025,22 @@ class QAPISchema:
|
||||||
tag_member = QAPISchemaObjectTypeMember('type', info, typ, False)
|
tag_member = QAPISchemaObjectTypeMember('type', info, typ, False)
|
||||||
members = [tag_member]
|
members = [tag_member]
|
||||||
self._def_entity(
|
self._def_entity(
|
||||||
QAPISchemaObjectType(name, info, doc, ifcond, base, members,
|
QAPISchemaObjectType(name, info, doc, ifcond, features,
|
||||||
|
base, members,
|
||||||
QAPISchemaObjectTypeVariants(
|
QAPISchemaObjectTypeVariants(
|
||||||
tag_name, info, tag_member, variants),
|
tag_name, info, tag_member, variants)))
|
||||||
[]))
|
|
||||||
|
|
||||||
def _def_alternate_type(self, expr, info, doc):
|
def _def_alternate_type(self, expr, info, doc):
|
||||||
name = expr['alternate']
|
name = expr['alternate']
|
||||||
data = expr['data']
|
data = expr['data']
|
||||||
ifcond = expr.get('if')
|
ifcond = expr.get('if')
|
||||||
|
features = self._make_features(expr, info)
|
||||||
variants = [self._make_variant(key, value['type'], value.get('if'),
|
variants = [self._make_variant(key, value['type'], value.get('if'),
|
||||||
info)
|
info)
|
||||||
for (key, value) in data.items()]
|
for (key, value) in data.items()]
|
||||||
tag_member = QAPISchemaObjectTypeMember('type', info, 'QType', False)
|
tag_member = QAPISchemaObjectTypeMember('type', info, 'QType', False)
|
||||||
self._def_entity(
|
self._def_entity(
|
||||||
QAPISchemaAlternateType(name, info, doc, ifcond,
|
QAPISchemaAlternateType(name, info, doc, ifcond, features,
|
||||||
QAPISchemaObjectTypeVariants(
|
QAPISchemaObjectTypeVariants(
|
||||||
None, info, tag_member, variants)))
|
None, info, tag_member, variants)))
|
||||||
|
|
||||||
|
@ -1048,27 +1054,31 @@ class QAPISchema:
|
||||||
allow_oob = expr.get('allow-oob', False)
|
allow_oob = expr.get('allow-oob', False)
|
||||||
allow_preconfig = expr.get('allow-preconfig', False)
|
allow_preconfig = expr.get('allow-preconfig', False)
|
||||||
ifcond = expr.get('if')
|
ifcond = expr.get('if')
|
||||||
features = expr.get('features', [])
|
features = self._make_features(expr, info)
|
||||||
if isinstance(data, OrderedDict):
|
if isinstance(data, OrderedDict):
|
||||||
data = self._make_implicit_object_type(
|
data = self._make_implicit_object_type(
|
||||||
name, info, ifcond, 'arg', self._make_members(data, info))
|
name, info, ifcond,
|
||||||
|
'arg', self._make_members(data, info))
|
||||||
if isinstance(rets, list):
|
if isinstance(rets, list):
|
||||||
assert len(rets) == 1
|
assert len(rets) == 1
|
||||||
rets = self._make_array_type(rets[0], info)
|
rets = self._make_array_type(rets[0], info)
|
||||||
self._def_entity(QAPISchemaCommand(name, info, doc, ifcond, data, rets,
|
self._def_entity(QAPISchemaCommand(name, info, doc, ifcond, features,
|
||||||
|
data, rets,
|
||||||
gen, success_response,
|
gen, success_response,
|
||||||
boxed, allow_oob, allow_preconfig,
|
boxed, allow_oob, allow_preconfig))
|
||||||
self._make_features(features, info)))
|
|
||||||
|
|
||||||
def _def_event(self, expr, info, doc):
|
def _def_event(self, expr, info, doc):
|
||||||
name = expr['event']
|
name = expr['event']
|
||||||
data = expr.get('data')
|
data = expr.get('data')
|
||||||
boxed = expr.get('boxed', False)
|
boxed = expr.get('boxed', False)
|
||||||
ifcond = expr.get('if')
|
ifcond = expr.get('if')
|
||||||
|
features = self._make_features(expr, info)
|
||||||
if isinstance(data, OrderedDict):
|
if isinstance(data, OrderedDict):
|
||||||
data = self._make_implicit_object_type(
|
data = self._make_implicit_object_type(
|
||||||
name, info, ifcond, 'arg', self._make_members(data, info))
|
name, info, ifcond,
|
||||||
self._def_entity(QAPISchemaEvent(name, info, doc, ifcond, data, boxed))
|
'arg', self._make_members(data, info))
|
||||||
|
self._def_entity(QAPISchemaEvent(name, info, doc, ifcond, features,
|
||||||
|
data, boxed))
|
||||||
|
|
||||||
def _def_exprs(self, exprs):
|
def _def_exprs(self, exprs):
|
||||||
for expr_elem in exprs:
|
for expr_elem in exprs:
|
||||||
|
|
|
@ -278,7 +278,7 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
|
||||||
self._genh.add(gen_type_cleanup_decl(name))
|
self._genh.add(gen_type_cleanup_decl(name))
|
||||||
self._genc.add(gen_type_cleanup(name))
|
self._genc.add(gen_type_cleanup(name))
|
||||||
|
|
||||||
def visit_enum_type(self, name, info, ifcond, members, prefix):
|
def visit_enum_type(self, name, info, ifcond, features, members, prefix):
|
||||||
with ifcontext(ifcond, self._genh, self._genc):
|
with ifcontext(ifcond, self._genh, self._genc):
|
||||||
self._genh.preamble_add(gen_enum(name, members, prefix))
|
self._genh.preamble_add(gen_enum(name, members, prefix))
|
||||||
self._genc.add(gen_enum_lookup(name, members, prefix))
|
self._genc.add(gen_enum_lookup(name, members, prefix))
|
||||||
|
@ -306,7 +306,7 @@ class QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor):
|
||||||
# implicit types won't be directly allocated/freed
|
# implicit types won't be directly allocated/freed
|
||||||
self._gen_type_cleanup(name)
|
self._gen_type_cleanup(name)
|
||||||
|
|
||||||
def visit_alternate_type(self, name, info, ifcond, variants):
|
def visit_alternate_type(self, name, info, ifcond, features, variants):
|
||||||
with ifcontext(ifcond, self._genh):
|
with ifcontext(ifcond, self._genh):
|
||||||
self._genh.preamble_add(gen_fwd_object_or_array(name))
|
self._genh.preamble_add(gen_fwd_object_or_array(name))
|
||||||
self._genh.add(gen_object(name, ifcond, None,
|
self._genh.add(gen_object(name, ifcond, None,
|
||||||
|
|
|
@ -316,7 +316,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor):
|
||||||
''',
|
''',
|
||||||
types=types))
|
types=types))
|
||||||
|
|
||||||
def visit_enum_type(self, name, info, ifcond, members, prefix):
|
def visit_enum_type(self, name, info, ifcond, features, members, prefix):
|
||||||
with ifcontext(ifcond, self._genh, self._genc):
|
with ifcontext(ifcond, self._genh, self._genc):
|
||||||
self._genh.add(gen_visit_decl(name, scalar=True))
|
self._genh.add(gen_visit_decl(name, scalar=True))
|
||||||
self._genc.add(gen_visit_enum(name))
|
self._genc.add(gen_visit_enum(name))
|
||||||
|
@ -342,7 +342,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor):
|
||||||
self._genh.add(gen_visit_decl(name))
|
self._genh.add(gen_visit_decl(name))
|
||||||
self._genc.add(gen_visit_object(name, base, members, variants))
|
self._genc.add(gen_visit_object(name, base, members, variants))
|
||||||
|
|
||||||
def visit_alternate_type(self, name, info, ifcond, variants):
|
def visit_alternate_type(self, name, info, ifcond, features, variants):
|
||||||
with ifcontext(ifcond, self._genh, self._genc):
|
with ifcontext(ifcond, self._genh, self._genc):
|
||||||
self._genh.add(gen_visit_decl(name))
|
self._genh.add(gen_visit_decl(name))
|
||||||
self._genc.add(gen_visit_alternate(name, variants))
|
self._genc.add(gen_visit_alternate(name, variants))
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
alternate-base.json: In alternate 'Alt':
|
alternate-base.json: In alternate 'Alt':
|
||||||
alternate-base.json:4: alternate has unknown key 'base'
|
alternate-base.json:4: alternate has unknown key 'base'
|
||||||
Valid keys are 'alternate', 'data', 'if'.
|
Valid keys are 'alternate', 'data', 'features', 'if'.
|
||||||
|
|
|
@ -53,10 +53,14 @@
|
||||||
# @Enum:
|
# @Enum:
|
||||||
# @one: The _one_ {and only}
|
# @one: The _one_ {and only}
|
||||||
#
|
#
|
||||||
|
# Features:
|
||||||
|
# @enum-feat: Also _one_ {and only}
|
||||||
|
#
|
||||||
# @two is undocumented
|
# @two is undocumented
|
||||||
##
|
##
|
||||||
{ 'enum': 'Enum', 'data':
|
{ 'enum': 'Enum', 'data':
|
||||||
[ { 'name': 'one', 'if': 'defined(IFONE)' }, 'two' ],
|
[ { 'name': 'one', 'if': 'defined(IFONE)' }, 'two' ],
|
||||||
|
'features': [ 'enum-feat' ],
|
||||||
'if': 'defined(IFCOND)' }
|
'if': 'defined(IFCOND)' }
|
||||||
|
|
||||||
##
|
##
|
||||||
|
@ -86,24 +90,34 @@
|
||||||
|
|
||||||
##
|
##
|
||||||
# @Object:
|
# @Object:
|
||||||
|
# Features:
|
||||||
|
# @union-feat1: a feature
|
||||||
##
|
##
|
||||||
{ 'union': 'Object',
|
{ 'union': 'Object',
|
||||||
|
'features': [ 'union-feat1' ],
|
||||||
'base': 'Base',
|
'base': 'Base',
|
||||||
'discriminator': 'base1',
|
'discriminator': 'base1',
|
||||||
'data': { 'one': 'Variant1', 'two': { 'type': 'Variant2', 'if': 'IFTWO' } } }
|
'data': { 'one': 'Variant1', 'two': { 'type': 'Variant2', 'if': 'IFTWO' } } }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @SugaredUnion:
|
# @SugaredUnion:
|
||||||
|
# Features:
|
||||||
|
# @union-feat2: a feature
|
||||||
##
|
##
|
||||||
{ 'union': 'SugaredUnion',
|
{ 'union': 'SugaredUnion',
|
||||||
|
'features': [ 'union-feat2' ],
|
||||||
'data': { 'one': 'Variant1', 'two': { 'type': 'Variant2', 'if': 'IFTWO' } } }
|
'data': { 'one': 'Variant1', 'two': { 'type': 'Variant2', 'if': 'IFTWO' } } }
|
||||||
|
|
||||||
##
|
##
|
||||||
# @Alternate:
|
# @Alternate:
|
||||||
# @i: an integer
|
# @i: an integer
|
||||||
# @b is undocumented
|
# @b is undocumented
|
||||||
|
#
|
||||||
|
# Features:
|
||||||
|
# @alt-feat: a feature
|
||||||
##
|
##
|
||||||
{ 'alternate': 'Alternate',
|
{ 'alternate': 'Alternate',
|
||||||
|
'features': [ 'alt-feat' ],
|
||||||
'data': { 'i': 'int', 'b': 'bool' } }
|
'data': { 'i': 'int', 'b': 'bool' } }
|
||||||
|
|
||||||
##
|
##
|
||||||
|
@ -160,6 +174,9 @@
|
||||||
|
|
||||||
##
|
##
|
||||||
# @EVT-BOXED:
|
# @EVT-BOXED:
|
||||||
|
# Features:
|
||||||
|
# @feat3: a feature
|
||||||
##
|
##
|
||||||
{ 'event': 'EVT-BOXED', 'boxed': true,
|
{ 'event': 'EVT-BOXED', 'boxed': true,
|
||||||
|
'features': [ 'feat3' ],
|
||||||
'data': 'Object' }
|
'data': 'Object' }
|
||||||
|
|
|
@ -15,6 +15,7 @@ enum Enum
|
||||||
if ['defined(IFONE)']
|
if ['defined(IFONE)']
|
||||||
member two
|
member two
|
||||||
if ['defined(IFCOND)']
|
if ['defined(IFCOND)']
|
||||||
|
feature enum-feat
|
||||||
object Base
|
object Base
|
||||||
member base1: Enum optional=False
|
member base1: Enum optional=False
|
||||||
object Variant1
|
object Variant1
|
||||||
|
@ -28,6 +29,7 @@ object Object
|
||||||
case one: Variant1
|
case one: Variant1
|
||||||
case two: Variant2
|
case two: Variant2
|
||||||
if ['IFTWO']
|
if ['IFTWO']
|
||||||
|
feature union-feat1
|
||||||
object q_obj_Variant1-wrapper
|
object q_obj_Variant1-wrapper
|
||||||
member data: Variant1 optional=False
|
member data: Variant1 optional=False
|
||||||
object q_obj_Variant2-wrapper
|
object q_obj_Variant2-wrapper
|
||||||
|
@ -42,10 +44,12 @@ object SugaredUnion
|
||||||
case one: q_obj_Variant1-wrapper
|
case one: q_obj_Variant1-wrapper
|
||||||
case two: q_obj_Variant2-wrapper
|
case two: q_obj_Variant2-wrapper
|
||||||
if ['IFTWO']
|
if ['IFTWO']
|
||||||
|
feature union-feat2
|
||||||
alternate Alternate
|
alternate Alternate
|
||||||
tag type
|
tag type
|
||||||
case i: int
|
case i: int
|
||||||
case b: bool
|
case b: bool
|
||||||
|
feature alt-feat
|
||||||
object q_obj_cmd-arg
|
object q_obj_cmd-arg
|
||||||
member arg1: int optional=False
|
member arg1: int optional=False
|
||||||
member arg2: str optional=True
|
member arg2: str optional=True
|
||||||
|
@ -60,6 +64,7 @@ command cmd-boxed Object -> None
|
||||||
feature cmd-feat2
|
feature cmd-feat2
|
||||||
event EVT-BOXED Object
|
event EVT-BOXED Object
|
||||||
boxed=True
|
boxed=True
|
||||||
|
feature feat3
|
||||||
doc freeform
|
doc freeform
|
||||||
body=
|
body=
|
||||||
= Section
|
= Section
|
||||||
|
@ -112,6 +117,8 @@ doc symbol=Enum
|
||||||
The _one_ {and only}
|
The _one_ {and only}
|
||||||
arg=two
|
arg=two
|
||||||
|
|
||||||
|
feature=enum-feat
|
||||||
|
Also _one_ {and only}
|
||||||
section=None
|
section=None
|
||||||
@two is undocumented
|
@two is undocumented
|
||||||
doc symbol=Base
|
doc symbol=Base
|
||||||
|
@ -134,11 +141,15 @@ doc symbol=Variant2
|
||||||
doc symbol=Object
|
doc symbol=Object
|
||||||
body=
|
body=
|
||||||
|
|
||||||
|
feature=union-feat1
|
||||||
|
a feature
|
||||||
doc symbol=SugaredUnion
|
doc symbol=SugaredUnion
|
||||||
body=
|
body=
|
||||||
|
|
||||||
arg=type
|
arg=type
|
||||||
|
|
||||||
|
feature=union-feat2
|
||||||
|
a feature
|
||||||
doc symbol=Alternate
|
doc symbol=Alternate
|
||||||
body=
|
body=
|
||||||
|
|
||||||
|
@ -147,6 +158,8 @@ an integer
|
||||||
@b is undocumented
|
@b is undocumented
|
||||||
arg=b
|
arg=b
|
||||||
|
|
||||||
|
feature=alt-feat
|
||||||
|
a feature
|
||||||
doc freeform
|
doc freeform
|
||||||
body=
|
body=
|
||||||
== Another subsection
|
== Another subsection
|
||||||
|
@ -197,3 +210,5 @@ another feature
|
||||||
doc symbol=EVT-BOXED
|
doc symbol=EVT-BOXED
|
||||||
body=
|
body=
|
||||||
|
|
||||||
|
feature=feat3
|
||||||
|
a feature
|
||||||
|
|
|
@ -88,6 +88,12 @@ The @emph{one} @{and only@}
|
||||||
@item @code{two}
|
@item @code{two}
|
||||||
Not documented
|
Not documented
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
|
@b{Features:}
|
||||||
|
@table @asis
|
||||||
|
@item @code{enum-feat}
|
||||||
|
Also @emph{one} @{and only@}
|
||||||
|
@end table
|
||||||
@code{two} is undocumented
|
@code{two} is undocumented
|
||||||
|
|
||||||
@b{If:} @code{defined(IFCOND)}
|
@b{If:} @code{defined(IFCOND)}
|
||||||
|
@ -151,6 +157,12 @@ a feature
|
||||||
@item The members of @code{Variant2} when @code{base1} is @t{"two"} (@b{If:} @code{IFTWO})
|
@item The members of @code{Variant2} when @code{base1} is @t{"two"} (@b{If:} @code{IFTWO})
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
|
@b{Features:}
|
||||||
|
@table @asis
|
||||||
|
@item @code{union-feat1}
|
||||||
|
a feature
|
||||||
|
@end table
|
||||||
|
|
||||||
@end deftp
|
@end deftp
|
||||||
|
|
||||||
|
|
||||||
|
@ -167,6 +179,12 @@ One of @t{"one"}, @t{"two"}
|
||||||
@item @code{data: Variant2} when @code{type} is @t{"two"} (@b{If:} @code{IFTWO})
|
@item @code{data: Variant2} when @code{type} is @t{"two"} (@b{If:} @code{IFTWO})
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
|
@b{Features:}
|
||||||
|
@table @asis
|
||||||
|
@item @code{union-feat2}
|
||||||
|
a feature
|
||||||
|
@end table
|
||||||
|
|
||||||
@end deftp
|
@end deftp
|
||||||
|
|
||||||
|
|
||||||
|
@ -184,6 +202,12 @@ an integer
|
||||||
Not documented
|
Not documented
|
||||||
@end table
|
@end table
|
||||||
|
|
||||||
|
@b{Features:}
|
||||||
|
@table @asis
|
||||||
|
@item @code{alt-feat}
|
||||||
|
a feature
|
||||||
|
@end table
|
||||||
|
|
||||||
@end deftp
|
@end deftp
|
||||||
|
|
||||||
|
|
||||||
|
@ -283,5 +307,11 @@ another feature
|
||||||
|
|
||||||
@b{Arguments:} the members of @code{Object}
|
@b{Arguments:} the members of @code{Object}
|
||||||
|
|
||||||
|
@b{Features:}
|
||||||
|
@table @asis
|
||||||
|
@item @code{feat3}
|
||||||
|
a feature
|
||||||
|
@end table
|
||||||
|
|
||||||
@end deftypefn
|
@end deftypefn
|
||||||
|
|
||||||
|
|
|
@ -252,7 +252,7 @@
|
||||||
'bar': { 'type': ['TestIfEnum'], 'if': 'defined(TEST_IF_EVT_BAR)' } },
|
'bar': { 'type': ['TestIfEnum'], 'if': 'defined(TEST_IF_EVT_BAR)' } },
|
||||||
'if': 'defined(TEST_IF_EVT) && defined(TEST_IF_STRUCT)' }
|
'if': 'defined(TEST_IF_EVT) && defined(TEST_IF_STRUCT)' }
|
||||||
|
|
||||||
# test 'features' for structs
|
# test 'features'
|
||||||
|
|
||||||
{ 'struct': 'FeatureStruct0',
|
{ 'struct': 'FeatureStruct0',
|
||||||
'data': { 'foo': 'int' },
|
'data': { 'foo': 'int' },
|
||||||
|
@ -281,7 +281,22 @@
|
||||||
'data': { 'foo': 'int' },
|
'data': { 'foo': 'int' },
|
||||||
'features': [ { 'name': 'feature1', 'if': [ 'defined(TEST_IF_COND_1)',
|
'features': [ { 'name': 'feature1', 'if': [ 'defined(TEST_IF_COND_1)',
|
||||||
'defined(TEST_IF_COND_2)'] } ] }
|
'defined(TEST_IF_COND_2)'] } ] }
|
||||||
{ 'command': 'test-features',
|
|
||||||
|
{ 'enum': 'FeatureEnum1',
|
||||||
|
'data': [ 'eins', 'zwei', 'drei' ],
|
||||||
|
'features': [ 'feature1' ] }
|
||||||
|
|
||||||
|
{ 'union': 'FeatureUnion1',
|
||||||
|
'base': { 'tag': 'FeatureEnum1' },
|
||||||
|
'discriminator': 'tag',
|
||||||
|
'data': { 'eins': 'FeatureStruct1' },
|
||||||
|
'features': [ 'feature1' ] }
|
||||||
|
|
||||||
|
{ 'alternate': 'FeatureAlternate1',
|
||||||
|
'data': { 'eins': 'FeatureStruct1' },
|
||||||
|
'features': [ 'feature1' ] }
|
||||||
|
|
||||||
|
{ 'command': 'test-features0',
|
||||||
'data': { 'fs0': 'FeatureStruct0',
|
'data': { 'fs0': 'FeatureStruct0',
|
||||||
'fs1': 'FeatureStruct1',
|
'fs1': 'FeatureStruct1',
|
||||||
'fs2': 'FeatureStruct2',
|
'fs2': 'FeatureStruct2',
|
||||||
|
@ -289,12 +304,9 @@
|
||||||
'fs4': 'FeatureStruct4',
|
'fs4': 'FeatureStruct4',
|
||||||
'cfs1': 'CondFeatureStruct1',
|
'cfs1': 'CondFeatureStruct1',
|
||||||
'cfs2': 'CondFeatureStruct2',
|
'cfs2': 'CondFeatureStruct2',
|
||||||
'cfs3': 'CondFeatureStruct3' } }
|
'cfs3': 'CondFeatureStruct3' },
|
||||||
|
|
||||||
# test 'features' for command
|
|
||||||
|
|
||||||
{ 'command': 'test-command-features0',
|
|
||||||
'features': [] }
|
'features': [] }
|
||||||
|
|
||||||
{ 'command': 'test-command-features1',
|
{ 'command': 'test-command-features1',
|
||||||
'features': [ 'feature1' ] }
|
'features': [ 'feature1' ] }
|
||||||
{ 'command': 'test-command-features3',
|
{ 'command': 'test-command-features3',
|
||||||
|
@ -308,3 +320,6 @@
|
||||||
{ 'command': 'test-command-cond-features3',
|
{ 'command': 'test-command-cond-features3',
|
||||||
'features': [ { 'name': 'feature1', 'if': [ 'defined(TEST_IF_COND_1)',
|
'features': [ { 'name': 'feature1', 'if': [ 'defined(TEST_IF_COND_1)',
|
||||||
'defined(TEST_IF_COND_2)'] } ] }
|
'defined(TEST_IF_COND_2)'] } ] }
|
||||||
|
|
||||||
|
{ 'event': 'TEST-EVENT-FEATURES1',
|
||||||
|
'features': [ 'feature1' ] }
|
||||||
|
|
|
@ -387,7 +387,25 @@ object CondFeatureStruct3
|
||||||
member foo: int optional=False
|
member foo: int optional=False
|
||||||
feature feature1
|
feature feature1
|
||||||
if ['defined(TEST_IF_COND_1)', 'defined(TEST_IF_COND_2)']
|
if ['defined(TEST_IF_COND_1)', 'defined(TEST_IF_COND_2)']
|
||||||
object q_obj_test-features-arg
|
enum FeatureEnum1
|
||||||
|
member eins
|
||||||
|
member zwei
|
||||||
|
member drei
|
||||||
|
feature feature1
|
||||||
|
object q_obj_FeatureUnion1-base
|
||||||
|
member tag: FeatureEnum1 optional=False
|
||||||
|
object FeatureUnion1
|
||||||
|
base q_obj_FeatureUnion1-base
|
||||||
|
tag tag
|
||||||
|
case eins: FeatureStruct1
|
||||||
|
case zwei: q_empty
|
||||||
|
case drei: q_empty
|
||||||
|
feature feature1
|
||||||
|
alternate FeatureAlternate1
|
||||||
|
tag type
|
||||||
|
case eins: FeatureStruct1
|
||||||
|
feature feature1
|
||||||
|
object q_obj_test-features0-arg
|
||||||
member fs0: FeatureStruct0 optional=False
|
member fs0: FeatureStruct0 optional=False
|
||||||
member fs1: FeatureStruct1 optional=False
|
member fs1: FeatureStruct1 optional=False
|
||||||
member fs2: FeatureStruct2 optional=False
|
member fs2: FeatureStruct2 optional=False
|
||||||
|
@ -396,9 +414,7 @@ object q_obj_test-features-arg
|
||||||
member cfs1: CondFeatureStruct1 optional=False
|
member cfs1: CondFeatureStruct1 optional=False
|
||||||
member cfs2: CondFeatureStruct2 optional=False
|
member cfs2: CondFeatureStruct2 optional=False
|
||||||
member cfs3: CondFeatureStruct3 optional=False
|
member cfs3: CondFeatureStruct3 optional=False
|
||||||
command test-features q_obj_test-features-arg -> None
|
command test-features0 q_obj_test-features0-arg -> None
|
||||||
gen=True success_response=True boxed=False oob=False preconfig=False
|
|
||||||
command test-command-features0 None -> None
|
|
||||||
gen=True success_response=True boxed=False oob=False preconfig=False
|
gen=True success_response=True boxed=False oob=False preconfig=False
|
||||||
command test-command-features1 None -> None
|
command test-command-features1 None -> None
|
||||||
gen=True success_response=True boxed=False oob=False preconfig=False
|
gen=True success_response=True boxed=False oob=False preconfig=False
|
||||||
|
@ -421,6 +437,9 @@ command test-command-cond-features3 None -> None
|
||||||
gen=True success_response=True boxed=False oob=False preconfig=False
|
gen=True success_response=True boxed=False oob=False preconfig=False
|
||||||
feature feature1
|
feature feature1
|
||||||
if ['defined(TEST_IF_COND_1)', 'defined(TEST_IF_COND_2)']
|
if ['defined(TEST_IF_COND_1)', 'defined(TEST_IF_COND_2)']
|
||||||
|
event TEST-EVENT-FEATURES1 None
|
||||||
|
boxed=False
|
||||||
|
feature feature1
|
||||||
module include/sub-module.json
|
module include/sub-module.json
|
||||||
include sub-sub-module.json
|
include sub-sub-module.json
|
||||||
object SecondArrayRef
|
object SecondArrayRef
|
||||||
|
|
|
@ -30,7 +30,7 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
|
||||||
def visit_include(self, name, info):
|
def visit_include(self, name, info):
|
||||||
print('include %s' % name)
|
print('include %s' % name)
|
||||||
|
|
||||||
def visit_enum_type(self, name, info, ifcond, members, prefix):
|
def visit_enum_type(self, name, info, ifcond, features, members, prefix):
|
||||||
print('enum %s' % name)
|
print('enum %s' % name)
|
||||||
if prefix:
|
if prefix:
|
||||||
print(' prefix %s' % prefix)
|
print(' prefix %s' % prefix)
|
||||||
|
@ -38,6 +38,7 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
|
||||||
print(' member %s' % m.name)
|
print(' member %s' % m.name)
|
||||||
self._print_if(m.ifcond, indent=8)
|
self._print_if(m.ifcond, indent=8)
|
||||||
self._print_if(ifcond)
|
self._print_if(ifcond)
|
||||||
|
self._print_features(features)
|
||||||
|
|
||||||
def visit_array_type(self, name, info, ifcond, element_type):
|
def visit_array_type(self, name, info, ifcond, element_type):
|
||||||
if not info:
|
if not info:
|
||||||
|
@ -58,10 +59,11 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
|
||||||
self._print_if(ifcond)
|
self._print_if(ifcond)
|
||||||
self._print_features(features)
|
self._print_features(features)
|
||||||
|
|
||||||
def visit_alternate_type(self, name, info, ifcond, variants):
|
def visit_alternate_type(self, name, info, ifcond, features, variants):
|
||||||
print('alternate %s' % name)
|
print('alternate %s' % name)
|
||||||
self._print_variants(variants)
|
self._print_variants(variants)
|
||||||
self._print_if(ifcond)
|
self._print_if(ifcond)
|
||||||
|
self._print_features(features)
|
||||||
|
|
||||||
def visit_command(self, name, info, ifcond, arg_type, ret_type, gen,
|
def visit_command(self, name, info, ifcond, arg_type, ret_type, gen,
|
||||||
success_response, boxed, allow_oob, allow_preconfig,
|
success_response, boxed, allow_oob, allow_preconfig,
|
||||||
|
@ -74,10 +76,11 @@ class QAPISchemaTestVisitor(QAPISchemaVisitor):
|
||||||
self._print_if(ifcond)
|
self._print_if(ifcond)
|
||||||
self._print_features(features)
|
self._print_features(features)
|
||||||
|
|
||||||
def visit_event(self, name, info, ifcond, arg_type, boxed):
|
def visit_event(self, name, info, ifcond, features, arg_type, boxed):
|
||||||
print('event %s %s' % (name, arg_type and arg_type.name))
|
print('event %s %s' % (name, arg_type and arg_type.name))
|
||||||
print(' boxed=%s' % boxed)
|
print(' boxed=%s' % boxed)
|
||||||
self._print_if(ifcond)
|
self._print_if(ifcond)
|
||||||
|
self._print_features(features)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _print_variants(variants):
|
def _print_variants(variants):
|
||||||
|
|
|
@ -45,7 +45,7 @@ void qmp_user_def_cmd1(UserDefOne * ud1, Error **errp)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void qmp_test_features(FeatureStruct0 *fs0, FeatureStruct1 *fs1,
|
void qmp_test_features0(FeatureStruct0 *fs0, FeatureStruct1 *fs1,
|
||||||
FeatureStruct2 *fs2, FeatureStruct3 *fs3,
|
FeatureStruct2 *fs2, FeatureStruct3 *fs3,
|
||||||
FeatureStruct4 *fs4, CondFeatureStruct1 *cfs1,
|
FeatureStruct4 *fs4, CondFeatureStruct1 *cfs1,
|
||||||
CondFeatureStruct2 *cfs2, CondFeatureStruct3 *cfs3,
|
CondFeatureStruct2 *cfs2, CondFeatureStruct3 *cfs3,
|
||||||
|
@ -53,10 +53,6 @@ void qmp_test_features(FeatureStruct0 *fs0, FeatureStruct1 *fs1,
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void qmp_test_command_features0(Error **errp)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void qmp_test_command_features1(Error **errp)
|
void qmp_test_command_features1(Error **errp)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue