diff mbox

[v6,07/16] qapi-event: Utilize implicit struct visits

Message ID 1458254921-17042-8-git-send-email-eblake@redhat.com (mailing list archive)
State New, archived
Headers show

Commit Message

Eric Blake March 17, 2016, 10:48 p.m. UTC
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, &param, &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>

---
v6: split into two patches, move FIXME here from patch 6
v5: move qapi.py:gen_struct_init() to qapi-event.py:gen_param_var(),
improve commit message
v4: new patch
---
 scripts/qapi-event.py | 48 ++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 38 insertions(+), 10 deletions(-)
diff mbox

Patch

diff --git a/scripts/qapi-event.py b/scripts/qapi-event.py
index 27af206..9b5c5b5 100644
--- a/scripts/qapi-event.py
+++ b/scripts/qapi-event.py
@@ -28,7 +28,37 @@  def gen_event_send_decl(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):
+    # 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
@@ -43,10 +73,11 @@  def gen_event_send(name, arg_type):
         ret += mcgen('''
     QmpOutputVisitor *qov;
     Visitor *v;
-
 ''')
+        ret += gen_param_var(arg_type)

     ret += mcgen('''
+
     emit = qmp_event_get_func_emit();
     if (!emit) {
         return;
@@ -58,26 +89,23 @@  def gen_event_send(name, arg_type):
                  name=name)

     if arg_type and arg_type.members:
-        assert not arg_type.variants
         ret += mcgen('''
     qov = qmp_output_visitor_new();
     v = qmp_output_get_visitor(qov);

     visit_start_struct(v, "%(name)s", NULL, 0, &err);
-''',
-                     name=name)
-        ret += gen_err_check()
-        ret += gen_visit_members(arg_type.members, need_cast=True,
-                                 label='out_obj')
-        ret += mcgen('''
-out_obj:
+    if (err) {
+        goto out;
+    }
+    visit_type_%(c_name)s_members(v, &param, &err);
     visit_end_struct(v, err ? NULL : &err);
     if (err) {
         goto out;
     }

     qdict_put_obj(qmp, "data", qmp_output_get_qobject(qov));
-''')
+''',
+                     name=name, c_name=arg_type.c_name())

     ret += mcgen('''
     emit(%(c_enum)s, qmp, &err);