diff options
author | Markus Armbruster <armbru@redhat.com> | 2018-02-26 13:48:58 -0600 |
---|---|---|
committer | Eric Blake <eblake@redhat.com> | 2018-03-02 13:14:09 -0600 |
commit | fb0bc835e56b894cbc7236294921e5393c786ad8 (patch) | |
tree | c96c6626054c20084fc9fe268fab187c0bed20bf /scripts/qapi-event.py | |
parent | 26df4e7fab06422b21e11d039c64243ca4003147 (diff) |
qapi-gen: New common driver for code and doc generators
Whenever qapi-schema.json changes, we run six programs eleven times to
update eleven files. Similar for qga/qapi-schema.json. This is
silly. Replace the six programs by a single program that spits out
all eleven files.
The programs become modules in new Python package qapi, along with the
helper library. This requires moving them to scripts/qapi/. While
moving them, consistently drop executable mode bits.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20180211093607.27351-9-armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Michael Roth <mdroth@linux.vnet.ibm.com>
[eblake: move change to one-line 'blurb' earlier in series, mention mode
bit change as intentional, update qapi-code-gen.txt to match actual
generated events.c file]
Signed-off-by: Eric Blake <eblake@redhat.com>
Diffstat (limited to 'scripts/qapi-event.py')
-rw-r--r-- | scripts/qapi-event.py | 215 |
1 files changed, 0 insertions, 215 deletions
diff --git a/scripts/qapi-event.py b/scripts/qapi-event.py deleted file mode 100644 index 1f8bf62c8b..0000000000 --- a/scripts/qapi-event.py +++ /dev/null @@ -1,215 +0,0 @@ -""" -QAPI event generator - -Copyright (c) 2014 Wenchao Xia -Copyright (c) 2015-2018 Red Hat Inc. - -Authors: - Wenchao Xia <wenchaoqemu@gmail.com> - Markus Armbruster <armbru@redhat.com> - -This work is licensed under the terms of the GNU GPL, version 2. -See the COPYING file in the top-level directory. -""" - -from qapi import * - - -def build_event_send_proto(name, arg_type, boxed): - return 'void qapi_event_send_%(c_name)s(%(param)s)' % { - 'c_name': c_name(name.lower()), - 'param': build_params(arg_type, boxed, 'Error **errp')} - - -def gen_event_send_decl(name, arg_type, boxed): - return mcgen(''' - -%(proto)s; -''', - proto=build_event_send_proto(name, arg_type, boxed)) - - -# Declare and initialize an object 'qapi' using parameters from build_params() -def gen_param_var(typ): - assert not typ.variants - ret = mcgen(''' - %(c_name)s param = { -''', - c_name=typ.c_name()) - sep = ' ' - for memb in typ.members: - ret += sep - sep = ', ' - if memb.optional: - ret += 'has_' + c_name(memb.name) + sep - if memb.type.name == 'str': - # Cast away const added in build_params() - ret += '(char *)' - ret += c_name(memb.name) - ret += mcgen(''' - - }; -''') - if not typ.is_implicit(): - ret += mcgen(''' - %(c_name)s *arg = ¶m; -''', - c_name=typ.c_name()) - return ret - - -def gen_event_send(name, arg_type, boxed, event_enum_name): - # FIXME: Our declaration of local variables (and of 'errp' in the - # parameter list) can collide with exploded members of the event's - # data type passed in as parameters. If this collision ever hits in - # practice, we can rename our local variables with a leading _ prefix, - # or split the code into a wrapper function that creates a boxed - # 'param' object then calls another to do the real work. - ret = mcgen(''' - -%(proto)s -{ - QDict *qmp; - Error *err = NULL; - QMPEventFuncEmit emit; -''', - proto=build_event_send_proto(name, arg_type, boxed)) - - if arg_type and not arg_type.is_empty(): - ret += mcgen(''' - QObject *obj; - Visitor *v; -''') - if not boxed: - ret += gen_param_var(arg_type) - else: - assert not boxed - - ret += mcgen(''' - - emit = qmp_event_get_func_emit(); - if (!emit) { - return; - } - - qmp = qmp_event_build_dict("%(name)s"); - -''', - name=name) - - if arg_type and not arg_type.is_empty(): - ret += mcgen(''' - v = qobject_output_visitor_new(&obj); -''') - if not arg_type.is_implicit(): - ret += mcgen(''' - visit_type_%(c_name)s(v, "%(name)s", &arg, &err); -''', - name=name, c_name=arg_type.c_name()) - else: - ret += mcgen(''' - - visit_start_struct(v, "%(name)s", NULL, 0, &err); - if (err) { - goto out; - } - visit_type_%(c_name)s_members(v, ¶m, &err); - if (!err) { - visit_check_struct(v, &err); - } - visit_end_struct(v, NULL); -''', - name=name, c_name=arg_type.c_name()) - ret += mcgen(''' - if (err) { - goto out; - } - - visit_complete(v, &obj); - qdict_put_obj(qmp, "data", obj); -''') - - ret += mcgen(''' - emit(%(c_enum)s, qmp, &err); - -''', - c_enum=c_enum_const(event_enum_name, name)) - - if arg_type and not arg_type.is_empty(): - ret += mcgen(''' -out: - visit_free(v); -''') - ret += mcgen(''' - error_propagate(errp, err); - QDECREF(qmp); -} -''') - return ret - - -class QAPISchemaGenEventVisitor(QAPISchemaVisitor): - def __init__(self, prefix): - self._enum_name = c_name(prefix + 'QAPIEvent', protect=False) - self.decl = None - self.defn = None - self._event_names = None - - def visit_begin(self, schema): - self.decl = '' - self.defn = '' - self._event_names = [] - - def visit_end(self): - self.decl += gen_enum(self._enum_name, self._event_names) - self.defn += gen_enum_lookup(self._enum_name, self._event_names) - self._event_names = None - - def visit_event(self, name, info, arg_type, boxed): - self.decl += gen_event_send_decl(name, arg_type, boxed) - self.defn += gen_event_send(name, arg_type, boxed, self._enum_name) - self._event_names.append(name) - - -def main(argv): - (input_file, output_dir, do_c, do_h, prefix, dummy) = parse_command_line() - - blurb = ' * Schema-defined QAPI/QMP events' - - genc = QAPIGenC(blurb, __doc__) - genh = QAPIGenH(blurb, __doc__) - - genc.add(mcgen(''' -#include "qemu/osdep.h" -#include "qemu-common.h" -#include "%(prefix)sqapi-event.h" -#include "%(prefix)sqapi-visit.h" -#include "qapi/error.h" -#include "qapi/qmp/qdict.h" -#include "qapi/qobject-output-visitor.h" -#include "qapi/qmp-event.h" - -''', - prefix=prefix)) - - genh.add(mcgen(''' -#include "qapi/util.h" -#include "%(prefix)sqapi-types.h" - -''', - prefix=prefix)) - - schema = QAPISchema(input_file) - vis = QAPISchemaGenEventVisitor(prefix) - schema.visit(vis) - genc.add(vis.defn) - genh.add(vis.decl) - - if do_c: - genc.write(output_dir, prefix + 'qapi-event.c') - if do_h: - genh.write(output_dir, prefix + 'qapi-event.h') - - -if __name__ == '__main__': - main(sys.argv) |