blob: eec5f1f4c5881f6213337146d20d8a7e7a15cbc7 [file] [log] [blame]
Michael Roth06d64c62011-07-19 14:50:41 -05001#
2# QAPI visitor generator
3#
4# Copyright IBM, Corp. 2011
Eric Blake6540e9f2015-04-10 15:07:59 -06005# Copyright (C) 2014-2015 Red Hat, Inc.
Michael Roth06d64c62011-07-19 14:50:41 -05006#
7# Authors:
8# Anthony Liguori <aliguori@us.ibm.com>
9# Michael Roth <mdroth@linux.vnet.ibm.com>
Markus Armbruster297a3642014-05-07 09:53:54 +020010# Markus Armbruster <armbru@redhat.com>
Michael Roth06d64c62011-07-19 14:50:41 -050011#
Markus Armbruster678e48a2014-03-01 08:40:34 +010012# This work is licensed under the terms of the GNU GPL, version 2.
13# See the COPYING file in the top-level directory.
Michael Roth06d64c62011-07-19 14:50:41 -050014
15from ordereddict import OrderedDict
16from qapi import *
Markus Armbruster297a3642014-05-07 09:53:54 +020017import re
Michael Roth06d64c62011-07-19 14:50:41 -050018
Markus Armbruster8c07edd2015-06-30 09:27:04 +020019implicit_structs_seen = set()
Markus Armbruster8c3f8e72015-06-26 10:19:11 +020020struct_fields_seen = set()
Markus Armbrusterbe3c7712014-05-07 09:53:50 +020021
22def generate_visit_implicit_struct(type):
Markus Armbruster8c07edd2015-06-30 09:27:04 +020023 if type in implicit_structs_seen:
Markus Armbrusterbe3c7712014-05-07 09:53:50 +020024 return ''
Markus Armbruster8c07edd2015-06-30 09:27:04 +020025 implicit_structs_seen.add(type)
Markus Armbruster8c3f8e72015-06-26 10:19:11 +020026 ret = ''
27 if type not in struct_fields_seen:
28 # Need a forward declaration
29 ret += mcgen('''
30
31static void visit_type_%(c_type)s_fields(Visitor *m, %(c_type)s **obj, Error **errp);
32''',
33 c_type=type_name(type))
34
35 ret += mcgen('''
Markus Armbrusterbe3c7712014-05-07 09:53:50 +020036
37static void visit_type_implicit_%(c_type)s(Visitor *m, %(c_type)s **obj, Error **errp)
38{
39 Error *err = NULL;
40
41 visit_start_implicit_struct(m, (void **)obj, sizeof(%(c_type)s), &err);
42 if (!err) {
Markus Armbruster297a3642014-05-07 09:53:54 +020043 visit_type_%(c_type)s_fields(m, obj, errp);
Markus Armbrusterbe3c7712014-05-07 09:53:50 +020044 visit_end_implicit_struct(m, &err);
45 }
46 error_propagate(errp, err);
47}
48''',
49 c_type=type_name(type))
Markus Armbruster8c3f8e72015-06-26 10:19:11 +020050 return ret
Markus Armbrusterbe3c7712014-05-07 09:53:50 +020051
Eric Blakea82b9822015-05-04 09:05:34 -060052def generate_visit_struct_fields(name, members, base = None):
Markus Armbruster8c3f8e72015-06-26 10:19:11 +020053 struct_fields_seen.add(name)
54
Kevin Wolfd131c892013-07-02 16:18:35 +020055 ret = ''
Kevin Wolf50f2bdc2013-07-03 15:58:57 +020056
Markus Armbrusterbe3c7712014-05-07 09:53:50 +020057 if base:
58 ret += generate_visit_implicit_struct(base)
59
Kevin Wolf50f2bdc2013-07-03 15:58:57 +020060 ret += mcgen('''
61
Eric Blakea82b9822015-05-04 09:05:34 -060062static void visit_type_%(name)s_fields(Visitor *m, %(name)s **obj, Error **errp)
Kevin Wolf50f2bdc2013-07-03 15:58:57 +020063{
64 Error *err = NULL;
65''',
Eric Blake83a02702015-05-14 06:50:57 -060066 name=c_name(name))
Kevin Wolf50f2bdc2013-07-03 15:58:57 +020067 push_indent()
Paolo Bonzinid1953252012-07-17 16:17:04 +020068
Kevin Wolf622f5572013-09-19 11:56:36 +020069 if base:
70 ret += mcgen('''
Eric Blakea82b9822015-05-04 09:05:34 -060071visit_type_implicit_%(type)s(m, &(*obj)->%(c_name)s, &err);
Markus Armbruster297a3642014-05-07 09:53:54 +020072if (err) {
73 goto out;
74}
Kevin Wolf622f5572013-09-19 11:56:36 +020075''',
Eric Blake18df5152015-05-14 06:50:48 -060076 type=type_name(base), c_name=c_name('base'))
Kevin Wolf622f5572013-09-19 11:56:36 +020077
Eric Blake6b5abc72015-05-04 09:05:33 -060078 for argname, argentry, optional in parse_args(members):
Michael Roth06d64c62011-07-19 14:50:41 -050079 if optional:
80 ret += mcgen('''
Eric Blakea82b9822015-05-04 09:05:34 -060081visit_optional(m, &(*obj)->has_%(c_name)s, "%(name)s", &err);
82if (!err && (*obj)->has_%(c_name)s) {
Michael Roth06d64c62011-07-19 14:50:41 -050083''',
Eric Blake18df5152015-05-14 06:50:48 -060084 c_name=c_name(argname), name=argname)
Michael Roth06d64c62011-07-19 14:50:41 -050085 push_indent()
86
Eric Blake6b5abc72015-05-04 09:05:33 -060087 ret += mcgen('''
Eric Blakea82b9822015-05-04 09:05:34 -060088visit_type_%(type)s(m, &(*obj)->%(c_name)s, "%(name)s", &err);
Michael Roth06d64c62011-07-19 14:50:41 -050089''',
Eric Blake18df5152015-05-14 06:50:48 -060090 type=type_name(argentry), c_name=c_name(argname),
Eric Blake6b5abc72015-05-04 09:05:33 -060091 name=argname)
Michael Roth06d64c62011-07-19 14:50:41 -050092
93 if optional:
94 pop_indent()
95 ret += mcgen('''
96}
Paolo Bonzinid1953252012-07-17 16:17:04 +020097''')
Markus Armbruster297a3642014-05-07 09:53:54 +020098 ret += mcgen('''
99if (err) {
100 goto out;
101}
102''')
Paolo Bonzinid1953252012-07-17 16:17:04 +0200103
Kevin Wolf50f2bdc2013-07-03 15:58:57 +0200104 pop_indent()
Markus Armbruster297a3642014-05-07 09:53:54 +0200105 if re.search('^ *goto out\\;', ret, re.MULTILINE):
106 ret += mcgen('''
Kevin Wolf50f2bdc2013-07-03 15:58:57 +0200107
Markus Armbruster297a3642014-05-07 09:53:54 +0200108out:
109''')
110 ret += mcgen('''
Kevin Wolf50f2bdc2013-07-03 15:58:57 +0200111 error_propagate(errp, err);
112}
113''')
Kevin Wolfd131c892013-07-02 16:18:35 +0200114 return ret
115
116
Markus Armbruster5aa05d32015-06-28 21:36:26 +0200117def generate_visit_struct_body(name):
Eric Blake2f52e202015-07-30 16:33:07 -0600118 # 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.
Kevin Wolfd131c892013-07-02 16:18:35 +0200122 ret = mcgen('''
Markus Armbruster297a3642014-05-07 09:53:54 +0200123 Error *err = NULL;
124
Eric Blake83a02702015-05-14 06:50:57 -0600125 visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(c_name)s), &err);
Markus Armbruster297a3642014-05-07 09:53:54 +0200126 if (!err) {
127 if (*obj) {
Eric Blake83a02702015-05-14 06:50:57 -0600128 visit_type_%(c_name)s_fields(m, obj, errp);
Markus Armbruster297a3642014-05-07 09:53:54 +0200129 }
130 visit_end_struct(m, &err);
Kevin Wolf50f2bdc2013-07-03 15:58:57 +0200131 }
Markus Armbruster297a3642014-05-07 09:53:54 +0200132 error_propagate(errp, err);
Kevin Wolf50f2bdc2013-07-03 15:58:57 +0200133''',
Eric Blake83a02702015-05-14 06:50:57 -0600134 name=name, c_name=c_name(name))
Kevin Wolfd131c892013-07-02 16:18:35 +0200135
Michael Roth06d64c62011-07-19 14:50:41 -0500136 return ret
137
Kevin Wolf14d36302013-09-18 17:22:02 +0200138def generate_visit_struct(expr):
139
Eric Blakefd41dd42015-05-04 09:05:25 -0600140 name = expr['struct']
Kevin Wolf14d36302013-09-18 17:22:02 +0200141 members = expr['data']
Kevin Wolf622f5572013-09-19 11:56:36 +0200142 base = expr.get('base')
Kevin Wolf14d36302013-09-18 17:22:02 +0200143
Eric Blakea82b9822015-05-04 09:05:34 -0600144 ret = generate_visit_struct_fields(name, members, base)
Kevin Wolf50f2bdc2013-07-03 15:58:57 +0200145
146 ret += mcgen('''
Michael Roth06d64c62011-07-19 14:50:41 -0500147
Amos Kong638ca8a2014-06-10 19:25:51 +0800148void visit_type_%(name)s(Visitor *m, %(name)s **obj, const char *name, Error **errp)
Michael Roth06d64c62011-07-19 14:50:41 -0500149{
Michael Roth06d64c62011-07-19 14:50:41 -0500150''',
Eric Blake83a02702015-05-14 06:50:57 -0600151 name=c_name(name))
Paolo Bonzinid1953252012-07-17 16:17:04 +0200152
Markus Armbruster5aa05d32015-06-28 21:36:26 +0200153 ret += generate_visit_struct_body(name)
Michael Roth06d64c62011-07-19 14:50:41 -0500154
155 ret += mcgen('''
Michael Roth06d64c62011-07-19 14:50:41 -0500156}
157''')
158 return ret
159
Markus Armbruster5aa05d32015-06-28 21:36:26 +0200160def generate_visit_list(name):
Michael Roth06d64c62011-07-19 14:50:41 -0500161 return mcgen('''
162
Amos Kong638ca8a2014-06-10 19:25:51 +0800163void visit_type_%(name)sList(Visitor *m, %(name)sList **obj, const char *name, Error **errp)
Michael Roth06d64c62011-07-19 14:50:41 -0500164{
Paolo Bonzinid1953252012-07-17 16:17:04 +0200165 Error *err = NULL;
Markus Armbruster297a3642014-05-07 09:53:54 +0200166 GenericList *i, **prev;
Michael Roth06d64c62011-07-19 14:50:41 -0500167
Markus Armbruster297a3642014-05-07 09:53:54 +0200168 visit_start_list(m, name, &err);
169 if (err) {
170 goto out;
Paolo Bonzinib6f04742012-03-22 12:51:06 +0100171 }
Markus Armbruster297a3642014-05-07 09:53:54 +0200172
173 for (prev = (GenericList **)obj;
174 !err && (i = visit_next_list(m, prev, &err)) != NULL;
175 prev = &i) {
176 %(name)sList *native_i = (%(name)sList *)i;
177 visit_type_%(name)s(m, &native_i->value, NULL, &err);
178 }
179
180 error_propagate(errp, err);
181 err = NULL;
182 visit_end_list(m, &err);
183out:
184 error_propagate(errp, err);
Michael Roth06d64c62011-07-19 14:50:41 -0500185}
186''',
Eric Blakefce384b2015-05-14 06:50:56 -0600187 name=type_name(name))
Michael Roth06d64c62011-07-19 14:50:41 -0500188
Markus Armbruster5aa05d32015-06-28 21:36:26 +0200189def generate_visit_enum(name):
Michael Roth06d64c62011-07-19 14:50:41 -0500190 return mcgen('''
191
Markus Armbruster40b3ade2015-06-26 17:21:42 +0200192void visit_type_%(c_name)s(Visitor *m, %(c_name)s *obj, const char *name, Error **errp)
Michael Roth06d64c62011-07-19 14:50:41 -0500193{
Markus Armbruster40b3ade2015-06-26 17:21:42 +0200194 visit_type_enum(m, (int *)obj, %(c_name)s_lookup, "%(name)s", name, errp);
Michael Roth06d64c62011-07-19 14:50:41 -0500195}
196''',
Markus Armbruster40b3ade2015-06-26 17:21:42 +0200197 c_name=c_name(name), name=name)
Michael Roth06d64c62011-07-19 14:50:41 -0500198
Eric Blake811d04f2015-05-04 09:05:10 -0600199def generate_visit_alternate(name, members):
Kevin Wolf69dd62d2013-07-08 16:14:21 +0200200 ret = mcgen('''
201
Amos Kong638ca8a2014-06-10 19:25:51 +0800202void visit_type_%(name)s(Visitor *m, %(name)s **obj, const char *name, Error **errp)
Kevin Wolf69dd62d2013-07-08 16:14:21 +0200203{
204 Error *err = NULL;
205
Markus Armbruster297a3642014-05-07 09:53:54 +0200206 visit_start_implicit_struct(m, (void**) obj, sizeof(%(name)s), &err);
207 if (err) {
208 goto out;
209 }
210 visit_get_next_type(m, (int*) &(*obj)->kind, %(name)s_qtypes, name, &err);
211 if (err) {
212 goto out_end;
213 }
214 switch ((*obj)->kind) {
Kevin Wolf69dd62d2013-07-08 16:14:21 +0200215''',
Eric Blaked1f07c82015-05-14 06:51:00 -0600216 name=c_name(name))
Kevin Wolf69dd62d2013-07-08 16:14:21 +0200217
Eric Blakeab916fa2015-05-04 09:05:13 -0600218 # For alternate, always use the default enum type automatically generated
Eric Blaked1f07c82015-05-14 06:51:00 -0600219 # as name + 'Kind'
220 disc_type = c_name(name) + 'Kind'
Wenchao Xiab0b58192014-03-04 18:44:36 -0800221
Kevin Wolf69dd62d2013-07-08 16:14:21 +0200222 for key in members:
Eric Blakeb52c4b92015-05-04 09:05:00 -0600223 assert (members[key] in builtin_types.keys()
Kevin Wolf69dd62d2013-07-08 16:14:21 +0200224 or find_struct(members[key])
Max Reitze775ba72014-08-20 19:59:34 +0200225 or find_union(members[key])
Eric Blakeab916fa2015-05-04 09:05:13 -0600226 or find_enum(members[key])), "Invalid alternate member"
Kevin Wolf69dd62d2013-07-08 16:14:21 +0200227
Markus Armbruster7c81c612015-05-14 06:50:50 -0600228 enum_full_value = c_enum_const(disc_type, key)
Kevin Wolf69dd62d2013-07-08 16:14:21 +0200229 ret += mcgen('''
Markus Armbruster297a3642014-05-07 09:53:54 +0200230 case %(enum_full_value)s:
231 visit_type_%(c_type)s(m, &(*obj)->%(c_name)s, name, &err);
232 break;
Kevin Wolf69dd62d2013-07-08 16:14:21 +0200233''',
Wenchao Xiab0b58192014-03-04 18:44:36 -0800234 enum_full_value = enum_full_value,
Kevin Wolf69dd62d2013-07-08 16:14:21 +0200235 c_type = type_name(members[key]),
Eric Blake18df5152015-05-14 06:50:48 -0600236 c_name = c_name(key))
Kevin Wolf69dd62d2013-07-08 16:14:21 +0200237
238 ret += mcgen('''
Markus Armbruster297a3642014-05-07 09:53:54 +0200239 default:
240 abort();
Kevin Wolf69dd62d2013-07-08 16:14:21 +0200241 }
Markus Armbruster297a3642014-05-07 09:53:54 +0200242out_end:
243 error_propagate(errp, err);
244 err = NULL;
245 visit_end_implicit_struct(m, &err);
246out:
247 error_propagate(errp, err);
Kevin Wolf69dd62d2013-07-08 16:14:21 +0200248}
249''')
250
251 return ret
252
253
Kevin Wolf0aef92b2013-07-02 16:20:04 +0200254def generate_visit_union(expr):
255
256 name = expr['union']
257 members = expr['data']
258
259 base = expr.get('base')
Kevin Wolf50f2bdc2013-07-03 15:58:57 +0200260 discriminator = expr.get('discriminator')
Kevin Wolf0aef92b2013-07-02 16:20:04 +0200261
Wenchao Xiabceae762014-03-06 17:08:56 -0800262 enum_define = discriminator_find_enum_define(expr)
263 if enum_define:
264 # Use the enum type as discriminator
265 ret = ""
Eric Blake857af5f2015-05-14 06:50:59 -0600266 disc_type = c_name(enum_define['enum_name'])
Wenchao Xiabceae762014-03-06 17:08:56 -0800267 else:
Eric Blakea8d4a2e2015-05-04 09:05:07 -0600268 # There will always be a discriminator in the C switch code, by default
Eric Blakebb337292015-05-14 06:50:58 -0600269 # it is an enum type generated silently
Markus Armbruster5aa05d32015-06-28 21:36:26 +0200270 ret = generate_visit_enum(name + 'Kind')
Eric Blakebb337292015-05-14 06:50:58 -0600271 disc_type = c_name(name) + 'Kind'
Michael Roth06d64c62011-07-19 14:50:41 -0500272
Kevin Wolf50f2bdc2013-07-03 15:58:57 +0200273 if base:
Eric Blakea8d4a2e2015-05-04 09:05:07 -0600274 assert discriminator
275 base_fields = find_struct(base)['data'].copy()
276 del base_fields[discriminator]
Eric Blakea82b9822015-05-04 09:05:34 -0600277 ret += generate_visit_struct_fields(name, base_fields)
Kevin Wolf50f2bdc2013-07-03 15:58:57 +0200278
Markus Armbrusterbe3c7712014-05-07 09:53:50 +0200279 if discriminator:
280 for key in members:
281 ret += generate_visit_implicit_struct(members[key])
282
Michael Roth06d64c62011-07-19 14:50:41 -0500283 ret += mcgen('''
284
Markus Armbruster40b3ade2015-06-26 17:21:42 +0200285void visit_type_%(c_name)s(Visitor *m, %(c_name)s **obj, const char *name, Error **errp)
Michael Roth06d64c62011-07-19 14:50:41 -0500286{
Paolo Bonzinidc8fb6d2012-03-06 18:55:56 +0100287 Error *err = NULL;
288
Markus Armbruster40b3ade2015-06-26 17:21:42 +0200289 visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(c_name)s), &err);
Markus Armbruster297a3642014-05-07 09:53:54 +0200290 if (err) {
291 goto out;
292 }
293 if (*obj) {
Michael Roth06d64c62011-07-19 14:50:41 -0500294''',
Markus Armbruster40b3ade2015-06-26 17:21:42 +0200295 c_name=c_name(name), name=name)
Michael Roth06d64c62011-07-19 14:50:41 -0500296
Kevin Wolf0aef92b2013-07-02 16:20:04 +0200297 if base:
Kevin Wolf50f2bdc2013-07-03 15:58:57 +0200298 ret += mcgen('''
Markus Armbruster468866b2014-05-07 09:53:47 +0200299 visit_type_%(name)s_fields(m, obj, &err);
Markus Armbruster297a3642014-05-07 09:53:54 +0200300 if (err) {
301 goto out_obj;
302 }
Kevin Wolf50f2bdc2013-07-03 15:58:57 +0200303''',
Eric Blake857af5f2015-05-14 06:50:59 -0600304 name=c_name(name))
Kevin Wolf0aef92b2013-07-02 16:20:04 +0200305
Richard Henderson7b75d9d2013-10-31 13:26:01 -0700306 if not discriminator:
Markus Armbruster0f61af32015-07-31 10:30:04 +0200307 tag = 'kind'
Wenchao Xiabceae762014-03-06 17:08:56 -0800308 disc_key = "type"
Richard Henderson7b75d9d2013-10-31 13:26:01 -0700309 else:
Markus Armbruster0f61af32015-07-31 10:30:04 +0200310 tag = discriminator
Wenchao Xiabceae762014-03-06 17:08:56 -0800311 disc_key = discriminator
Kevin Wolf0aef92b2013-07-02 16:20:04 +0200312 ret += mcgen('''
Markus Armbruster0f61af32015-07-31 10:30:04 +0200313 visit_type_%(disc_type)s(m, &(*obj)->%(c_tag)s, "%(disc_key)s", &err);
Markus Armbruster297a3642014-05-07 09:53:54 +0200314 if (err) {
315 goto out_obj;
316 }
Michael Rothcee2ded2014-09-18 15:36:40 -0500317 if (!visit_start_union(m, !!(*obj)->data, &err) || err) {
318 goto out_obj;
319 }
Markus Armbruster0f61af32015-07-31 10:30:04 +0200320 switch ((*obj)->%(c_tag)s) {
Kevin Wolf0aef92b2013-07-02 16:20:04 +0200321''',
Wenchao Xiabceae762014-03-06 17:08:56 -0800322 disc_type = disc_type,
Markus Armbruster0f61af32015-07-31 10:30:04 +0200323 c_tag=c_name(tag),
Wenchao Xiabceae762014-03-06 17:08:56 -0800324 disc_key = disc_key)
Kevin Wolf0aef92b2013-07-02 16:20:04 +0200325
Paolo Bonzinidc8fb6d2012-03-06 18:55:56 +0100326 for key in members:
Kevin Wolf50f2bdc2013-07-03 15:58:57 +0200327 if not discriminator:
328 fmt = 'visit_type_%(c_type)s(m, &(*obj)->%(c_name)s, "data", &err);'
329 else:
Markus Armbrusterbe3c7712014-05-07 09:53:50 +0200330 fmt = 'visit_type_implicit_%(c_type)s(m, &(*obj)->%(c_name)s, &err);'
Kevin Wolf50f2bdc2013-07-03 15:58:57 +0200331
Markus Armbruster7c81c612015-05-14 06:50:50 -0600332 enum_full_value = c_enum_const(disc_type, key)
Paolo Bonzinidc8fb6d2012-03-06 18:55:56 +0100333 ret += mcgen('''
Markus Armbruster297a3642014-05-07 09:53:54 +0200334 case %(enum_full_value)s:
335 ''' + fmt + '''
336 break;
Paolo Bonzinidc8fb6d2012-03-06 18:55:56 +0100337''',
Wenchao Xiab0b58192014-03-04 18:44:36 -0800338 enum_full_value = enum_full_value,
Michael Rothc664aef2013-05-10 17:46:01 -0500339 c_type=type_name(members[key]),
Eric Blake18df5152015-05-14 06:50:48 -0600340 c_name=c_name(key))
Paolo Bonzinidc8fb6d2012-03-06 18:55:56 +0100341
342 ret += mcgen('''
Markus Armbruster297a3642014-05-07 09:53:54 +0200343 default:
344 abort();
Paolo Bonzinid1953252012-07-17 16:17:04 +0200345 }
Markus Armbruster297a3642014-05-07 09:53:54 +0200346out_obj:
Paolo Bonzinid1953252012-07-17 16:17:04 +0200347 error_propagate(errp, err);
348 err = NULL;
Michael Rothcee2ded2014-09-18 15:36:40 -0500349 visit_end_union(m, !!(*obj)->data, &err);
350 error_propagate(errp, err);
351 err = NULL;
Markus Armbruster468866b2014-05-07 09:53:47 +0200352 }
Markus Armbruster297a3642014-05-07 09:53:54 +0200353 visit_end_struct(m, &err);
354out:
355 error_propagate(errp, err);
Paolo Bonzinidc8fb6d2012-03-06 18:55:56 +0100356}
357''')
358
Michael Roth06d64c62011-07-19 14:50:41 -0500359 return ret
360
Markus Armbruster5aa05d32015-06-28 21:36:26 +0200361def generate_declaration(name, builtin_type=False):
Michael Roth7c946bc2013-05-10 17:46:02 -0500362 ret = ""
363 if not builtin_type:
Eric Blake83a02702015-05-14 06:50:57 -0600364 name = c_name(name)
Michael Roth7c946bc2013-05-10 17:46:02 -0500365 ret += mcgen('''
Michael Roth06d64c62011-07-19 14:50:41 -0500366
Amos Kong638ca8a2014-06-10 19:25:51 +0800367void visit_type_%(name)s(Visitor *m, %(name)s **obj, const char *name, Error **errp);
Michael Roth06d64c62011-07-19 14:50:41 -0500368''',
Eric Blake6540e9f2015-04-10 15:07:59 -0600369 name=name)
Michael Roth06d64c62011-07-19 14:50:41 -0500370
Eric Blake6540e9f2015-04-10 15:07:59 -0600371 ret += mcgen('''
Amos Kong638ca8a2014-06-10 19:25:51 +0800372void visit_type_%(name)sList(Visitor *m, %(name)sList **obj, const char *name, Error **errp);
Michael Roth06d64c62011-07-19 14:50:41 -0500373''',
374 name=name)
375
376 return ret
377
Markus Armbruster5aa05d32015-06-28 21:36:26 +0200378def generate_enum_declaration(name):
Eric Blake6540e9f2015-04-10 15:07:59 -0600379 ret = mcgen('''
Amos Kong638ca8a2014-06-10 19:25:51 +0800380void visit_type_%(name)sList(Visitor *m, %(name)sList **obj, const char *name, Error **errp);
Amos Kongb9c4b482012-08-31 10:56:23 +0800381''',
Eric Blakefce384b2015-05-14 06:50:56 -0600382 name=c_name(name))
Amos Kongb9c4b482012-08-31 10:56:23 +0800383
384 return ret
385
Markus Armbruster5aa05d32015-06-28 21:36:26 +0200386def generate_decl_enum(name):
Michael Roth06d64c62011-07-19 14:50:41 -0500387 return mcgen('''
388
Amos Kong638ca8a2014-06-10 19:25:51 +0800389void visit_type_%(name)s(Visitor *m, %(name)s *obj, const char *name, Error **errp);
Michael Roth06d64c62011-07-19 14:50:41 -0500390''',
Eric Blakefce384b2015-05-14 06:50:56 -0600391 name=c_name(name))
Michael Roth06d64c62011-07-19 14:50:41 -0500392
Michael Roth7c946bc2013-05-10 17:46:02 -0500393do_builtins = False
Avi Kivity8d3bc512011-12-27 16:02:16 +0200394
Markus Armbruster2114f5a2015-04-02 13:12:21 +0200395(input_file, output_dir, do_c, do_h, prefix, opts) = \
396 parse_command_line("b", ["builtins"])
Avi Kivity8d3bc512011-12-27 16:02:16 +0200397
Markus Armbruster2114f5a2015-04-02 13:12:21 +0200398for o, a in opts:
399 if o in ("-b", "--builtins"):
400 do_builtins = True
Michael Roth06d64c62011-07-19 14:50:41 -0500401
Markus Armbruster12f8e1b2015-04-02 14:46:39 +0200402c_comment = '''
403/*
404 * schema-defined QAPI visitor functions
405 *
406 * Copyright IBM, Corp. 2011
407 *
408 * Authors:
409 * Anthony Liguori <aliguori@us.ibm.com>
410 *
411 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
412 * See the COPYING.LIB file in the top-level directory.
413 *
414 */
415'''
416h_comment = '''
417/*
418 * schema-defined QAPI visitor functions
419 *
420 * Copyright IBM, Corp. 2011
421 *
422 * Authors:
423 * Anthony Liguori <aliguori@us.ibm.com>
424 *
425 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
426 * See the COPYING.LIB file in the top-level directory.
427 *
428 */
429'''
Michael Roth06d64c62011-07-19 14:50:41 -0500430
Markus Armbruster12f8e1b2015-04-02 14:46:39 +0200431(fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix,
432 'qapi-visit.c', 'qapi-visit.h',
433 c_comment, h_comment)
Michael Roth06d64c62011-07-19 14:50:41 -0500434
435fdef.write(mcgen('''
Paolo Bonzini79ee7df2012-12-06 11:22:34 +0100436#include "qemu-common.h"
Markus Armbruster12f8e1b2015-04-02 14:46:39 +0200437#include "%(prefix)sqapi-visit.h"
Michael Roth06d64c62011-07-19 14:50:41 -0500438''',
Markus Armbruster12f8e1b2015-04-02 14:46:39 +0200439 prefix = prefix))
Michael Roth06d64c62011-07-19 14:50:41 -0500440
441fdecl.write(mcgen('''
Paolo Bonzini7b1b5d12012-12-17 18:19:43 +0100442#include "qapi/visitor.h"
Michael Roth06d64c62011-07-19 14:50:41 -0500443#include "%(prefix)sqapi-types.h"
Michael Roth7c946bc2013-05-10 17:46:02 -0500444
Michael Roth06d64c62011-07-19 14:50:41 -0500445''',
Markus Armbruster12f8e1b2015-04-02 14:46:39 +0200446 prefix=prefix))
Michael Roth06d64c62011-07-19 14:50:41 -0500447
LluĂ­s Vilanova33aaad52014-05-02 15:52:35 +0200448exprs = parse_schema(input_file)
Michael Roth06d64c62011-07-19 14:50:41 -0500449
Michael Roth7c946bc2013-05-10 17:46:02 -0500450# to avoid header dependency hell, we always generate declarations
451# for built-in types in our header files and simply guard them
452fdecl.write(guardstart("QAPI_VISIT_BUILTIN_VISITOR_DECL"))
Eric Blakeb52c4b92015-05-04 09:05:00 -0600453for typename in builtin_types.keys():
Markus Armbruster5aa05d32015-06-28 21:36:26 +0200454 fdecl.write(generate_declaration(typename, builtin_type=True))
Michael Roth7c946bc2013-05-10 17:46:02 -0500455fdecl.write(guardend("QAPI_VISIT_BUILTIN_VISITOR_DECL"))
456
457# ...this doesn't work for cases where we link in multiple objects that
458# have the functions defined, so we use -b option to provide control
459# over these cases
460if do_builtins:
Eric Blakeb52c4b92015-05-04 09:05:00 -0600461 for typename in builtin_types.keys():
Markus Armbruster5aa05d32015-06-28 21:36:26 +0200462 fdef.write(generate_visit_list(typename))
Michael Roth7c946bc2013-05-10 17:46:02 -0500463
Michael Roth06d64c62011-07-19 14:50:41 -0500464for expr in exprs:
Eric Blakefd41dd42015-05-04 09:05:25 -0600465 if expr.has_key('struct'):
Kevin Wolf14d36302013-09-18 17:22:02 +0200466 ret = generate_visit_struct(expr)
Markus Armbruster5aa05d32015-06-28 21:36:26 +0200467 ret += generate_visit_list(expr['struct'])
Michael Roth06d64c62011-07-19 14:50:41 -0500468 fdef.write(ret)
469
Markus Armbruster5aa05d32015-06-28 21:36:26 +0200470 ret = generate_declaration(expr['struct'])
Michael Roth06d64c62011-07-19 14:50:41 -0500471 fdecl.write(ret)
472 elif expr.has_key('union'):
Kevin Wolf0aef92b2013-07-02 16:20:04 +0200473 ret = generate_visit_union(expr)
Markus Armbruster5aa05d32015-06-28 21:36:26 +0200474 ret += generate_visit_list(expr['union'])
Michael Roth06d64c62011-07-19 14:50:41 -0500475 fdef.write(ret)
476
Wenchao Xiabceae762014-03-06 17:08:56 -0800477 enum_define = discriminator_find_enum_define(expr)
478 ret = ""
479 if not enum_define:
Markus Armbruster5aa05d32015-06-28 21:36:26 +0200480 ret = generate_decl_enum('%sKind' % expr['union'])
481 ret += generate_declaration(expr['union'])
Michael Roth06d64c62011-07-19 14:50:41 -0500482 fdecl.write(ret)
Eric Blakeab916fa2015-05-04 09:05:13 -0600483 elif expr.has_key('alternate'):
484 ret = generate_visit_alternate(expr['alternate'], expr['data'])
Markus Armbruster5aa05d32015-06-28 21:36:26 +0200485 ret += generate_visit_list(expr['alternate'])
Eric Blakeab916fa2015-05-04 09:05:13 -0600486 fdef.write(ret)
487
Markus Armbruster5aa05d32015-06-28 21:36:26 +0200488 ret = generate_decl_enum('%sKind' % expr['alternate'])
489 ret += generate_declaration(expr['alternate'])
Eric Blakeab916fa2015-05-04 09:05:13 -0600490 fdecl.write(ret)
Michael Roth06d64c62011-07-19 14:50:41 -0500491 elif expr.has_key('enum'):
Markus Armbruster5aa05d32015-06-28 21:36:26 +0200492 ret = generate_visit_list(expr['enum'])
493 ret += generate_visit_enum(expr['enum'])
Michael Roth06d64c62011-07-19 14:50:41 -0500494 fdef.write(ret)
495
Markus Armbruster5aa05d32015-06-28 21:36:26 +0200496 ret = generate_decl_enum(expr['enum'])
497 ret += generate_enum_declaration(expr['enum'])
Michael Roth06d64c62011-07-19 14:50:41 -0500498 fdecl.write(ret)
499
Markus Armbruster12f8e1b2015-04-02 14:46:39 +0200500close_output(fdef, fdecl)