2 # QAPI visitor generator
4 # Copyright IBM, Corp. 2011
5 # Copyright (C) 2014-2015 Red Hat, Inc.
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()
21 def generate_visit_implicit_struct(type):
22 if type in implicit_structs_seen:
24 implicit_structs_seen.add(type)
26 if type.name not in struct_fields_seen:
27 # Need a forward declaration
30 static void visit_type_%(c_type)s_fields(Visitor *m, %(c_type)s **obj, Error **errp);
36 static void visit_type_implicit_%(c_type)s(Visitor *m, %(c_type)s **obj, Error **errp)
40 visit_start_implicit_struct(m, (void **)obj, sizeof(%(c_type)s), &err);
42 visit_type_%(c_type)s_fields(m, obj, errp);
43 visit_end_implicit_struct(m, &err);
45 error_propagate(errp, err);
51 def generate_visit_struct_fields(name, members, base = None):
52 struct_fields_seen.add(name)
57 ret += generate_visit_implicit_struct(base)
61 static void visit_type_%(name)s_fields(Visitor *m, %(name)s **obj, Error **errp)
71 visit_type_implicit_%(type)s(m, &(*obj)->%(c_name)s, &err);
76 type=base.c_name(), c_name=c_name('base'))
81 visit_optional(m, &(*obj)->has_%(c_name)s, "%(name)s", &err);
82 if (!err && (*obj)->has_%(c_name)s) {
84 c_name=c_name(memb.name), name=memb.name)
88 visit_type_%(type)s(m, &(*obj)->%(c_name)s, "%(name)s", &err);
90 type=memb.type.c_name(), c_name=c_name(memb.name),
105 if re.search('^ *goto out\\;', ret, re.MULTILINE):
111 error_propagate(errp, err);
117 def generate_visit_struct_body(name):
118 # FIXME: if *obj is NULL on entry, and visit_start_struct() assigns to
119 # *obj, but then visit_type_FOO_fields() fails, we should clean up *obj
120 # rather than leaving it non-NULL. As currently written, the caller must
121 # call qapi_free_FOO() to avoid a memory leak of the partial FOO.
125 visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(c_name)s), &err);
128 visit_type_%(c_name)s_fields(m, obj, errp);
130 visit_end_struct(m, &err);
132 error_propagate(errp, err);
134 name=name, c_name=c_name(name))
138 def gen_visit_struct(name, base, members):
139 ret = generate_visit_struct_fields(name, members, base)
143 void visit_type_%(name)s(Visitor *m, %(name)s **obj, const char *name, Error **errp)
148 ret += generate_visit_struct_body(name)
155 def gen_visit_list(name, element_type):
158 void visit_type_%(name)s(Visitor *m, %(name)s **obj, const char *name, Error **errp)
161 GenericList *i, **prev;
163 visit_start_list(m, name, &err);
168 for (prev = (GenericList **)obj;
169 !err && (i = visit_next_list(m, prev, &err)) != NULL;
171 %(name)s *native_i = (%(name)s *)i;
172 visit_type_%(c_elt_type)s(m, &native_i->value, NULL, &err);
175 error_propagate(errp, err);
177 visit_end_list(m, &err);
179 error_propagate(errp, err);
183 c_elt_type=element_type.c_name())
185 def generate_visit_enum(name):
188 void visit_type_%(c_name)s(Visitor *m, %(c_name)s *obj, const char *name, Error **errp)
190 visit_type_enum(m, (int *)obj, %(c_name)s_lookup, "%(name)s", name, errp);
193 c_name=c_name(name), name=name)
195 def gen_visit_alternate(name, variants):
198 void visit_type_%(name)s(Visitor *m, %(name)s **obj, const char *name, Error **errp)
202 visit_start_implicit_struct(m, (void**) obj, sizeof(%(name)s), &err);
206 visit_get_next_type(m, (int*) &(*obj)->kind, %(name)s_qtypes, name, &err);
210 switch ((*obj)->kind) {
214 for var in variants.variants:
215 enum_full_value = c_enum_const(variants.tag_member.type.name,
218 case %(enum_full_value)s:
219 visit_type_%(c_type)s(m, &(*obj)->%(c_name)s, name, &err);
222 enum_full_value = enum_full_value,
223 c_type=var.type.c_name(),
224 c_name=c_name(var.name))
231 error_propagate(errp, err);
233 visit_end_implicit_struct(m, &err);
235 error_propagate(errp, err);
241 def gen_visit_union(name, base, variants):
245 members = [m for m in base.members if m != variants.tag_member]
246 ret += generate_visit_struct_fields(name, members)
248 for var in variants.variants:
249 # Ugly special case for simple union TODO get rid of it
250 if not var.simple_union_type():
251 ret += generate_visit_implicit_struct(var.type)
255 void visit_type_%(c_name)s(Visitor *m, %(c_name)s **obj, const char *name, Error **errp)
259 visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(c_name)s), &err);
265 c_name=c_name(name), name=name)
269 visit_type_%(name)s_fields(m, obj, &err);
276 disc_key = variants.tag_member.name
277 if not variants.tag_name:
278 # we pointlessly use a different key for simple unions
281 visit_type_%(disc_type)s(m, &(*obj)->%(c_name)s, "%(disc_key)s", &err);
285 if (!visit_start_union(m, !!(*obj)->data, &err) || err) {
288 switch ((*obj)->%(c_name)s) {
290 disc_type=variants.tag_member.type.c_name(),
291 # TODO ugly special case for simple union
292 # Use same tag name in C as on the wire to get rid of
293 # it, then: c_name=c_name(variants.tag_member.name)
294 c_name=c_name(variants.tag_name or 'kind'),
297 for var in variants.variants:
298 # TODO ugly special case for simple union
299 simple_union_type = var.simple_union_type()
300 if simple_union_type:
301 fmt = 'visit_type_%(c_type)s(m, &(*obj)->%(c_name)s, "data", &err);'
303 fmt = 'visit_type_implicit_%(c_type)s(m, &(*obj)->%(c_name)s, &err);'
305 enum_full_value = c_enum_const(variants.tag_member.type.name, var.name)
307 case %(enum_full_value)s:
311 enum_full_value = enum_full_value,
312 c_type=(simple_union_type or var.type).c_name(),
313 c_name=c_name(var.name))
320 error_propagate(errp, err);
322 visit_end_union(m, !!(*obj)->data, &err);
323 error_propagate(errp, err);
326 visit_end_struct(m, &err);
328 error_propagate(errp, err);
334 def gen_visit_decl(name, scalar=False):
335 c_type = c_name(name) + ' *'
339 void visit_type_%(c_name)s(Visitor *m, %(c_type)sobj, const char *name, Error **errp);
341 c_name=c_name(name), c_type=c_type)
344 class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
350 def visit_begin(self, schema):
353 self._btin = guardstart('QAPI_VISIT_BUILTIN')
356 # To avoid header dependency hell, we always generate
357 # declarations for built-in types in our header files and
358 # simply guard them. See also do_builtins (command line
360 self._btin += guardend('QAPI_VISIT_BUILTIN')
361 self.decl = self._btin + self.decl
364 def visit_enum_type(self, name, info, values, prefix):
365 self.decl += gen_visit_decl(name, scalar=True)
366 self.defn += generate_visit_enum(name)
368 def visit_array_type(self, name, info, element_type):
369 decl = gen_visit_decl(name)
370 defn = gen_visit_list(name, element_type)
371 if isinstance(element_type, QAPISchemaBuiltinType):
379 def visit_object_type(self, name, info, base, members, variants):
381 self.decl += gen_visit_decl(name)
383 assert not members # not implemented
384 self.defn += gen_visit_union(name, base, variants)
386 self.defn += gen_visit_struct(name, base, members)
388 def visit_alternate_type(self, name, info, variants):
389 self.decl += gen_visit_decl(name)
390 self.defn += gen_visit_alternate(name, variants)
392 # If you link code generated from multiple schemata, you want only one
393 # instance of the code for built-in types. Generate it only when
394 # do_builtins, enabled by command line option -b. See also
395 # QAPISchemaGenVisitVisitor.visit_end().
398 (input_file, output_dir, do_c, do_h, prefix, opts) = \
399 parse_command_line("b", ["builtins"])
402 if o in ("-b", "--builtins"):
407 * schema-defined QAPI visitor functions
409 * Copyright IBM, Corp. 2011
414 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
415 * See the COPYING.LIB file in the top-level directory.
421 * schema-defined QAPI visitor functions
423 * Copyright IBM, Corp. 2011
428 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
429 * See the COPYING.LIB file in the top-level directory.
434 (fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix,
435 'qapi-visit.c', 'qapi-visit.h',
436 c_comment, h_comment)
439 #include "qemu-common.h"
440 #include "%(prefix)sqapi-visit.h"
444 fdecl.write(mcgen('''
445 #include "qapi/visitor.h"
446 #include "%(prefix)sqapi-types.h"
451 schema = QAPISchema(input_file)
452 gen = QAPISchemaGenVisitVisitor()
455 fdecl.write(gen.decl)
457 close_output(fdef, fdecl)