diff options
Diffstat (limited to 'scripts/qapi-visit.py')
-rw-r--r-- | scripts/qapi-visit.py | 95 |
1 files changed, 70 insertions, 25 deletions
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py index 597cca4b6..45ce3a957 100644 --- a/scripts/qapi-visit.py +++ b/scripts/qapi-visit.py @@ -7,8 +7,8 @@ # Anthony Liguori <aliguori@us.ibm.com> # Michael Roth <mdroth@linux.vnet.ibm.com> # -# This work is licensed under the terms of the GNU GPLv2. -# See the COPYING.LIB file in the top-level directory. +# This work is licensed under the terms of the GNU GPL, version 2. +# See the COPYING file in the top-level directory. from ordereddict import OrderedDict from qapi import * @@ -17,10 +17,13 @@ import os import getopt import errno -def generate_visit_struct_fields(name, field_prefix, fn_prefix, members): +def generate_visit_struct_fields(name, field_prefix, fn_prefix, members, base = None): substructs = [] ret = '' - full_name = name if not fn_prefix else "%s_%s" % (name, fn_prefix) + if not fn_prefix: + full_name = name + else: + full_name = "%s_%s" % (name, fn_prefix) for argname, argentry, optional, structured in parse_args(members): if structured: @@ -42,11 +45,24 @@ static void visit_type_%(full_name)s_fields(Visitor *m, %(name)s ** obj, Error * name=name, full_name=full_name) push_indent() + if base: + ret += mcgen(''' +visit_start_implicit_struct(m, (void**) &(*obj)->%(c_name)s, sizeof(%(type)s), &err); +if (!err) { + visit_type_%(type)s_fields(m, &(*obj)->%(c_prefix)s%(c_name)s, &err); + error_propagate(errp, err); + err = NULL; + visit_end_implicit_struct(m, &err); +} +''', + c_prefix=c_var(field_prefix), + type=type_name(base), c_name=c_var('base')) + for argname, argentry, optional, structured in parse_args(members): if optional: ret += mcgen(''' -visit_start_optional(m, obj ? &(*obj)->%(c_prefix)shas_%(c_name)s : NULL, "%(name)s", &err); -if (obj && (*obj)->%(prefix)shas_%(c_name)s) { +visit_start_optional(m, &(*obj)->%(c_prefix)shas_%(c_name)s, "%(name)s", &err); +if ((*obj)->%(prefix)shas_%(c_name)s) { ''', c_prefix=c_var(field_prefix), prefix=field_prefix, c_name=c_var(argname), name=argname) @@ -56,7 +72,7 @@ if (obj && (*obj)->%(prefix)shas_%(c_name)s) { ret += generate_visit_struct_body(full_name, argname, argentry) else: ret += mcgen(''' -visit_type_%(type)s(m, obj ? &(*obj)->%(c_prefix)s%(c_name)s : NULL, "%(name)s", &err); +visit_type_%(type)s(m, &(*obj)->%(c_prefix)s%(c_name)s, "%(name)s", &err); ''', c_prefix=c_var(field_prefix), prefix=field_prefix, type=type_name(argentry), c_name=c_var(argname), @@ -84,7 +100,10 @@ if (!error_is_set(errp)) { ''') push_indent() - full_name = name if not field_prefix else "%s_%s" % (field_prefix, name) + if not field_prefix: + full_name = name + else: + full_name = "%s_%s" % (field_prefix, name) if len(field_prefix): ret += mcgen(''' @@ -102,7 +121,7 @@ visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(name)s), &err); ret += mcgen(''' if (!err) { - if (!obj || *obj) { + if (*obj) { visit_type_%(name)s_fields(m, obj, &err); error_propagate(errp, err); err = NULL; @@ -120,8 +139,13 @@ if (!err) { ''') return ret -def generate_visit_struct(name, members): - ret = generate_visit_struct_fields(name, "", "", members) +def generate_visit_struct(expr): + + name = expr['type'] + members = expr['data'] + base = expr.get('base') + + ret = generate_visit_struct_fields(name, "", "", members, base) ret += mcgen(''' @@ -190,18 +214,22 @@ void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error ** ''', name=name) + # For anon union, always use the default enum type automatically generated + # as "'%sKind' % (name)" + disc_type = '%sKind' % (name) + for key in members: assert (members[key] in builtin_types or find_struct(members[key]) or find_union(members[key])), "Invalid anonymous union member" + enum_full_value = generate_enum_full_value(disc_type, key) ret += mcgen(''' - case %(abbrev)s_KIND_%(enum)s: + case %(enum_full_value)s: visit_type_%(c_type)s(m, &(*obj)->%(c_name)s, name, &err); break; ''', - abbrev = de_camel_case(name).upper(), - enum = c_fun(de_camel_case(key),False).upper(), + enum_full_value = enum_full_value, c_type = type_name(members[key]), c_name = c_fun(key)) @@ -231,7 +259,16 @@ def generate_visit_union(expr): assert not base return generate_visit_anon_union(name, members) - ret = generate_visit_enum('%sKind' % name, members.keys()) + enum_define = discriminator_find_enum_define(expr) + if enum_define: + # Use the enum type as discriminator + ret = "" + disc_type = enum_define['enum_name'] + else: + # There will always be a discriminator in the C switch code, by default it + # is an enum type generated silently as "'%sKind' % (name)" + ret = generate_visit_enum('%sKind' % name, members.keys()) + disc_type = '%sKind' % (name) if base: base_fields = find_struct(base)['data'] @@ -249,7 +286,7 @@ void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error ** if (!error_is_set(errp)) { visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(name)s), &err); if (!err) { - if (obj && *obj) { + if (*obj) { ''', name=name) @@ -265,12 +302,18 @@ void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error ** name=name) pop_indent() + + if not discriminator: + disc_key = "type" + else: + disc_key = discriminator ret += mcgen(''' - visit_type_%(name)sKind(m, &(*obj)->kind, "%(type)s", &err); + visit_type_%(disc_type)s(m, &(*obj)->kind, "%(disc_key)s", &err); if (!err) { switch ((*obj)->kind) { ''', - name=name, type="type" if not discriminator else discriminator) + disc_type = disc_type, + disc_key = disc_key) for key in members: if not discriminator: @@ -284,13 +327,13 @@ void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error ** visit_end_implicit_struct(m, &err); }''' + enum_full_value = generate_enum_full_value(disc_type, key) ret += mcgen(''' - case %(abbrev)s_KIND_%(enum)s: + case %(enum_full_value)s: ''' + fmt + ''' break; ''', - abbrev = de_camel_case(name).upper(), - enum = c_fun(de_camel_case(key),False).upper(), + enum_full_value = enum_full_value, c_type=type_name(members[key]), c_name=c_fun(key)) @@ -465,14 +508,12 @@ fdecl.write(guardend("QAPI_VISIT_BUILTIN_VISITOR_DECL")) # have the functions defined, so we use -b option to provide control # over these cases if do_builtins: - fdef.write(guardstart("QAPI_VISIT_BUILTIN_VISITOR_DEF")) for typename in builtin_types: fdef.write(generate_visit_list(typename, None)) - fdef.write(guardend("QAPI_VISIT_BUILTIN_VISITOR_DEF")) for expr in exprs: if expr.has_key('type'): - ret = generate_visit_struct(expr['type'], expr['data']) + ret = generate_visit_struct(expr) ret += generate_visit_list(expr['type'], expr['data']) fdef.write(ret) @@ -483,7 +524,11 @@ for expr in exprs: ret += generate_visit_list(expr['union'], expr['data']) fdef.write(ret) - ret = generate_decl_enum('%sKind' % expr['union'], expr['data'].keys()) + enum_define = discriminator_find_enum_define(expr) + ret = "" + if not enum_define: + ret = generate_decl_enum('%sKind' % expr['union'], + expr['data'].keys()) ret += generate_declaration(expr['union'], expr['data']) fdecl.write(ret) elif expr.has_key('enum'): |