mirror of
https://github.com/yuzu-emu/unicorn.git
synced 2025-01-22 23:01:02 +00:00
qapi: Consistent generated code: minimize push_indent() usage
We had some pointless differences in the generated code for visit, command marshalling, and events; unifying them makes it easier for future patches to consolidate to common helper functions. This is one patch of a series to clean up these differences. This patch reduces the number of push_indent()/pop_indent() pairs so that generated code is typically already at its natural output indentation in the python files. It is easier to reason about generated code if the reader does not have to track how much spacing will be inserted alongside the code, and moreso when all of the generators use the same patterns (qapi-type and qapi-event were already using in-place indentation). Arguably, the resulting python may be a bit harder to read with C code at the same indentation as python; on the other hand, not having to think about push_indent() is a win, and most decent editors provide syntax highlighting that makes it easier to visually distinguish python code from string literals that will become C code. There is no change to the generated output. Backports commit 05372f708a8cb3556e4d67458de79417dadf241f from qemu
This commit is contained in:
parent
ec89e19b30
commit
13b3a6c92f
|
@ -13,68 +13,52 @@
|
|||
|
||||
from qapi import *
|
||||
|
||||
def _generate_event_api_name(event_name, params):
|
||||
api_name = "void qapi_event_send_%s(" % c_name(event_name).lower();
|
||||
l = len(api_name)
|
||||
|
||||
if params:
|
||||
for m in params.members:
|
||||
if m.optional:
|
||||
api_name += "bool has_%s,\n" % c_name(m.name)
|
||||
api_name += "".ljust(l)
|
||||
|
||||
api_name += "%s %s,\n" % (m.type.c_type(is_param=True),
|
||||
c_name(m.name))
|
||||
api_name += "".ljust(l)
|
||||
|
||||
api_name += "Error **errp)"
|
||||
return api_name;
|
||||
def gen_event_send_proto(name, arg_type):
|
||||
return 'void qapi_event_send_%(c_name)s(%(param)s)' % {
|
||||
'c_name': c_name(name.lower()),
|
||||
'param': gen_params(arg_type, 'Error **errp')}
|
||||
|
||||
|
||||
# Following are the core functions that generate C APIs to emit event.
|
||||
|
||||
def generate_event_declaration(api_name):
|
||||
def gen_event_send_decl(name, arg_type):
|
||||
return mcgen('''
|
||||
|
||||
%(api_name)s;
|
||||
%(proto)s;
|
||||
''',
|
||||
api_name = api_name)
|
||||
proto=gen_event_send_proto(name, arg_type))
|
||||
|
||||
def generate_event_implement(api_name, event_name, params):
|
||||
# step 1: declare any variables
|
||||
ret = mcgen("""
|
||||
|
||||
%(api_name)s
|
||||
def gen_event_send(name, arg_type):
|
||||
ret = mcgen('''
|
||||
|
||||
%(proto)s
|
||||
{
|
||||
QDict *qmp;
|
||||
Error *err = NULL;
|
||||
QMPEventFuncEmit emit;
|
||||
""",
|
||||
api_name = api_name)
|
||||
''',
|
||||
proto=gen_event_send_proto(name, arg_type))
|
||||
|
||||
if params and params.members:
|
||||
ret += mcgen("""
|
||||
if arg_type and arg_type.members:
|
||||
ret += mcgen('''
|
||||
QmpOutputVisitor *qov;
|
||||
Visitor *v;
|
||||
QObject *obj;
|
||||
|
||||
""")
|
||||
''')
|
||||
|
||||
# step 2: check emit function, create a dict
|
||||
ret += mcgen("""
|
||||
ret += mcgen('''
|
||||
emit = qmp_event_get_func_emit();
|
||||
if (!emit) {
|
||||
return;
|
||||
}
|
||||
|
||||
qmp = qmp_event_build_dict("%(event_name)s");
|
||||
qmp = qmp_event_build_dict("%(name)s");
|
||||
|
||||
""",
|
||||
event_name = event_name)
|
||||
''',
|
||||
name=name)
|
||||
|
||||
# step 3: visit the params if params != None
|
||||
if params and params.members:
|
||||
ret += mcgen("""
|
||||
if arg_type and arg_type.members:
|
||||
ret += mcgen('''
|
||||
qov = qmp_output_visitor_new();
|
||||
g_assert(qov);
|
||||
|
||||
|
@ -82,46 +66,41 @@ def generate_event_implement(api_name, event_name, params):
|
|||
g_assert(v);
|
||||
|
||||
/* Fake visit, as if all members are under a structure */
|
||||
visit_start_struct(v, NULL, "", "%(event_name)s", 0, &err);
|
||||
if (err) {
|
||||
goto out;
|
||||
}
|
||||
visit_start_struct(v, NULL, "", "%(name)s", 0, &err);
|
||||
''',
|
||||
name=name)
|
||||
ret += gen_err_check()
|
||||
|
||||
""",
|
||||
event_name = event_name)
|
||||
|
||||
for memb in params.members:
|
||||
for memb in arg_type.members:
|
||||
if memb.optional:
|
||||
ret += mcgen("""
|
||||
if (has_%(var)s) {
|
||||
""",
|
||||
var=c_name(memb.name))
|
||||
ret += mcgen('''
|
||||
if (has_%(c_name)s) {
|
||||
''',
|
||||
c_name=c_name(memb.name))
|
||||
push_indent()
|
||||
|
||||
# Ugly: need to cast away the const
|
||||
if memb.type.name == "str":
|
||||
var_type = "(char **)"
|
||||
cast = '(char **)'
|
||||
else:
|
||||
var_type = ""
|
||||
cast = ''
|
||||
|
||||
ret += mcgen("""
|
||||
visit_type_%(type)s(v, %(var_type)s&%(var)s, "%(name)s", &err);
|
||||
if (err) {
|
||||
goto out;
|
||||
}
|
||||
""",
|
||||
var_type = var_type,
|
||||
var=c_name(memb.name),
|
||||
type=memb.type.c_name(),
|
||||
ret += mcgen('''
|
||||
visit_type_%(c_type)s(v, %(cast)s&%(c_name)s, "%(name)s", &err);
|
||||
''',
|
||||
cast=cast,
|
||||
c_name=c_name(memb.name),
|
||||
c_type=memb.type.c_name(),
|
||||
name=memb.name)
|
||||
ret += gen_err_check()
|
||||
|
||||
if memb.optional:
|
||||
pop_indent()
|
||||
ret += mcgen("""
|
||||
ret += mcgen('''
|
||||
}
|
||||
""")
|
||||
|
||||
ret += mcgen("""
|
||||
''')
|
||||
|
||||
ret += mcgen('''
|
||||
visit_end_struct(v, &err);
|
||||
if (err) {
|
||||
goto out;
|
||||
|
@ -131,27 +110,24 @@ def generate_event_implement(api_name, event_name, params):
|
|||
g_assert(obj != NULL);
|
||||
|
||||
qdict_put_obj(qmp, "data", obj);
|
||||
""")
|
||||
''')
|
||||
|
||||
# step 4: call qmp event api
|
||||
ret += mcgen("""
|
||||
emit(%(event_enum_value)s, qmp, &err);
|
||||
ret += mcgen('''
|
||||
emit(%(c_enum)s, qmp, &err);
|
||||
|
||||
""",
|
||||
event_enum_value = c_enum_const(event_enum_name, event_name))
|
||||
''',
|
||||
c_enum=c_enum_const(event_enum_name, name))
|
||||
|
||||
# step 5: clean up
|
||||
if params and params.members:
|
||||
ret += mcgen("""
|
||||
out:
|
||||
if arg_type and arg_type.members:
|
||||
ret += mcgen('''
|
||||
out:
|
||||
qmp_output_visitor_cleanup(qov);
|
||||
""")
|
||||
ret += mcgen("""
|
||||
''')
|
||||
ret += mcgen('''
|
||||
error_propagate(errp, err);
|
||||
QDECREF(qmp);
|
||||
}
|
||||
""")
|
||||
|
||||
''')
|
||||
return ret
|
||||
|
||||
|
||||
|
@ -167,14 +143,13 @@ class QAPISchemaGenEventVisitor(QAPISchemaVisitor):
|
|||
self._event_names = []
|
||||
|
||||
def visit_end(self):
|
||||
self.decl += generate_enum(event_enum_name, self._event_names)
|
||||
self.defn += generate_enum_lookup(event_enum_name, self._event_names)
|
||||
self._event_names = None
|
||||
self.decl += gen_enum(event_enum_name, self._event_names)
|
||||
self.defn += gen_enum_lookup(event_enum_name, self._event_names)
|
||||
self._event_names = None;
|
||||
|
||||
def visit_event(self, name, info, arg_type):
|
||||
api_name = _generate_event_api_name(name, arg_type)
|
||||
self.decl += generate_event_declaration(api_name)
|
||||
self.defn += generate_event_implement(api_name, name, arg_type)
|
||||
self.decl += gen_event_send_decl(name, arg_type)
|
||||
self.defn += gen_event_send(name, arg_type)
|
||||
self._event_names.append(name)
|
||||
|
||||
(input_file, output_dir, do_c, do_h, prefix, dummy) = parse_command_line()
|
||||
|
|
|
@ -75,28 +75,25 @@ static void visit_type_%(c_name)s_fields(Visitor *v, %(c_name)s **obj, Error **e
|
|||
|
||||
''',
|
||||
c_name=c_name(name))
|
||||
push_indent()
|
||||
|
||||
if base:
|
||||
ret += mcgen('''
|
||||
visit_type_implicit_%(c_type)s(v, &(*obj)->%(c_name)s, &err);
|
||||
if (err) {
|
||||
goto out;
|
||||
}
|
||||
visit_type_implicit_%(c_type)s(v, &(*obj)->%(c_name)s, &err);
|
||||
''',
|
||||
c_type=base.c_name(), c_name=c_name('base'))
|
||||
ret += gen_err_check()
|
||||
|
||||
for memb in members:
|
||||
if memb.optional:
|
||||
ret += mcgen('''
|
||||
visit_optional(v, &(*obj)->has_%(c_name)s, "%(name)s", &err);
|
||||
if (!err && (*obj)->has_%(c_name)s) {
|
||||
visit_optional(v, &(*obj)->has_%(c_name)s, "%(name)s", &err);
|
||||
if (!err && (*obj)->has_%(c_name)s) {
|
||||
''',
|
||||
c_name=c_name(memb.name), name=memb.name)
|
||||
push_indent()
|
||||
|
||||
ret += mcgen('''
|
||||
visit_type_%(c_type)s(v, &(*obj)->%(c_name)s, "%(name)s", &err);
|
||||
visit_type_%(c_type)s(v, &(*obj)->%(c_name)s, "%(name)s", &err);
|
||||
''',
|
||||
c_type=memb.type.c_name(), c_name=c_name(memb.name),
|
||||
name=memb.name)
|
||||
|
@ -104,15 +101,10 @@ visit_type_%(c_type)s(v, &(*obj)->%(c_name)s, "%(name)s", &err);
|
|||
if memb.optional:
|
||||
pop_indent()
|
||||
ret += mcgen('''
|
||||
}
|
||||
''')
|
||||
ret += mcgen('''
|
||||
if (err) {
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
''')
|
||||
ret += gen_err_check()
|
||||
|
||||
pop_indent()
|
||||
if re.search('^ *goto out;', ret, re.MULTILINE):
|
||||
ret += mcgen('''
|
||||
|
||||
|
@ -271,11 +263,9 @@ void visit_type_%(c_name)s(Visitor *v, %(c_name)s **obj, const char *name, Error
|
|||
if base:
|
||||
ret += mcgen('''
|
||||
visit_type_%(c_name)s_fields(v, obj, &err);
|
||||
if (err) {
|
||||
goto out_obj;
|
||||
}
|
||||
''',
|
||||
c_name=c_name(name))
|
||||
ret += gen_err_check(label='out_obj')
|
||||
|
||||
tag_key = variants.tag_member.name
|
||||
if not variants.tag_name:
|
||||
|
|
|
@ -1531,6 +1531,18 @@ def gen_params(arg_type, extra):
|
|||
ret += sep + extra
|
||||
return ret
|
||||
|
||||
|
||||
def gen_err_check(err='err', label='out'):
|
||||
if not err:
|
||||
return ''
|
||||
return mcgen('''
|
||||
if (%(err)s) {
|
||||
goto %(label)s;
|
||||
}
|
||||
''',
|
||||
err=err, label=label)
|
||||
|
||||
|
||||
#
|
||||
# Common command line parsing
|
||||
#
|
||||
|
|
Loading…
Reference in a new issue