diff options
Diffstat (limited to 'scripts')
-rw-r--r-- | scripts/qapi/commands.py | 18 | ||||
-rw-r--r-- | scripts/qapi/common.py | 15 | ||||
-rw-r--r-- | scripts/qapi/doc.py | 9 | ||||
-rw-r--r-- | scripts/qapi/introspect.py | 83 |
4 files changed, 75 insertions, 50 deletions
diff --git a/scripts/qapi/commands.py b/scripts/qapi/commands.py index 21a7e0dbe6..0c5da3a54d 100644 --- a/scripts/qapi/commands.py +++ b/scripts/qapi/commands.py @@ -193,10 +193,18 @@ out: return ret -def gen_register_command(name, success_response): - options = 'QCO_NO_OPTIONS' +def gen_register_command(name, success_response, allow_oob): + options = [] + if not success_response: - options = 'QCO_NO_SUCCESS_RESP' + options += ['QCO_NO_SUCCESS_RESP'] + if allow_oob: + options += ['QCO_ALLOW_OOB'] + + if not options: + options = ['QCO_NO_OPTIONS'] + + options = " | ".join(options) ret = mcgen(''' qmp_register_command(cmds, "%(name)s", @@ -268,7 +276,7 @@ void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds); genc.add(gen_registry(self._regy, self._prefix)) def visit_command(self, name, info, arg_type, ret_type, - gen, success_response, boxed): + gen, success_response, boxed, allow_oob): if not gen: return self._genh.add(gen_command_decl(name, arg_type, boxed, ret_type)) @@ -277,7 +285,7 @@ void %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds); self._genc.add(gen_marshal_output(ret_type)) self._genh.add(gen_marshal_decl(name)) self._genc.add(gen_marshal(name, arg_type, boxed, ret_type)) - self._regy += gen_register_command(name, success_response) + self._regy += gen_register_command(name, success_response, allow_oob) def gen_commands(schema, output_dir, prefix): diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py index 97e9060b67..2c05e3c284 100644 --- a/scripts/qapi/common.py +++ b/scripts/qapi/common.py @@ -921,7 +921,8 @@ def check_exprs(exprs): elif 'command' in expr: meta = 'command' check_keys(expr_elem, 'command', [], - ['data', 'returns', 'gen', 'success-response', 'boxed']) + ['data', 'returns', 'gen', 'success-response', + 'boxed', 'allow-oob']) elif 'event' in expr: meta = 'event' check_keys(expr_elem, 'event', [], ['data', 'boxed']) @@ -1044,7 +1045,7 @@ class QAPISchemaVisitor(object): pass def visit_command(self, name, info, arg_type, ret_type, - gen, success_response, boxed): + gen, success_response, boxed, allow_oob): pass def visit_event(self, name, info, arg_type, boxed): @@ -1421,7 +1422,7 @@ class QAPISchemaAlternateType(QAPISchemaType): class QAPISchemaCommand(QAPISchemaEntity): def __init__(self, name, info, doc, arg_type, ret_type, - gen, success_response, boxed): + gen, success_response, boxed, allow_oob): QAPISchemaEntity.__init__(self, name, info, doc) assert not arg_type or isinstance(arg_type, str) assert not ret_type or isinstance(ret_type, str) @@ -1432,6 +1433,7 @@ class QAPISchemaCommand(QAPISchemaEntity): self.gen = gen self.success_response = success_response self.boxed = boxed + self.allow_oob = allow_oob def check(self, schema): if self._arg_type_name: @@ -1455,7 +1457,8 @@ class QAPISchemaCommand(QAPISchemaEntity): def visit(self, visitor): visitor.visit_command(self.name, self.info, self.arg_type, self.ret_type, - self.gen, self.success_response, self.boxed) + self.gen, self.success_response, + self.boxed, self.allow_oob) class QAPISchemaEvent(QAPISchemaEntity): @@ -1674,6 +1677,7 @@ class QAPISchema(object): gen = expr.get('gen', True) success_response = expr.get('success-response', True) boxed = expr.get('boxed', False) + allow_oob = expr.get('allow-oob', False) if isinstance(data, OrderedDict): data = self._make_implicit_object_type( name, info, doc, 'arg', self._make_members(data, info)) @@ -1681,7 +1685,8 @@ class QAPISchema(object): assert len(rets) == 1 rets = self._make_array_type(rets[0], info) self._def_entity(QAPISchemaCommand(name, info, doc, data, rets, - gen, success_response, boxed)) + gen, success_response, + boxed, allow_oob)) def _def_event(self, expr, info, doc): name = expr['event'] diff --git a/scripts/qapi/doc.py b/scripts/qapi/doc.py index 0ea68bf813..9b312b2c51 100644 --- a/scripts/qapi/doc.py +++ b/scripts/qapi/doc.py @@ -134,10 +134,9 @@ def texi_enum_value(value): def texi_member(member, suffix=''): """Format a table of members item for an object type member""" typ = member.type.doc_type() - return '@item @code{%s%s%s}%s%s\n' % ( - member.name, - ': ' if typ else '', - typ if typ else '', + membertype = ': ' + typ if typ else '' + return '@item @code{%s%s}%s%s\n' % ( + member.name, membertype, ' (optional)' if member.optional else '', suffix) @@ -228,7 +227,7 @@ class QAPISchemaGenDocVisitor(qapi.common.QAPISchemaVisitor): body=texi_entity(doc, 'Members'))) def visit_command(self, name, info, arg_type, ret_type, - gen, success_response, boxed): + gen, success_response, boxed, allow_oob): doc = self.cur_doc if boxed: body = texi_body(doc) diff --git a/scripts/qapi/introspect.py b/scripts/qapi/introspect.py index f66c397fb0..f9e67e8227 100644 --- a/scripts/qapi/introspect.py +++ b/scripts/qapi/introspect.py @@ -13,26 +13,38 @@ See the COPYING file in the top-level directory. from qapi.common import * -# Caveman's json.dumps() replacement (we're stuck at Python 2.4) -# TODO try to use json.dumps() once we get unstuck -def to_json(obj, level=0): +def to_qlit(obj, level=0, suppress_first_indent=False): + + def indent(level): + return level * 4 * ' ' + + ret = '' + if not suppress_first_indent: + ret += indent(level) if obj is None: - ret = 'null' + ret += 'QLIT_QNULL' elif isinstance(obj, str): - ret = '"' + obj.replace('"', r'\"') + '"' + ret += 'QLIT_QSTR(' + to_c_string(obj) + ')' elif isinstance(obj, list): - elts = [to_json(elt, level + 1) + elts = [to_qlit(elt, level + 1) for elt in obj] - ret = '[' + ', '.join(elts) + ']' + elts.append(indent(level + 1) + "{}") + ret += 'QLIT_QLIST(((QLitObject[]) {\n' + ret += ',\n'.join(elts) + '\n' + ret += indent(level) + '}))' elif isinstance(obj, dict): - elts = ['"%s": %s' % (key.replace('"', r'\"'), - to_json(obj[key], level + 1)) - for key in sorted(obj.keys())] - ret = '{' + ', '.join(elts) + '}' + elts = [] + for key, value in sorted(obj.items()): + elts.append(indent(level + 1) + '{ %s, %s }' % + (to_c_string(key), to_qlit(value, level + 1, True))) + elts.append(indent(level + 1) + '{}') + ret += 'QLIT_QDICT(((QLitDictEntry[]) {\n' + ret += ',\n'.join(elts) + '\n' + ret += indent(level) + '}))' + elif isinstance(obj, bool): + ret += 'QLIT_QBOOL(%s)' % ('true' if obj else 'false') else: assert False # not implemented - if level == 1: - ret = '\n' + ret return ret @@ -48,7 +60,7 @@ class QAPISchemaGenIntrospectVisitor(QAPISchemaMonolithicCVisitor): ' * QAPI/QMP schema introspection', __doc__) self._unmask = unmask self._schema = None - self._jsons = [] + self._qlits = [] self._used_types = [] self._name_map = {} self._genc.add(mcgen(''' @@ -63,27 +75,27 @@ class QAPISchemaGenIntrospectVisitor(QAPISchemaMonolithicCVisitor): def visit_end(self): # visit the types that are actually used - jsons = self._jsons - self._jsons = [] + qlits = self._qlits + self._qlits = [] for typ in self._used_types: typ.visit(self) # generate C # TODO can generate awfully long lines - jsons.extend(self._jsons) - name = c_name(self._prefix, protect=False) + 'qmp_schema_json' + qlits.extend(self._qlits) + name = c_name(self._prefix, protect=False) + 'qmp_schema_qlit' self._genh.add(mcgen(''' -extern const char %(c_name)s[]; +#include "qapi/qmp/qlit.h" + +extern const QLitObject %(c_name)s; ''', c_name=c_name(name))) - lines = to_json(jsons).split('\n') - c_string = '\n '.join([to_c_string(line) for line in lines]) self._genc.add(mcgen(''' -const char %(c_name)s[] = %(c_string)s; +const QLitObject %(c_name)s = %(c_string)s; ''', c_name=c_name(name), - c_string=c_string)) + c_string=to_qlit(qlits))) self._schema = None - self._jsons = [] + self._qlits = [] self._used_types = [] self._name_map = {} @@ -117,12 +129,12 @@ const char %(c_name)s[] = %(c_string)s; return '[' + self._use_type(typ.element_type) + ']' return self._name(typ.name) - def _gen_json(self, name, mtype, obj): + def _gen_qlit(self, name, mtype, obj): if mtype not in ('command', 'event', 'builtin', 'array'): name = self._name(name) obj['name'] = name obj['meta-type'] = mtype - self._jsons.append(obj) + self._qlits.append(obj) def _gen_member(self, member): ret = {'name': member.name, 'type': self._use_type(member.type)} @@ -138,38 +150,39 @@ const char %(c_name)s[] = %(c_string)s; return {'case': variant.name, 'type': self._use_type(variant.type)} def visit_builtin_type(self, name, info, json_type): - self._gen_json(name, 'builtin', {'json-type': json_type}) + self._gen_qlit(name, 'builtin', {'json-type': json_type}) def visit_enum_type(self, name, info, values, prefix): - self._gen_json(name, 'enum', {'values': values}) + self._gen_qlit(name, 'enum', {'values': values}) def visit_array_type(self, name, info, element_type): element = self._use_type(element_type) - self._gen_json('[' + element + ']', 'array', {'element-type': element}) + self._gen_qlit('[' + element + ']', 'array', {'element-type': element}) def visit_object_type_flat(self, name, info, members, variants): obj = {'members': [self._gen_member(m) for m in members]} if variants: obj.update(self._gen_variants(variants.tag_member.name, variants.variants)) - self._gen_json(name, 'object', obj) + self._gen_qlit(name, 'object', obj) def visit_alternate_type(self, name, info, variants): - self._gen_json(name, 'alternate', + self._gen_qlit(name, 'alternate', {'members': [{'type': self._use_type(m.type)} for m in variants.variants]}) def visit_command(self, name, info, arg_type, ret_type, - gen, success_response, boxed): + gen, success_response, boxed, allow_oob): arg_type = arg_type or self._schema.the_empty_object_type ret_type = ret_type or self._schema.the_empty_object_type - self._gen_json(name, 'command', + self._gen_qlit(name, 'command', {'arg-type': self._use_type(arg_type), - 'ret-type': self._use_type(ret_type)}) + 'ret-type': self._use_type(ret_type), + 'allow-oob': allow_oob}) def visit_event(self, name, info, arg_type, boxed): arg_type = arg_type or self._schema.the_empty_object_type - self._gen_json(name, 'event', {'arg-type': self._use_type(arg_type)}) + self._gen_qlit(name, 'event', {'arg-type': self._use_type(arg_type)}) def gen_introspect(schema, output_dir, prefix, opt_unmask): |