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