2 # QAPI visitor generator
4 # Copyright IBM, Corp. 2011
5 # Copyright (C) 2014-2015 Red Hat, Inc.
8 # Anthony Liguori <aliguori@us.ibm.com>
9 # Michael Roth <mdroth@linux.vnet.ibm.com>
10 # Markus Armbruster <armbru@redhat.com>
12 # This work is licensed under the terms of the GNU GPL, version 2.
13 # See the COPYING file in the top-level directory.
18 implicit_structs_seen
= set()
19 struct_fields_seen
= set()
22 def gen_visit_decl(name
, scalar
=False):
23 c_type
= c_name(name
) + ' *'
27 void visit_type_%(c_name)s(Visitor *v, %(c_type)sobj, const char *name, Error **errp);
29 c_name
=c_name(name
), c_type
=c_type
)
32 def gen_visit_implicit_struct(typ
):
33 if typ
in implicit_structs_seen
:
35 implicit_structs_seen
.add(typ
)
38 if typ
.name
not in struct_fields_seen
:
39 # Need a forward declaration
42 static void visit_type_%(c_type)s_fields(Visitor *v, %(c_type)s **obj, Error **errp);
48 static void visit_type_implicit_%(c_type)s(Visitor *v, %(c_type)s **obj, Error **errp)
52 visit_start_implicit_struct(v, (void **)obj, sizeof(%(c_type)s), &err);
54 visit_type_%(c_type)s_fields(v, obj, errp);
55 visit_end_implicit_struct(v, &err);
57 error_propagate(errp, err);
64 def gen_visit_struct_fields(name
, base
, members
):
65 struct_fields_seen
.add(name
)
70 ret
+= gen_visit_implicit_struct(base
)
74 static void visit_type_%(c_name)s_fields(Visitor *v, %(c_name)s **obj, Error **errp)
83 visit_type_implicit_%(c_type)s(v, &(*obj)->%(c_name)s, &err);
85 c_type
=base
.c_name(), c_name
=c_name('base'))
86 ret
+= gen_err_check()
88 ret
+= gen_visit_fields(members
, prefix
='(*obj)->')
90 if re
.search('^ *goto out;', ret
, re
.MULTILINE
):
96 error_propagate(errp, err);
102 def gen_visit_struct(name
, base
, members
):
103 ret
= gen_visit_struct_fields(name
, base
, members
)
105 # FIXME: if *obj is NULL on entry, and visit_start_struct() assigns to
106 # *obj, but then visit_type_FOO_fields() fails, we should clean up *obj
107 # rather than leaving it non-NULL. As currently written, the caller must
108 # call qapi_free_FOO() to avoid a memory leak of the partial FOO.
111 void visit_type_%(c_name)s(Visitor *v, %(c_name)s **obj, const char *name, Error **errp)
115 visit_start_struct(v, (void **)obj, "%(name)s", name, sizeof(%(c_name)s), &err);
118 visit_type_%(c_name)s_fields(v, obj, errp);
120 visit_end_struct(v, &err);
122 error_propagate(errp, err);
125 name
=name
, c_name
=c_name(name
))
130 def gen_visit_list(name
, element_type
):
133 void visit_type_%(c_name)s(Visitor *v, %(c_name)s **obj, const char *name, Error **errp)
136 GenericList *i, **prev;
138 visit_start_list(v, name, &err);
143 for (prev = (GenericList **)obj;
144 !err && (i = visit_next_list(v, prev, &err)) != NULL;
146 %(c_name)s *native_i = (%(c_name)s *)i;
147 visit_type_%(c_elt_type)s(v, &native_i->value, NULL, &err);
150 error_propagate(errp, err);
152 visit_end_list(v, &err);
154 error_propagate(errp, err);
157 c_name
=c_name(name
), c_elt_type
=element_type
.c_name())
160 def gen_visit_enum(name
):
163 void visit_type_%(c_name)s(Visitor *v, %(c_name)s *obj, const char *name, Error **errp)
165 visit_type_enum(v, (int *)obj, %(c_name)s_lookup, "%(name)s", name, errp);
168 c_name
=c_name(name
), name
=name
)
171 def gen_visit_alternate(name
, variants
):
174 void visit_type_%(c_name)s(Visitor *v, %(c_name)s **obj, const char *name, Error **errp)
178 visit_start_implicit_struct(v, (void**) obj, sizeof(%(c_name)s), &err);
182 visit_get_next_type(v, (int*) &(*obj)->kind, %(c_name)s_qtypes, name, &err);
186 switch ((*obj)->kind) {
190 for var
in variants
.variants
:
193 visit_type_%(c_type)s(v, &(*obj)->%(c_name)s, name, &err);
196 case
=c_enum_const(variants
.tag_member
.type.name
,
198 c_type
=var
.type.c_name(),
199 c_name
=c_name(var
.name
))
206 error_propagate(errp, err);
208 visit_end_implicit_struct(v, &err);
210 error_propagate(errp, err);
217 def gen_visit_union(name
, base
, variants
):
221 members
= [m
for m
in base
.members
if m
!= variants
.tag_member
]
222 ret
+= gen_visit_struct_fields(name
, None, members
)
224 for var
in variants
.variants
:
225 # Ugly special case for simple union TODO get rid of it
226 if not var
.simple_union_type():
227 ret
+= gen_visit_implicit_struct(var
.type)
231 void visit_type_%(c_name)s(Visitor *v, %(c_name)s **obj, const char *name, Error **errp)
235 visit_start_struct(v, (void **)obj, "%(name)s", name, sizeof(%(c_name)s), &err);
243 c_name
=c_name(name
), name
=name
)
247 visit_type_%(c_name)s_fields(v, obj, &err);
250 ret
+= gen_err_check(label
='out_obj')
252 tag_key
= variants
.tag_member
.name
253 if not variants
.tag_name
:
254 # we pointlessly use a different key for simple unions
257 visit_type_%(c_type)s(v, &(*obj)->%(c_name)s, "%(name)s", &err);
261 if (!visit_start_union(v, !!(*obj)->data, &err) || err) {
264 switch ((*obj)->%(c_name)s) {
266 c_type
=variants
.tag_member
.type.c_name(),
267 # TODO ugly special case for simple union
268 # Use same tag name in C as on the wire to get rid of
269 # it, then: c_name=c_name(variants.tag_member.name)
270 c_name
=c_name(variants
.tag_name
or 'kind'),
273 for var
in variants
.variants
:
274 # TODO ugly special case for simple union
275 simple_union_type
= var
.simple_union_type()
279 case
=c_enum_const(variants
.tag_member
.type.name
,
281 if simple_union_type
:
283 visit_type_%(c_type)s(v, &(*obj)->%(c_name)s, "data", &err);
285 c_type
=simple_union_type
.c_name(),
286 c_name
=c_name(var
.name
))
289 visit_type_implicit_%(c_type)s(v, &(*obj)->%(c_name)s, &err);
291 c_type
=var
.type.c_name(),
292 c_name
=c_name(var
.name
))
302 error_propagate(errp, err);
305 visit_end_union(v, !!(*obj)->data, &err);
307 error_propagate(errp, err);
309 visit_end_struct(v, &err);
311 error_propagate(errp, err);
318 class QAPISchemaGenVisitVisitor(QAPISchemaVisitor
):
324 def visit_begin(self
, schema
):
327 self
._btin
= guardstart('QAPI_VISIT_BUILTIN')
330 # To avoid header dependency hell, we always generate
331 # declarations for built-in types in our header files and
332 # simply guard them. See also do_builtins (command line
334 self
._btin
+= guardend('QAPI_VISIT_BUILTIN')
335 self
.decl
= self
._btin
+ self
.decl
338 def visit_needed(self
, entity
):
339 # Visit everything except implicit objects
340 return not (entity
.is_implicit() and
341 isinstance(entity
, QAPISchemaObjectType
))
343 def visit_enum_type(self
, name
, info
, values
, prefix
):
344 self
.decl
+= gen_visit_decl(name
, scalar
=True)
345 self
.defn
+= gen_visit_enum(name
)
347 def visit_array_type(self
, name
, info
, element_type
):
348 decl
= gen_visit_decl(name
)
349 defn
= gen_visit_list(name
, element_type
)
350 if isinstance(element_type
, QAPISchemaBuiltinType
):
358 def visit_object_type(self
, name
, info
, base
, members
, variants
):
359 self
.decl
+= gen_visit_decl(name
)
361 assert not members
# not implemented
362 self
.defn
+= gen_visit_union(name
, base
, variants
)
364 self
.defn
+= gen_visit_struct(name
, base
, members
)
366 def visit_alternate_type(self
, name
, info
, variants
):
367 self
.decl
+= gen_visit_decl(name
)
368 self
.defn
+= gen_visit_alternate(name
, variants
)
370 # If you link code generated from multiple schemata, you want only one
371 # instance of the code for built-in types. Generate it only when
372 # do_builtins, enabled by command line option -b. See also
373 # QAPISchemaGenVisitVisitor.visit_end().
376 (input_file
, output_dir
, do_c
, do_h
, prefix
, opts
) = \
377 parse_command_line("b", ["builtins"])
380 if o
in ("-b", "--builtins"):
385 * schema-defined QAPI visitor functions
387 * Copyright IBM, Corp. 2011
390 * Anthony Liguori <aliguori@us.ibm.com>
392 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
393 * See the COPYING.LIB file in the top-level directory.
399 * schema-defined QAPI visitor functions
401 * Copyright IBM, Corp. 2011
404 * Anthony Liguori <aliguori@us.ibm.com>
406 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
407 * See the COPYING.LIB file in the top-level directory.
412 (fdef
, fdecl
) = open_output(output_dir
, do_c
, do_h
, prefix
,
413 'qapi-visit.c', 'qapi-visit.h',
414 c_comment
, h_comment
)
417 #include "qemu-common.h"
418 #include "%(prefix)sqapi-visit.h"
422 fdecl
.write(mcgen('''
423 #include "qapi/visitor.h"
424 #include "%(prefix)sqapi-types.h"
429 schema
= QAPISchema(input_file
)
430 gen
= QAPISchemaGenVisitVisitor()
433 fdecl
.write(gen
.decl
)
435 close_output(fdef
, fdecl
)