2014-06-18 10:43:28 +04:00
|
|
|
#
|
|
|
|
# QAPI event generator
|
|
|
|
#
|
|
|
|
# Copyright (c) 2014 Wenchao Xia
|
qapi-event: Convert to QAPISchemaVisitor, fixing data with base
Fixes events whose data is struct with base to include the struct's
base members. Test case is qapi-schema-test.json's event
__org.qemu_x-command:
{ 'event': '__ORG.QEMU_X-EVENT', 'data': '__org.qemu_x-Struct' }
{ 'struct': '__org.qemu_x-Struct', 'base': '__org.qemu_x-Base',
'data': { '__org.qemu_x-member2': 'str' } }
{ 'struct': '__org.qemu_x-Base',
'data': { '__org.qemu_x-member1': '__org.qemu_x-Enum' } }
Patch's effect on generated qapi_event_send___org_qemu_x_event():
-void qapi_event_send___org_qemu_x_event(const char *__org_qemu_x_member2,
+void qapi_event_send___org_qemu_x_event(__org_qemu_x_Enum __org_qemu_x_member1,
+ const char *__org_qemu_x_member2,
Error **errp)
{
QDict *qmp;
@@ -224,6 +225,10 @@ void qapi_event_send___org_qemu_x_event(
goto clean;
}
+ visit_type___org_qemu_x_Enum(v, &__org_qemu_x_member1, "__org.qemu_x-member1", &local_err);
+ if (local_err) {
+ goto clean;
+ }
visit_type_str(v, (char **)&__org_qemu_x_member2, "__org.qemu_x-member2", &local_err);
if (local_err) {
goto clean;
Code is generated in a different order now, but that doesn't matter.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
2015-09-16 14:06:14 +03:00
|
|
|
# Copyright (c) 2015 Red Hat Inc.
|
2014-06-18 10:43:28 +04:00
|
|
|
#
|
|
|
|
# Authors:
|
|
|
|
# Wenchao Xia <wenchaoqemu@gmail.com>
|
qapi-event: Convert to QAPISchemaVisitor, fixing data with base
Fixes events whose data is struct with base to include the struct's
base members. Test case is qapi-schema-test.json's event
__org.qemu_x-command:
{ 'event': '__ORG.QEMU_X-EVENT', 'data': '__org.qemu_x-Struct' }
{ 'struct': '__org.qemu_x-Struct', 'base': '__org.qemu_x-Base',
'data': { '__org.qemu_x-member2': 'str' } }
{ 'struct': '__org.qemu_x-Base',
'data': { '__org.qemu_x-member1': '__org.qemu_x-Enum' } }
Patch's effect on generated qapi_event_send___org_qemu_x_event():
-void qapi_event_send___org_qemu_x_event(const char *__org_qemu_x_member2,
+void qapi_event_send___org_qemu_x_event(__org_qemu_x_Enum __org_qemu_x_member1,
+ const char *__org_qemu_x_member2,
Error **errp)
{
QDict *qmp;
@@ -224,6 +225,10 @@ void qapi_event_send___org_qemu_x_event(
goto clean;
}
+ visit_type___org_qemu_x_Enum(v, &__org_qemu_x_member1, "__org.qemu_x-member1", &local_err);
+ if (local_err) {
+ goto clean;
+ }
visit_type_str(v, (char **)&__org_qemu_x_member2, "__org.qemu_x-member2", &local_err);
if (local_err) {
goto clean;
Code is generated in a different order now, but that doesn't matter.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
2015-09-16 14:06:14 +03:00
|
|
|
# Markus Armbruster <armbru@redhat.com>
|
2014-06-18 10:43:28 +04:00
|
|
|
#
|
|
|
|
# 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 *
|
|
|
|
|
2015-09-16 14:06:16 +03:00
|
|
|
|
|
|
|
def gen_event_send_proto(name, arg_type):
|
2015-09-16 14:06:20 +03:00
|
|
|
return 'void qapi_event_send_%(c_name)s(%(param)s)' % {
|
|
|
|
'c_name': c_name(name.lower()),
|
|
|
|
'param': gen_params(arg_type, 'Error **errp')}
|
2014-06-18 10:43:28 +04:00
|
|
|
|
|
|
|
|
2015-09-16 14:06:16 +03:00
|
|
|
def gen_event_send_decl(name, arg_type):
|
2014-06-18 10:43:28 +04:00
|
|
|
return mcgen('''
|
|
|
|
|
2015-09-16 14:06:16 +03:00
|
|
|
%(proto)s;
|
2014-06-18 10:43:28 +04:00
|
|
|
''',
|
2015-09-16 14:06:16 +03:00
|
|
|
proto=gen_event_send_proto(name, arg_type))
|
|
|
|
|
2014-06-18 10:43:28 +04:00
|
|
|
|
2015-09-16 14:06:16 +03:00
|
|
|
def gen_event_send(name, arg_type):
|
|
|
|
ret = mcgen('''
|
2014-06-18 10:43:28 +04:00
|
|
|
|
2015-09-16 14:06:16 +03:00
|
|
|
%(proto)s
|
2014-06-18 10:43:28 +04:00
|
|
|
{
|
|
|
|
QDict *qmp;
|
2015-09-30 01:21:08 +03:00
|
|
|
Error *err = NULL;
|
2014-06-18 10:43:28 +04:00
|
|
|
QMPEventFuncEmit emit;
|
2015-09-16 14:06:16 +03:00
|
|
|
''',
|
|
|
|
proto=gen_event_send_proto(name, arg_type))
|
2014-06-18 10:43:28 +04:00
|
|
|
|
2015-09-16 14:06:16 +03:00
|
|
|
if arg_type and arg_type.members:
|
|
|
|
ret += mcgen('''
|
2014-06-18 10:43:28 +04:00
|
|
|
QmpOutputVisitor *qov;
|
|
|
|
Visitor *v;
|
|
|
|
QObject *obj;
|
|
|
|
|
2015-09-16 14:06:16 +03:00
|
|
|
''')
|
2014-06-18 10:43:28 +04:00
|
|
|
|
2015-09-16 14:06:16 +03:00
|
|
|
ret += mcgen('''
|
2014-06-18 10:43:28 +04:00
|
|
|
emit = qmp_event_get_func_emit();
|
|
|
|
if (!emit) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-09-16 14:06:16 +03:00
|
|
|
qmp = qmp_event_build_dict("%(name)s");
|
2014-06-18 10:43:28 +04:00
|
|
|
|
2015-09-16 14:06:16 +03:00
|
|
|
''',
|
|
|
|
name=name)
|
2014-06-18 10:43:28 +04:00
|
|
|
|
2015-09-16 14:06:16 +03:00
|
|
|
if arg_type and arg_type.members:
|
|
|
|
ret += mcgen('''
|
2014-06-18 10:43:28 +04:00
|
|
|
qov = qmp_output_visitor_new();
|
|
|
|
g_assert(qov);
|
|
|
|
|
|
|
|
v = qmp_output_get_visitor(qov);
|
|
|
|
g_assert(v);
|
|
|
|
|
|
|
|
/* Fake visit, as if all members are under a structure */
|
2015-09-30 01:21:08 +03:00
|
|
|
visit_start_struct(v, NULL, "", "%(name)s", 0, &err);
|
2015-09-16 14:06:16 +03:00
|
|
|
''',
|
|
|
|
name=name)
|
2015-09-30 01:21:13 +03:00
|
|
|
ret += gen_err_check()
|
qapi: Share gen_visit_fields()
Consolidate the code between visit, command marshalling, and
event generation that iterates over the members of a struct.
It reduces code duplication in the generator, so that a future
patch can reduce the size of generated code while touching only
one instead of three locations.
There are no changes to the generated marshal code.
The visitor code becomes slightly more verbose, but remains
semantically equivalent, and is actually easier to read as
it follows a more common idiom:
| visit_optional(v, &(*obj)->has_device, "device", &err);
|- if (!err && (*obj)->has_device) {
|- visit_type_str(v, &(*obj)->device, "device", &err);
|- }
| if (err) {
| goto out;
| }
|+ if ((*obj)->has_device) {
|+ visit_type_str(v, &(*obj)->device, "device", &err);
|+ if (err) {
|+ goto out;
|+ }
|+ }
The event code becomes slightly more verbose, but this is
arguably a bug fix: although the visitors are not well
documented, use of an optional member should not be attempted
unless guarded by a prior call to visit_optional(). Works only
because the output qmp visitor has a no-op visit_optional():
|+ visit_optional(v, &has_offset, "offset", &err);
|+ if (err) {
|+ goto out;
|+ }
| if (has_offset) {
| visit_type_int(v, &offset, "offset", &err);
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1443565276-4535-17-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2015-09-30 01:21:14 +03:00
|
|
|
ret += gen_visit_fields(arg_type.members, need_cast=True)
|
2015-09-16 14:06:16 +03:00
|
|
|
ret += mcgen('''
|
2015-09-30 01:21:08 +03:00
|
|
|
visit_end_struct(v, &err);
|
|
|
|
if (err) {
|
2015-09-30 01:21:10 +03:00
|
|
|
goto out;
|
2014-06-18 10:43:28 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
obj = qmp_output_get_qobject(qov);
|
|
|
|
g_assert(obj != NULL);
|
|
|
|
|
|
|
|
qdict_put_obj(qmp, "data", obj);
|
2015-09-16 14:06:16 +03:00
|
|
|
''')
|
2014-06-18 10:43:28 +04:00
|
|
|
|
2015-09-16 14:06:16 +03:00
|
|
|
ret += mcgen('''
|
2015-09-30 01:21:08 +03:00
|
|
|
emit(%(c_enum)s, qmp, &err);
|
2014-06-18 10:43:28 +04:00
|
|
|
|
2015-09-16 14:06:16 +03:00
|
|
|
''',
|
|
|
|
c_enum=c_enum_const(event_enum_name, name))
|
2014-06-18 10:43:28 +04:00
|
|
|
|
2015-09-16 14:06:16 +03:00
|
|
|
if arg_type and arg_type.members:
|
|
|
|
ret += mcgen('''
|
2015-09-30 01:21:10 +03:00
|
|
|
out:
|
2014-06-18 10:43:28 +04:00
|
|
|
qmp_output_visitor_cleanup(qov);
|
2015-09-16 14:06:16 +03:00
|
|
|
''')
|
|
|
|
ret += mcgen('''
|
2015-09-30 01:21:08 +03:00
|
|
|
error_propagate(errp, err);
|
2014-06-18 10:43:28 +04:00
|
|
|
QDECREF(qmp);
|
|
|
|
}
|
2015-09-16 14:06:16 +03:00
|
|
|
''')
|
2014-06-18 10:43:28 +04:00
|
|
|
return ret
|
|
|
|
|
qapi-event: Convert to QAPISchemaVisitor, fixing data with base
Fixes events whose data is struct with base to include the struct's
base members. Test case is qapi-schema-test.json's event
__org.qemu_x-command:
{ 'event': '__ORG.QEMU_X-EVENT', 'data': '__org.qemu_x-Struct' }
{ 'struct': '__org.qemu_x-Struct', 'base': '__org.qemu_x-Base',
'data': { '__org.qemu_x-member2': 'str' } }
{ 'struct': '__org.qemu_x-Base',
'data': { '__org.qemu_x-member1': '__org.qemu_x-Enum' } }
Patch's effect on generated qapi_event_send___org_qemu_x_event():
-void qapi_event_send___org_qemu_x_event(const char *__org_qemu_x_member2,
+void qapi_event_send___org_qemu_x_event(__org_qemu_x_Enum __org_qemu_x_member1,
+ const char *__org_qemu_x_member2,
Error **errp)
{
QDict *qmp;
@@ -224,6 +225,10 @@ void qapi_event_send___org_qemu_x_event(
goto clean;
}
+ visit_type___org_qemu_x_Enum(v, &__org_qemu_x_member1, "__org.qemu_x-member1", &local_err);
+ if (local_err) {
+ goto clean;
+ }
visit_type_str(v, (char **)&__org_qemu_x_member2, "__org.qemu_x-member2", &local_err);
if (local_err) {
goto clean;
Code is generated in a different order now, but that doesn't matter.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
2015-09-16 14:06:14 +03:00
|
|
|
|
|
|
|
class QAPISchemaGenEventVisitor(QAPISchemaVisitor):
|
|
|
|
def __init__(self):
|
|
|
|
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):
|
2015-09-16 14:06:16 +03:00
|
|
|
self.decl += gen_enum(event_enum_name, self._event_names)
|
|
|
|
self.defn += gen_enum_lookup(event_enum_name, self._event_names)
|
qapi-event: Convert to QAPISchemaVisitor, fixing data with base
Fixes events whose data is struct with base to include the struct's
base members. Test case is qapi-schema-test.json's event
__org.qemu_x-command:
{ 'event': '__ORG.QEMU_X-EVENT', 'data': '__org.qemu_x-Struct' }
{ 'struct': '__org.qemu_x-Struct', 'base': '__org.qemu_x-Base',
'data': { '__org.qemu_x-member2': 'str' } }
{ 'struct': '__org.qemu_x-Base',
'data': { '__org.qemu_x-member1': '__org.qemu_x-Enum' } }
Patch's effect on generated qapi_event_send___org_qemu_x_event():
-void qapi_event_send___org_qemu_x_event(const char *__org_qemu_x_member2,
+void qapi_event_send___org_qemu_x_event(__org_qemu_x_Enum __org_qemu_x_member1,
+ const char *__org_qemu_x_member2,
Error **errp)
{
QDict *qmp;
@@ -224,6 +225,10 @@ void qapi_event_send___org_qemu_x_event(
goto clean;
}
+ visit_type___org_qemu_x_Enum(v, &__org_qemu_x_member1, "__org.qemu_x-member1", &local_err);
+ if (local_err) {
+ goto clean;
+ }
visit_type_str(v, (char **)&__org_qemu_x_member2, "__org.qemu_x-member2", &local_err);
if (local_err) {
goto clean;
Code is generated in a different order now, but that doesn't matter.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
2015-09-16 14:06:14 +03:00
|
|
|
self._event_names = None
|
|
|
|
|
|
|
|
def visit_event(self, name, info, arg_type):
|
2015-09-16 14:06:16 +03:00
|
|
|
self.decl += gen_event_send_decl(name, arg_type)
|
|
|
|
self.defn += gen_event_send(name, arg_type)
|
qapi-event: Convert to QAPISchemaVisitor, fixing data with base
Fixes events whose data is struct with base to include the struct's
base members. Test case is qapi-schema-test.json's event
__org.qemu_x-command:
{ 'event': '__ORG.QEMU_X-EVENT', 'data': '__org.qemu_x-Struct' }
{ 'struct': '__org.qemu_x-Struct', 'base': '__org.qemu_x-Base',
'data': { '__org.qemu_x-member2': 'str' } }
{ 'struct': '__org.qemu_x-Base',
'data': { '__org.qemu_x-member1': '__org.qemu_x-Enum' } }
Patch's effect on generated qapi_event_send___org_qemu_x_event():
-void qapi_event_send___org_qemu_x_event(const char *__org_qemu_x_member2,
+void qapi_event_send___org_qemu_x_event(__org_qemu_x_Enum __org_qemu_x_member1,
+ const char *__org_qemu_x_member2,
Error **errp)
{
QDict *qmp;
@@ -224,6 +225,10 @@ void qapi_event_send___org_qemu_x_event(
goto clean;
}
+ visit_type___org_qemu_x_Enum(v, &__org_qemu_x_member1, "__org.qemu_x-member1", &local_err);
+ if (local_err) {
+ goto clean;
+ }
visit_type_str(v, (char **)&__org_qemu_x_member2, "__org.qemu_x-member2", &local_err);
if (local_err) {
goto clean;
Code is generated in a different order now, but that doesn't matter.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
2015-09-16 14:06:14 +03:00
|
|
|
self._event_names.append(name)
|
|
|
|
|
|
|
|
|
2015-04-02 14:12:21 +03:00
|
|
|
(input_file, output_dir, do_c, do_h, prefix, dummy) = parse_command_line()
|
2014-06-18 10:43:28 +04:00
|
|
|
|
2015-04-02 15:46:39 +03:00
|
|
|
c_comment = '''
|
2014-06-18 10:43:28 +04:00
|
|
|
/*
|
|
|
|
* schema-defined QAPI event functions
|
|
|
|
*
|
|
|
|
* Copyright (c) 2014 Wenchao Xia
|
|
|
|
*
|
|
|
|
* Authors:
|
|
|
|
* Wenchao Xia <wenchaoqemu@gmail.com>
|
|
|
|
*
|
|
|
|
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
|
|
|
* See the COPYING.LIB file in the top-level directory.
|
|
|
|
*
|
|
|
|
*/
|
2015-04-02 15:46:39 +03:00
|
|
|
'''
|
|
|
|
h_comment = '''
|
2014-06-18 10:43:28 +04:00
|
|
|
/*
|
|
|
|
* schema-defined QAPI event functions
|
|
|
|
*
|
|
|
|
* Copyright (c) 2014 Wenchao Xia
|
|
|
|
*
|
|
|
|
* Authors:
|
|
|
|
* Wenchao Xia <wenchaoqemu@gmail.com>
|
|
|
|
*
|
|
|
|
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
|
|
|
* See the COPYING.LIB file in the top-level directory.
|
|
|
|
*
|
|
|
|
*/
|
2015-04-02 15:46:39 +03:00
|
|
|
'''
|
2014-06-18 10:43:28 +04:00
|
|
|
|
2015-04-02 15:46:39 +03:00
|
|
|
(fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix,
|
|
|
|
'qapi-event.c', 'qapi-event.h',
|
|
|
|
c_comment, h_comment)
|
2014-06-18 10:43:28 +04:00
|
|
|
|
2015-04-02 15:46:39 +03:00
|
|
|
fdef.write(mcgen('''
|
|
|
|
#include "qemu-common.h"
|
|
|
|
#include "%(prefix)sqapi-event.h"
|
|
|
|
#include "%(prefix)sqapi-visit.h"
|
|
|
|
#include "qapi/qmp-output-visitor.h"
|
|
|
|
#include "qapi/qmp-event.h"
|
|
|
|
|
|
|
|
''',
|
|
|
|
prefix=prefix))
|
|
|
|
|
|
|
|
fdecl.write(mcgen('''
|
2014-06-18 10:43:28 +04:00
|
|
|
#include "qapi/error.h"
|
|
|
|
#include "qapi/qmp/qdict.h"
|
|
|
|
#include "%(prefix)sqapi-types.h"
|
|
|
|
|
|
|
|
''',
|
2015-04-02 15:46:39 +03:00
|
|
|
prefix=prefix))
|
2014-06-18 10:43:28 +04:00
|
|
|
|
2015-07-01 13:59:40 +03:00
|
|
|
event_enum_name = c_name(prefix + "QAPIEvent", protect=False)
|
qapi-event: Convert to QAPISchemaVisitor, fixing data with base
Fixes events whose data is struct with base to include the struct's
base members. Test case is qapi-schema-test.json's event
__org.qemu_x-command:
{ 'event': '__ORG.QEMU_X-EVENT', 'data': '__org.qemu_x-Struct' }
{ 'struct': '__org.qemu_x-Struct', 'base': '__org.qemu_x-Base',
'data': { '__org.qemu_x-member2': 'str' } }
{ 'struct': '__org.qemu_x-Base',
'data': { '__org.qemu_x-member1': '__org.qemu_x-Enum' } }
Patch's effect on generated qapi_event_send___org_qemu_x_event():
-void qapi_event_send___org_qemu_x_event(const char *__org_qemu_x_member2,
+void qapi_event_send___org_qemu_x_event(__org_qemu_x_Enum __org_qemu_x_member1,
+ const char *__org_qemu_x_member2,
Error **errp)
{
QDict *qmp;
@@ -224,6 +225,10 @@ void qapi_event_send___org_qemu_x_event(
goto clean;
}
+ visit_type___org_qemu_x_Enum(v, &__org_qemu_x_member1, "__org.qemu_x-member1", &local_err);
+ if (local_err) {
+ goto clean;
+ }
visit_type_str(v, (char **)&__org_qemu_x_member2, "__org.qemu_x-member2", &local_err);
if (local_err) {
goto clean;
Code is generated in a different order now, but that doesn't matter.
Signed-off-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
Reviewed-by: Daniel P. Berrange <berrange@redhat.com>
2015-09-16 14:06:14 +03:00
|
|
|
|
|
|
|
schema = QAPISchema(input_file)
|
|
|
|
gen = QAPISchemaGenEventVisitor()
|
|
|
|
schema.visit(gen)
|
|
|
|
fdef.write(gen.defn)
|
|
|
|
fdecl.write(gen.decl)
|
2014-06-18 10:43:28 +04:00
|
|
|
|
2015-04-02 15:46:39 +03:00
|
|
|
close_output(fdef, fdecl)
|