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>
This commit is contained in:
parent
8df59565d2
commit
0949e95b48
@ -28,7 +28,37 @@ def gen_event_send_decl(name, arg_type):
|
|||||||
proto=gen_event_send_proto(name, arg_type))
|
proto=gen_event_send_proto(name, arg_type))
|
||||||
|
|
||||||
|
|
||||||
|
# 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
|
||||||
|
|
||||||
|
|
||||||
def gen_event_send(name, arg_type):
|
def gen_event_send(name, arg_type):
|
||||||
|
# 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('''
|
ret = mcgen('''
|
||||||
|
|
||||||
%(proto)s
|
%(proto)s
|
||||||
@ -43,10 +73,11 @@ def gen_event_send(name, arg_type):
|
|||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
QmpOutputVisitor *qov;
|
QmpOutputVisitor *qov;
|
||||||
Visitor *v;
|
Visitor *v;
|
||||||
|
|
||||||
''')
|
''')
|
||||||
|
ret += gen_param_var(arg_type)
|
||||||
|
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
|
|
||||||
emit = qmp_event_get_func_emit();
|
emit = qmp_event_get_func_emit();
|
||||||
if (!emit) {
|
if (!emit) {
|
||||||
return;
|
return;
|
||||||
@ -58,26 +89,23 @@ def gen_event_send(name, arg_type):
|
|||||||
name=name)
|
name=name)
|
||||||
|
|
||||||
if arg_type and arg_type.members:
|
if arg_type and arg_type.members:
|
||||||
assert not arg_type.variants
|
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
qov = qmp_output_visitor_new();
|
qov = qmp_output_visitor_new();
|
||||||
v = qmp_output_get_visitor(qov);
|
v = qmp_output_get_visitor(qov);
|
||||||
|
|
||||||
visit_start_struct(v, "%(name)s", NULL, 0, &err);
|
visit_start_struct(v, "%(name)s", NULL, 0, &err);
|
||||||
''',
|
if (err) {
|
||||||
name=name)
|
goto out;
|
||||||
ret += gen_err_check()
|
}
|
||||||
ret += gen_visit_members(arg_type.members, need_cast=True,
|
visit_type_%(c_name)s_members(v, ¶m, &err);
|
||||||
label='out_obj')
|
|
||||||
ret += mcgen('''
|
|
||||||
out_obj:
|
|
||||||
visit_end_struct(v, err ? NULL : &err);
|
visit_end_struct(v, err ? NULL : &err);
|
||||||
if (err) {
|
if (err) {
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
qdict_put_obj(qmp, "data", qmp_output_get_qobject(qov));
|
qdict_put_obj(qmp, "data", qmp_output_get_qobject(qov));
|
||||||
''')
|
''',
|
||||||
|
name=name, c_name=arg_type.c_name())
|
||||||
|
|
||||||
ret += mcgen('''
|
ret += mcgen('''
|
||||||
emit(%(c_enum)s, qmp, &err);
|
emit(%(c_enum)s, qmp, &err);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user