2014-06-18 10:43:28 +04:00
|
|
|
#
|
|
|
|
# QAPI event generator
|
|
|
|
#
|
|
|
|
# Copyright (c) 2014 Wenchao Xia
|
qapi: Improve generated event use of qapi visitor
All other successful clients of visit_start_struct() were paired
with an unconditional visit_end_struct(); but the generated
code for events was relying on qmp_output_visitor_cleanup() to
work on an incomplete visit. Alter the code to guarantee that
the struct is completed, which will make a future patch to
split visit_end_struct() easier to reason about. While at it,
drop some assertions and comments that are not present in other
uses of the qmp output visitor, and pass NULL rather than "" as
the 'kind' parameter (matching most other uses where obj is NULL).
The changes to the generated code look like:
| qmp = qmp_event_build_dict("DEVICE_TRAY_MOVED");
|
| 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 */
|- visit_start_struct(v, NULL, "", "DEVICE_TRAY_MOVED", 0, &err);
|+ visit_start_struct(v, NULL, NULL, "DEVICE_TRAY_MOVED", 0, &err);
| if (err) {
| goto out;
| }
| visit_type_str(v, (char **)&device, "device", &err);
| if (err) {
|- goto out;
|+ goto out_obj;
| }
| visit_type_bool(v, &tray_open, "tray-open", &err);
| if (err) {
|- goto out;
|+ goto out_obj;
| }
|- visit_end_struct(v, &err);
|+out_obj:
|+ visit_end_struct(v, err ? NULL : &err);
| if (err) {
| goto out;
| }
|
| obj = qmp_output_get_qobject(qov);
|- g_assert(obj != NULL);
|+ g_assert(obj);
|
| qdict_put_obj(qmp, "data", obj);
| emit(QAPI_EVENT_DEVICE_TRAY_MOVED, qmp, &err);
Note that the 'goto out_obj' with no intervening code before the
label, as well as the construct of 'err ? NULL : &err', are both
a bit unusual but also temporary; they get fixed in a later patch
that splits visit_end_struct() to drop its errp parameter by moving
some checking before the label. But until that time, this was the
simplest way to avoid the appearance of passing a possibly-set
error to visit_end_struct(), even though actual code inspection
shows that visit_end_struct() for a QMP output visitor will never
set an error.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1454075341-13658-11-git-send-email-eblake@redhat.com>
[Commit message's code diff tweaked]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-01-29 16:48:46 +03:00
|
|
|
# Copyright (c) 2015-2016 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
|
|
|
|
qapi-event: Utilize implicit struct visits
Rather than generate inline per-member visits, take advantage
of the 'visit_type_FOO_members()' function for emitting events.
This is possible now that implicit structs can be visited like
any other. Generated code shrinks accordingly; by initializing
a struct based on parameters, through a new gen_param_var()
helper, like:
|@@ -338,6 +250,9 @@ void qapi_event_send_block_job_error(con
| QMPEventFuncEmit emit = qmp_event_get_func_emit();
| QmpOutputVisitor *qov;
| Visitor *v;
|+ q_obj_BLOCK_JOB_ERROR_arg param = {
|+ (char *)device, operation, action
|+ };
|
| if (!emit) {
| return;
@@ -351,19 +266,7 @@ void qapi_event_send_block_job_error(con
| if (err) {
| goto out;
| }
|- visit_type_str(v, "device", (char **)&device, &err);
|- if (err) {
|- goto out_obj;
|- }
|- visit_type_IoOperationType(v, "operation", &operation, &err);
|- if (err) {
|- goto out_obj;
|- }
|- visit_type_BlockErrorAction(v, "action", &action, &err);
|- if (err) {
|- goto out_obj;
|- }
|-out_obj:
|+ visit_type_q_obj_BLOCK_JOB_ERROR_arg_members(v, ¶m, &err);
| visit_end_struct(v, err ? NULL : &err);
Notice that the initialization of 'param' has to cast away const
(just as the old gen_visit_members() had to do): we can't change
the signature of the user function (which uses 'const char *'), but
have to assign it to a non-const QAPI object (which requires
'char *').
While touching this, document with a FIXME comment that there is
still a potential collision between QMP members and our choice of
local variable names within qapi_event_send_FOO().
This patch also paves the way for some followup simplifications
in the generator, in subsequent patches.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1458254921-17042-8-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-03-18 01:48:32 +03:00
|
|
|
# Declare and initialize an object 'qapi' using parameters from gen_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 gen_params()
|
|
|
|
ret += '(char *)'
|
|
|
|
ret += c_name(memb.name)
|
|
|
|
ret += mcgen('''
|
|
|
|
|
|
|
|
};
|
|
|
|
''')
|
|
|
|
return ret
|
|
|
|
|
|
|
|
|
2015-09-16 14:06:16 +03:00
|
|
|
def gen_event_send(name, arg_type):
|
qapi-event: Utilize implicit struct visits
Rather than generate inline per-member visits, take advantage
of the 'visit_type_FOO_members()' function for emitting events.
This is possible now that implicit structs can be visited like
any other. Generated code shrinks accordingly; by initializing
a struct based on parameters, through a new gen_param_var()
helper, like:
|@@ -338,6 +250,9 @@ void qapi_event_send_block_job_error(con
| QMPEventFuncEmit emit = qmp_event_get_func_emit();
| QmpOutputVisitor *qov;
| Visitor *v;
|+ q_obj_BLOCK_JOB_ERROR_arg param = {
|+ (char *)device, operation, action
|+ };
|
| if (!emit) {
| return;
@@ -351,19 +266,7 @@ void qapi_event_send_block_job_error(con
| if (err) {
| goto out;
| }
|- visit_type_str(v, "device", (char **)&device, &err);
|- if (err) {
|- goto out_obj;
|- }
|- visit_type_IoOperationType(v, "operation", &operation, &err);
|- if (err) {
|- goto out_obj;
|- }
|- visit_type_BlockErrorAction(v, "action", &action, &err);
|- if (err) {
|- goto out_obj;
|- }
|-out_obj:
|+ visit_type_q_obj_BLOCK_JOB_ERROR_arg_members(v, ¶m, &err);
| visit_end_struct(v, err ? NULL : &err);
Notice that the initialization of 'param' has to cast away const
(just as the old gen_visit_members() had to do): we can't change
the signature of the user function (which uses 'const char *'), but
have to assign it to a non-const QAPI object (which requires
'char *').
While touching this, document with a FIXME comment that there is
still a potential collision between QMP members and our choice of
local variable names within qapi_event_send_FOO().
This patch also paves the way for some followup simplifications
in the generator, in subsequent patches.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1458254921-17042-8-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-03-18 01:48:32 +03:00
|
|
|
# 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.
|
2015-09-16 14:06:16 +03:00
|
|
|
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;
|
2015-09-16 14:06:16 +03:00
|
|
|
''')
|
qapi-event: Utilize implicit struct visits
Rather than generate inline per-member visits, take advantage
of the 'visit_type_FOO_members()' function for emitting events.
This is possible now that implicit structs can be visited like
any other. Generated code shrinks accordingly; by initializing
a struct based on parameters, through a new gen_param_var()
helper, like:
|@@ -338,6 +250,9 @@ void qapi_event_send_block_job_error(con
| QMPEventFuncEmit emit = qmp_event_get_func_emit();
| QmpOutputVisitor *qov;
| Visitor *v;
|+ q_obj_BLOCK_JOB_ERROR_arg param = {
|+ (char *)device, operation, action
|+ };
|
| if (!emit) {
| return;
@@ -351,19 +266,7 @@ void qapi_event_send_block_job_error(con
| if (err) {
| goto out;
| }
|- visit_type_str(v, "device", (char **)&device, &err);
|- if (err) {
|- goto out_obj;
|- }
|- visit_type_IoOperationType(v, "operation", &operation, &err);
|- if (err) {
|- goto out_obj;
|- }
|- visit_type_BlockErrorAction(v, "action", &action, &err);
|- if (err) {
|- goto out_obj;
|- }
|-out_obj:
|+ visit_type_q_obj_BLOCK_JOB_ERROR_arg_members(v, ¶m, &err);
| visit_end_struct(v, err ? NULL : &err);
Notice that the initialization of 'param' has to cast away const
(just as the old gen_visit_members() had to do): we can't change
the signature of the user function (which uses 'const char *'), but
have to assign it to a non-const QAPI object (which requires
'char *').
While touching this, document with a FIXME comment that there is
still a potential collision between QMP members and our choice of
local variable names within qapi_event_send_FOO().
This patch also paves the way for some followup simplifications
in the generator, in subsequent patches.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1458254921-17042-8-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-03-18 01:48:32 +03:00
|
|
|
ret += gen_param_var(arg_type)
|
2014-06-18 10:43:28 +04:00
|
|
|
|
2015-09-16 14:06:16 +03:00
|
|
|
ret += mcgen('''
|
qapi-event: Utilize implicit struct visits
Rather than generate inline per-member visits, take advantage
of the 'visit_type_FOO_members()' function for emitting events.
This is possible now that implicit structs can be visited like
any other. Generated code shrinks accordingly; by initializing
a struct based on parameters, through a new gen_param_var()
helper, like:
|@@ -338,6 +250,9 @@ void qapi_event_send_block_job_error(con
| QMPEventFuncEmit emit = qmp_event_get_func_emit();
| QmpOutputVisitor *qov;
| Visitor *v;
|+ q_obj_BLOCK_JOB_ERROR_arg param = {
|+ (char *)device, operation, action
|+ };
|
| if (!emit) {
| return;
@@ -351,19 +266,7 @@ void qapi_event_send_block_job_error(con
| if (err) {
| goto out;
| }
|- visit_type_str(v, "device", (char **)&device, &err);
|- if (err) {
|- goto out_obj;
|- }
|- visit_type_IoOperationType(v, "operation", &operation, &err);
|- if (err) {
|- goto out_obj;
|- }
|- visit_type_BlockErrorAction(v, "action", &action, &err);
|- if (err) {
|- goto out_obj;
|- }
|-out_obj:
|+ visit_type_q_obj_BLOCK_JOB_ERROR_arg_members(v, ¶m, &err);
| visit_end_struct(v, err ? NULL : &err);
Notice that the initialization of 'param' has to cast away const
(just as the old gen_visit_members() had to do): we can't change
the signature of the user function (which uses 'const char *'), but
have to assign it to a non-const QAPI object (which requires
'char *').
While touching this, document with a FIXME comment that there is
still a potential collision between QMP members and our choice of
local variable names within qapi_event_send_FOO().
This patch also paves the way for some followup simplifications
in the generator, in subsequent patches.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1458254921-17042-8-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-03-18 01:48:32 +03:00
|
|
|
|
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();
|
|
|
|
v = qmp_output_get_visitor(qov);
|
|
|
|
|
2016-01-29 16:48:57 +03:00
|
|
|
visit_start_struct(v, "%(name)s", NULL, 0, &err);
|
qapi-event: Utilize implicit struct visits
Rather than generate inline per-member visits, take advantage
of the 'visit_type_FOO_members()' function for emitting events.
This is possible now that implicit structs can be visited like
any other. Generated code shrinks accordingly; by initializing
a struct based on parameters, through a new gen_param_var()
helper, like:
|@@ -338,6 +250,9 @@ void qapi_event_send_block_job_error(con
| QMPEventFuncEmit emit = qmp_event_get_func_emit();
| QmpOutputVisitor *qov;
| Visitor *v;
|+ q_obj_BLOCK_JOB_ERROR_arg param = {
|+ (char *)device, operation, action
|+ };
|
| if (!emit) {
| return;
@@ -351,19 +266,7 @@ void qapi_event_send_block_job_error(con
| if (err) {
| goto out;
| }
|- visit_type_str(v, "device", (char **)&device, &err);
|- if (err) {
|- goto out_obj;
|- }
|- visit_type_IoOperationType(v, "operation", &operation, &err);
|- if (err) {
|- goto out_obj;
|- }
|- visit_type_BlockErrorAction(v, "action", &action, &err);
|- if (err) {
|- goto out_obj;
|- }
|-out_obj:
|+ visit_type_q_obj_BLOCK_JOB_ERROR_arg_members(v, ¶m, &err);
| visit_end_struct(v, err ? NULL : &err);
Notice that the initialization of 'param' has to cast away const
(just as the old gen_visit_members() had to do): we can't change
the signature of the user function (which uses 'const char *'), but
have to assign it to a non-const QAPI object (which requires
'char *').
While touching this, document with a FIXME comment that there is
still a potential collision between QMP members and our choice of
local variable names within qapi_event_send_FOO().
This patch also paves the way for some followup simplifications
in the generator, in subsequent patches.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1458254921-17042-8-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-03-18 01:48:32 +03:00
|
|
|
if (err) {
|
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
visit_type_%(c_name)s_members(v, ¶m, &err);
|
qapi: Split visit_end_struct() into pieces
As mentioned in previous patches, we want to call visit_end_struct()
functions unconditionally, so that visitors can release resources
tied up since the matching visit_start_struct() without also having
to worry about error priority if more than one error occurs.
Even though error_propagate() can be safely used to ignore a second
error during cleanup caused by a first error, it is simpler if the
cleanup cannot set an error. So, split out the error checking
portion (basically, input visitors checking for unvisited keys) into
a new function visit_check_struct(), which can be safely skipped if
any earlier errors are encountered, and leave the cleanup portion
(which never fails, but must be called unconditionally if
visit_start_struct() succeeded) in visit_end_struct().
Generated code in qapi-visit.c has diffs resembling:
|@@ -59,10 +59,12 @@ void visit_type_ACPIOSTInfo(Visitor *v,
| goto out_obj;
| }
| visit_type_ACPIOSTInfo_members(v, obj, &err);
|- error_propagate(errp, err);
|- err = NULL;
|+ if (err) {
|+ goto out_obj;
|+ }
|+ visit_check_struct(v, &err);
| out_obj:
|- visit_end_struct(v, &err);
|+ visit_end_struct(v);
| out:
and in qapi-event.c:
@@ -47,7 +47,10 @@ void qapi_event_send_acpi_device_ost(ACP
| goto out;
| }
| visit_type_q_obj_ACPI_DEVICE_OST_arg_members(v, ¶m, &err);
|- visit_end_struct(v, err ? NULL : &err);
|+ if (!err) {
|+ visit_check_struct(v, &err);
|+ }
|+ visit_end_struct(v);
| if (err) {
| goto out;
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1461879932-9020-20-git-send-email-eblake@redhat.com>
[Conflict with a doc fixup resolved]
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-04-29 00:45:27 +03:00
|
|
|
if (!err) {
|
|
|
|
visit_check_struct(v, &err);
|
|
|
|
}
|
|
|
|
visit_end_struct(v);
|
2015-09-30 01:21:08 +03:00
|
|
|
if (err) {
|
2015-09-30 01:21:10 +03:00
|
|
|
goto out;
|
2014-06-18 10:43:28 +04:00
|
|
|
}
|
|
|
|
|
qapi-event: Drop qmp_output_get_qobject() null check
qmp_output_get_qobject() was changed never to return null some time
ago (in commit 6c2f9a15), but the qapi_event_send_FOO() functions
still check. Clean that up:
|@@ -28,7 +28,6 @@ void qapi_event_send_acpi_device_ost(ACP
| QMPEventFuncEmit emit;
| QmpOutputVisitor *qov;
| Visitor *v;
|- QObject *obj;
|
| emit = qmp_event_get_func_emit();
| if (!emit) {
|@@ -54,10 +53,7 @@ out_obj:
| goto out;
| }
|
|- obj = qmp_output_get_qobject(qov);
|- g_assert(obj);
|-
|- qdict_put_obj(qmp, "data", obj);
|+ qdict_put_obj(qmp, "data", qmp_output_get_qobject(qov));
| emit(QAPI_EVENT_ACPI_DEVICE_OST, qmp, &err);
|
| out:
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1458254921-17042-7-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-03-18 01:48:31 +03:00
|
|
|
qdict_put_obj(qmp, "data", qmp_output_get_qobject(qov));
|
qapi-event: Utilize implicit struct visits
Rather than generate inline per-member visits, take advantage
of the 'visit_type_FOO_members()' function for emitting events.
This is possible now that implicit structs can be visited like
any other. Generated code shrinks accordingly; by initializing
a struct based on parameters, through a new gen_param_var()
helper, like:
|@@ -338,6 +250,9 @@ void qapi_event_send_block_job_error(con
| QMPEventFuncEmit emit = qmp_event_get_func_emit();
| QmpOutputVisitor *qov;
| Visitor *v;
|+ q_obj_BLOCK_JOB_ERROR_arg param = {
|+ (char *)device, operation, action
|+ };
|
| if (!emit) {
| return;
@@ -351,19 +266,7 @@ void qapi_event_send_block_job_error(con
| if (err) {
| goto out;
| }
|- visit_type_str(v, "device", (char **)&device, &err);
|- if (err) {
|- goto out_obj;
|- }
|- visit_type_IoOperationType(v, "operation", &operation, &err);
|- if (err) {
|- goto out_obj;
|- }
|- visit_type_BlockErrorAction(v, "action", &action, &err);
|- if (err) {
|- goto out_obj;
|- }
|-out_obj:
|+ visit_type_q_obj_BLOCK_JOB_ERROR_arg_members(v, ¶m, &err);
| visit_end_struct(v, err ? NULL : &err);
Notice that the initialization of 'param' has to cast away const
(just as the old gen_visit_members() had to do): we can't change
the signature of the user function (which uses 'const char *'), but
have to assign it to a non-const QAPI object (which requires
'char *').
While touching this, document with a FIXME comment that there is
still a potential collision between QMP members and our choice of
local variable names within qapi_event_send_FOO().
This patch also paves the way for some followup simplifications
in the generator, in subsequent patches.
Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1458254921-17042-8-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
2016-03-18 01:48:32 +03:00
|
|
|
''',
|
|
|
|
name=name, c_name=arg_type.c_name())
|
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('''
|
2016-02-08 18:36:46 +03:00
|
|
|
#include "qemu/osdep.h"
|
2015-04-02 15:46:39 +03:00
|
|
|
#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)
|