blob: e13bbe42925fc6f43465170529b4e545675ca859 [file] [log] [blame]
Markus Armbruster5ddeec82018-02-11 10:35:41 +01001"""
2QAPI visitor generator
3
4Copyright IBM, Corp. 2011
5Copyright (C) 2014-2018 Red Hat, Inc.
6
7Authors:
8 Anthony Liguori <aliguori@us.ibm.com>
9 Michael Roth <mdroth@linux.vnet.ibm.com>
10 Markus Armbruster <armbru@redhat.com>
11
12This work is licensed under the terms of the GNU GPL, version 2.
13See the COPYING file in the top-level directory.
14"""
Michael Roth06d64c62011-07-19 14:50:41 -050015
Marc-André Lureauf17539c2021-08-04 12:30:57 +040016from typing import List, Optional
John Snowb4c0aa52020-10-09 12:15:58 -040017
John Snow5af82632020-10-09 12:15:28 -040018from .common import (
19 c_enum_const,
20 c_name,
John Snowcbe8f872020-10-09 12:15:33 -040021 indent,
John Snow5af82632020-10-09 12:15:28 -040022 mcgen,
John Snow5af82632020-10-09 12:15:28 -040023)
Markus Armbrustera1307282021-10-28 12:25:16 +020024from .gen import QAPISchemaModularCVisitor, gen_special_features, ifcontext
John Snowb4c0aa52020-10-09 12:15:58 -040025from .schema import (
26 QAPISchema,
27 QAPISchemaEnumMember,
28 QAPISchemaEnumType,
29 QAPISchemaFeature,
Marc-André Lureauf17539c2021-08-04 12:30:57 +040030 QAPISchemaIfCond,
John Snowb4c0aa52020-10-09 12:15:58 -040031 QAPISchemaObjectType,
32 QAPISchemaObjectTypeMember,
33 QAPISchemaType,
34 QAPISchemaVariants,
35)
36from .source import QAPISourceInfo
Michael Roth06d64c62011-07-19 14:50:41 -050037
Markus Armbrustere98859a2015-09-16 13:06:16 +020038
John Snowb4c0aa52020-10-09 12:15:58 -040039def gen_visit_decl(name: str, scalar: bool = False) -> str:
Markus Armbruster60f85462015-09-16 13:06:17 +020040 c_type = c_name(name) + ' *'
41 if not scalar:
42 c_type += '*'
43 return mcgen('''
John Snow42c0dd12020-10-09 12:15:30 -040044
45bool visit_type_%(c_name)s(Visitor *v, const char *name,
46 %(c_type)sobj, Error **errp);
Markus Armbruster60f85462015-09-16 13:06:17 +020047''',
48 c_name=c_name(name), c_type=c_type)
49
50
John Snowb4c0aa52020-10-09 12:15:58 -040051def gen_visit_members_decl(name: str) -> str:
Eric Blake2208d642016-02-17 23:48:25 -070052 return mcgen('''
Markus Armbruster8c3f8e72015-06-26 10:19:11 +020053
Markus Armbruster012d4c92020-07-07 18:05:45 +020054bool visit_type_%(c_name)s_members(Visitor *v, %(c_name)s *obj, Error **errp);
Markus Armbruster8c3f8e72015-06-26 10:19:11 +020055''',
Eric Blake4d91e912016-03-03 09:16:45 -070056 c_name=c_name(name))
Eric Blaked02cf372015-10-26 16:34:46 -060057
58
John Snowb4c0aa52020-10-09 12:15:58 -040059def gen_visit_object_members(name: str,
60 base: Optional[QAPISchemaObjectType],
61 members: List[QAPISchemaObjectTypeMember],
62 variants: Optional[QAPISchemaVariants]) -> str:
Eric Blake4d91e912016-03-03 09:16:45 -070063 ret = mcgen('''
Kevin Wolf50f2bdc2013-07-03 15:58:57 +020064
Markus Armbruster012d4c92020-07-07 18:05:45 +020065bool visit_type_%(c_name)s_members(Visitor *v, %(c_name)s *obj, Error **errp)
Kevin Wolf50f2bdc2013-07-03 15:58:57 +020066{
Kevin Wolf50f2bdc2013-07-03 15:58:57 +020067''',
Eric Blake4d91e912016-03-03 09:16:45 -070068 c_name=c_name(name))
Paolo Bonzinid1953252012-07-17 16:17:04 +020069
Kevin Wolf622f5572013-09-19 11:56:36 +020070 if base:
71 ret += mcgen('''
Markus Armbruster012d4c92020-07-07 18:05:45 +020072 if (!visit_type_%(c_type)s_members(v, (%(c_type)s *)obj, errp)) {
73 return false;
Eric Blakefa274ed2016-07-13 21:50:17 -060074 }
Kevin Wolf622f5572013-09-19 11:56:36 +020075''',
Eric Blakeddf21902015-10-26 16:34:49 -060076 c_type=base.c_name())
Kevin Wolf622f5572013-09-19 11:56:36 +020077
Eric Blake12f254f2016-03-17 16:48:35 -060078 for memb in members:
Markus Armbruster1889e572021-08-31 14:37:58 +020079 ret += memb.ifcond.gen_if()
Eric Blake12f254f2016-03-17 16:48:35 -060080 if memb.optional:
81 ret += mcgen('''
82 if (visit_optional(v, "%(name)s", &obj->has_%(c_name)s)) {
83''',
84 name=memb.name, c_name=c_name(memb.name))
John Snowcbe8f872020-10-09 12:15:33 -040085 indent.increase()
Markus Armbrustera1307282021-10-28 12:25:16 +020086 special_features = gen_special_features(memb.features)
87 if special_features != '0':
Markus Armbruster91fa93e2021-03-18 16:55:11 +010088 ret += mcgen('''
Markus Armbrustera1307282021-10-28 12:25:16 +020089 if (visit_policy_reject(v, "%(name)s", %(special_features)s, errp)) {
Markus Armbrusterdb291642021-03-18 16:55:18 +010090 return false;
91 }
Markus Armbrustera1307282021-10-28 12:25:16 +020092 if (!visit_policy_skip(v, "%(name)s", %(special_features)s)) {
Markus Armbruster91fa93e2021-03-18 16:55:11 +010093''',
Markus Armbrustera1307282021-10-28 12:25:16 +020094 name=memb.name, special_features=special_features)
Markus Armbruster91fa93e2021-03-18 16:55:11 +010095 indent.increase()
Eric Blake12f254f2016-03-17 16:48:35 -060096 ret += mcgen('''
Markus Armbruster012d4c92020-07-07 18:05:45 +020097 if (!visit_type_%(c_type)s(v, "%(name)s", &obj->%(c_name)s, errp)) {
98 return false;
Eric Blakefa274ed2016-07-13 21:50:17 -060099 }
Eric Blake12f254f2016-03-17 16:48:35 -0600100''',
101 c_type=memb.type.c_name(), name=memb.name,
102 c_name=c_name(memb.name))
Markus Armbrustera1307282021-10-28 12:25:16 +0200103 if special_features != '0':
Markus Armbruster91fa93e2021-03-18 16:55:11 +0100104 indent.decrease()
105 ret += mcgen('''
106 }
107''')
Eric Blake12f254f2016-03-17 16:48:35 -0600108 if memb.optional:
John Snowcbe8f872020-10-09 12:15:33 -0400109 indent.decrease()
Eric Blake12f254f2016-03-17 16:48:35 -0600110 ret += mcgen('''
111 }
112''')
Markus Armbruster1889e572021-08-31 14:37:58 +0200113 ret += memb.ifcond.gen_endif()
Paolo Bonzinid1953252012-07-17 16:17:04 +0200114
Eric Blake9a5cd422016-02-17 23:48:20 -0700115 if variants:
John Snow554df4f2020-10-09 12:15:56 -0400116 tag_member = variants.tag_member
117 assert isinstance(tag_member.type, QAPISchemaEnumType)
118
Eric Blake9a5cd422016-02-17 23:48:20 -0700119 ret += mcgen('''
Eric Blake65551902016-02-17 23:48:22 -0700120 switch (obj->%(c_name)s) {
Eric Blake9a5cd422016-02-17 23:48:20 -0700121''',
John Snow554df4f2020-10-09 12:15:56 -0400122 c_name=c_name(tag_member.name))
Eric Blake9a5cd422016-02-17 23:48:20 -0700123
124 for var in variants.variants:
John Snow554df4f2020-10-09 12:15:56 -0400125 case_str = c_enum_const(tag_member.type.name, var.name,
126 tag_member.type.prefix)
Markus Armbruster1889e572021-08-31 14:37:58 +0200127 ret += var.ifcond.gen_if()
Anton Nefedov800877b2018-06-18 11:40:05 +0300128 if var.type.name == 'q_empty':
129 # valid variant and nothing to do
130 ret += mcgen('''
131 case %(case)s:
132 break;
133''',
134 case=case_str)
135 else:
136 ret += mcgen('''
Eric Blake9a5cd422016-02-17 23:48:20 -0700137 case %(case)s:
Markus Armbrustercdd2b222020-07-07 18:06:08 +0200138 return visit_type_%(c_type)s_members(v, &obj->u.%(c_name)s, errp);
Eric Blake9a5cd422016-02-17 23:48:20 -0700139''',
Anton Nefedov800877b2018-06-18 11:40:05 +0300140 case=case_str,
141 c_type=var.type.c_name(), c_name=c_name(var.name))
Eric Blake9a5cd422016-02-17 23:48:20 -0700142
Markus Armbruster1889e572021-08-31 14:37:58 +0200143 ret += var.ifcond.gen_endif()
Eric Blake9a5cd422016-02-17 23:48:20 -0700144 ret += mcgen('''
145 default:
146 abort();
147 }
148''')
149
Markus Armbruster297a3642014-05-07 09:53:54 +0200150 ret += mcgen('''
Markus Armbrustercdd2b222020-07-07 18:06:08 +0200151 return true;
Kevin Wolf50f2bdc2013-07-03 15:58:57 +0200152}
153''')
Kevin Wolfd131c892013-07-02 16:18:35 +0200154 return ret
155
156
John Snowb4c0aa52020-10-09 12:15:58 -0400157def gen_visit_list(name: str, element_type: QAPISchemaType) -> str:
Michael Roth06d64c62011-07-19 14:50:41 -0500158 return mcgen('''
159
John Snow42c0dd12020-10-09 12:15:30 -0400160bool visit_type_%(c_name)s(Visitor *v, const char *name,
161 %(c_name)s **obj, Error **errp)
Michael Roth06d64c62011-07-19 14:50:41 -0500162{
Markus Armbrustercdd2b222020-07-07 18:06:08 +0200163 bool ok = false;
Eric Blaked9f62dd2016-04-28 15:45:31 -0600164 %(c_name)s *tail;
165 size_t size = sizeof(**obj);
Michael Roth06d64c62011-07-19 14:50:41 -0500166
Markus Armbruster012d4c92020-07-07 18:05:45 +0200167 if (!visit_start_list(v, name, (GenericList **)obj, size, errp)) {
168 return false;
Paolo Bonzinib6f04742012-03-22 12:51:06 +0100169 }
Markus Armbruster297a3642014-05-07 09:53:54 +0200170
Eric Blaked9f62dd2016-04-28 15:45:31 -0600171 for (tail = *obj; tail;
172 tail = (%(c_name)s *)visit_next_list(v, (GenericList *)tail, size)) {
Markus Armbrustercdd2b222020-07-07 18:06:08 +0200173 if (!visit_type_%(c_elt_type)s(v, NULL, &tail->value, errp)) {
174 goto out_obj;
Eric Blaked9f62dd2016-04-28 15:45:31 -0600175 }
Markus Armbruster297a3642014-05-07 09:53:54 +0200176 }
177
Markus Armbrustercdd2b222020-07-07 18:06:08 +0200178 ok = visit_check_list(v, errp);
179out_obj:
Eric Blake1158bb22016-06-09 10:48:34 -0600180 visit_end_list(v, (void **)obj);
Markus Armbrustercdd2b222020-07-07 18:06:08 +0200181 if (!ok && visit_is_input(v)) {
Eric Blake68ab47e2016-04-28 15:45:32 -0600182 qapi_free_%(c_name)s(*obj);
183 *obj = NULL;
184 }
Markus Armbrustercdd2b222020-07-07 18:06:08 +0200185 return ok;
Michael Roth06d64c62011-07-19 14:50:41 -0500186}
187''',
Markus Armbrustere98859a2015-09-16 13:06:16 +0200188 c_name=c_name(name), c_elt_type=element_type.c_name())
Michael Roth06d64c62011-07-19 14:50:41 -0500189
Markus Armbrustere98859a2015-09-16 13:06:16 +0200190
John Snowb4c0aa52020-10-09 12:15:58 -0400191def gen_visit_enum(name: str) -> str:
Michael Roth06d64c62011-07-19 14:50:41 -0500192 return mcgen('''
193
John Snow42c0dd12020-10-09 12:15:30 -0400194bool visit_type_%(c_name)s(Visitor *v, const char *name,
195 %(c_name)s *obj, Error **errp)
Michael Roth06d64c62011-07-19 14:50:41 -0500196{
Eric Blake395a2332016-01-29 06:48:52 -0700197 int value = *obj;
Markus Armbruster012d4c92020-07-07 18:05:45 +0200198 bool ok = visit_type_enum(v, name, &value, &%(c_name)s_lookup, errp);
Eric Blake395a2332016-01-29 06:48:52 -0700199 *obj = value;
Markus Armbruster012d4c92020-07-07 18:05:45 +0200200 return ok;
Michael Roth06d64c62011-07-19 14:50:41 -0500201}
202''',
Eric Blake337283d2016-01-29 06:48:57 -0700203 c_name=c_name(name))
Michael Roth06d64c62011-07-19 14:50:41 -0500204
Markus Armbrustere98859a2015-09-16 13:06:16 +0200205
John Snowb4c0aa52020-10-09 12:15:58 -0400206def gen_visit_alternate(name: str, variants: QAPISchemaVariants) -> str:
Marc-André Lureau60390d22017-06-07 20:35:59 +0400207 ret = mcgen('''
Kevin Wolf69dd62d2013-07-08 16:14:21 +0200208
John Snow42c0dd12020-10-09 12:15:30 -0400209bool visit_type_%(c_name)s(Visitor *v, const char *name,
210 %(c_name)s **obj, Error **errp)
Kevin Wolf69dd62d2013-07-08 16:14:21 +0200211{
Markus Armbrustercdd2b222020-07-07 18:06:08 +0200212 bool ok = false;
Kevin Wolf69dd62d2013-07-08 16:14:21 +0200213
Markus Armbruster012d4c92020-07-07 18:05:45 +0200214 if (!visit_start_alternate(v, name, (GenericAlternate **)obj,
215 sizeof(**obj), errp)) {
216 return false;
Markus Armbruster297a3642014-05-07 09:53:54 +0200217 }
Eric Blake9b4e38f2016-06-15 11:37:51 -0600218 if (!*obj) {
Markus Armbruster8e08bf42020-04-24 10:43:29 +0200219 /* incomplete */
220 assert(visit_is_dealloc(v));
Markus Armbrustercdd2b222020-07-07 18:06:08 +0200221 ok = true;
Eric Blake9b4e38f2016-06-15 11:37:51 -0600222 goto out_obj;
223 }
Eric Blake150d0562015-10-26 16:34:52 -0600224 switch ((*obj)->type) {
Kevin Wolf69dd62d2013-07-08 16:14:21 +0200225''',
Markus Armbrusterb736e252018-06-21 10:35:51 +0200226 c_name=c_name(name))
Kevin Wolf69dd62d2013-07-08 16:14:21 +0200227
Markus Armbruster441cbac2015-09-16 13:06:10 +0200228 for var in variants.variants:
Markus Armbruster1889e572021-08-31 14:37:58 +0200229 ret += var.ifcond.gen_if()
Kevin Wolf69dd62d2013-07-08 16:14:21 +0200230 ret += mcgen('''
Markus Armbrustere98859a2015-09-16 13:06:16 +0200231 case %(case)s:
Kevin Wolf69dd62d2013-07-08 16:14:21 +0200232''',
Eric Blakebecceed2016-02-17 23:48:26 -0700233 case=var.type.alternate_qtype())
234 if isinstance(var.type, QAPISchemaObjectType):
235 ret += mcgen('''
Markus Armbrustercdd2b222020-07-07 18:06:08 +0200236 if (!visit_start_struct(v, name, NULL, 0, errp)) {
Eric Blakebecceed2016-02-17 23:48:26 -0700237 break;
238 }
Markus Armbrustercdd2b222020-07-07 18:06:08 +0200239 if (visit_type_%(c_type)s_members(v, &(*obj)->u.%(c_name)s, errp)) {
240 ok = visit_check_struct(v, errp);
Eric Blake15c2f662016-04-28 15:45:27 -0600241 }
Eric Blake1158bb22016-06-09 10:48:34 -0600242 visit_end_struct(v, NULL);
Eric Blakebecceed2016-02-17 23:48:26 -0700243''',
244 c_type=var.type.c_name(),
245 c_name=c_name(var.name))
246 else:
247 ret += mcgen('''
Markus Armbrustercdd2b222020-07-07 18:06:08 +0200248 ok = visit_type_%(c_type)s(v, name, &(*obj)->u.%(c_name)s, errp);
Eric Blakebecceed2016-02-17 23:48:26 -0700249''',
250 c_type=var.type.c_name(),
251 c_name=c_name(var.name))
252 ret += mcgen('''
253 break;
254''')
Markus Armbruster1889e572021-08-31 14:37:58 +0200255 ret += var.ifcond.gen_endif()
Kevin Wolf69dd62d2013-07-08 16:14:21 +0200256
257 ret += mcgen('''
Eric Blake9b4e38f2016-06-15 11:37:51 -0600258 case QTYPE_NONE:
259 abort();
Markus Armbruster297a3642014-05-07 09:53:54 +0200260 default:
Markus Armbruster7111a862020-04-24 10:43:34 +0200261 assert(visit_is_input(v));
Markus Armbrustercdd2b222020-07-07 18:06:08 +0200262 error_setg(errp, QERR_INVALID_PARAMETER_TYPE, name ? name : "null",
Eric Blake0426d532015-12-01 22:20:48 -0700263 "%(name)s");
Markus Armbrusterc978bd52020-04-24 10:43:33 +0200264 /* Avoid passing invalid *obj to qapi_free_%(c_name)s() */
265 g_free(*obj);
266 *obj = NULL;
Kevin Wolf69dd62d2013-07-08 16:14:21 +0200267 }
Eric Blake9b4e38f2016-06-15 11:37:51 -0600268out_obj:
Eric Blake1158bb22016-06-09 10:48:34 -0600269 visit_end_alternate(v, (void **)obj);
Markus Armbrustercdd2b222020-07-07 18:06:08 +0200270 if (!ok && visit_is_input(v)) {
Eric Blake68ab47e2016-04-28 15:45:32 -0600271 qapi_free_%(c_name)s(*obj);
272 *obj = NULL;
273 }
Markus Armbrustercdd2b222020-07-07 18:06:08 +0200274 return ok;
Kevin Wolf69dd62d2013-07-08 16:14:21 +0200275}
Eric Blake0426d532015-12-01 22:20:48 -0700276''',
Eric Blake68ab47e2016-04-28 15:45:32 -0600277 name=name, c_name=c_name(name))
Kevin Wolf69dd62d2013-07-08 16:14:21 +0200278
279 return ret
280
Markus Armbrustere98859a2015-09-16 13:06:16 +0200281
John Snowb4c0aa52020-10-09 12:15:58 -0400282def gen_visit_object(name: str) -> str:
Eric Blake7ce106a2016-03-17 16:48:30 -0600283 return mcgen('''
Michael Roth06d64c62011-07-19 14:50:41 -0500284
John Snow42c0dd12020-10-09 12:15:30 -0400285bool visit_type_%(c_name)s(Visitor *v, const char *name,
286 %(c_name)s **obj, Error **errp)
Michael Roth06d64c62011-07-19 14:50:41 -0500287{
Markus Armbrustercdd2b222020-07-07 18:06:08 +0200288 bool ok = false;
Paolo Bonzinidc8fb6d2012-03-06 18:55:56 +0100289
Markus Armbruster012d4c92020-07-07 18:05:45 +0200290 if (!visit_start_struct(v, name, (void **)obj, sizeof(%(c_name)s), errp)) {
291 return false;
Markus Armbruster297a3642014-05-07 09:53:54 +0200292 }
Eric Blakee36c7142015-09-29 16:21:11 -0600293 if (!*obj) {
Markus Armbruster8e08bf42020-04-24 10:43:29 +0200294 /* incomplete */
295 assert(visit_is_dealloc(v));
Markus Armbrustercbf97d52020-07-16 17:06:17 +0200296 ok = true;
Eric Blakee36c7142015-09-29 16:21:11 -0600297 goto out_obj;
298 }
Markus Armbrustercdd2b222020-07-07 18:06:08 +0200299 if (!visit_type_%(c_name)s_members(v, *obj, errp)) {
Eric Blake15c2f662016-04-28 15:45:27 -0600300 goto out_obj;
301 }
Markus Armbrustercdd2b222020-07-07 18:06:08 +0200302 ok = visit_check_struct(v, errp);
Eric Blake9a5cd422016-02-17 23:48:20 -0700303out_obj:
Eric Blake1158bb22016-06-09 10:48:34 -0600304 visit_end_struct(v, (void **)obj);
Markus Armbrustercdd2b222020-07-07 18:06:08 +0200305 if (!ok && visit_is_input(v)) {
Eric Blake68ab47e2016-04-28 15:45:32 -0600306 qapi_free_%(c_name)s(*obj);
307 *obj = NULL;
308 }
Markus Armbrustercdd2b222020-07-07 18:06:08 +0200309 return ok;
Paolo Bonzinidc8fb6d2012-03-06 18:55:56 +0100310}
Eric Blake9a5cd422016-02-17 23:48:20 -0700311''',
312 c_name=c_name(name))
Paolo Bonzinidc8fb6d2012-03-06 18:55:56 +0100313
Markus Armbrustere98859a2015-09-16 13:06:16 +0200314
Markus Armbrustercdb66102018-02-26 16:29:21 -0600315class QAPISchemaGenVisitVisitor(QAPISchemaModularCVisitor):
Markus Armbruster441cbac2015-09-16 13:06:10 +0200316
John Snowb4c0aa52020-10-09 12:15:58 -0400317 def __init__(self, prefix: str):
Markus Armbruster2cae67b2020-03-04 16:59:31 +0100318 super().__init__(
319 prefix, 'qapi-visit', ' * Schema-defined QAPI visitors',
Markus Armbruster3bef3aa2019-11-20 19:25:51 +0100320 ' * Built-in QAPI visitors', __doc__)
321
Markus Armbrusterf3a70592021-02-01 14:37:37 -0500322 def _begin_builtin_module(self) -> None:
Markus Armbrustercdb66102018-02-26 16:29:21 -0600323 self._genc.preamble_add(mcgen('''
324#include "qemu/osdep.h"
Markus Armbrustercdb66102018-02-26 16:29:21 -0600325#include "qapi/error.h"
Markus Armbrustereb815e22018-02-11 10:36:05 +0100326#include "qapi/qapi-builtin-visit.h"
Markus Armbrustercdb66102018-02-26 16:29:21 -0600327'''))
328 self._genh.preamble_add(mcgen('''
329#include "qapi/visitor.h"
Markus Armbrustereb815e22018-02-11 10:36:05 +0100330#include "qapi/qapi-builtin-types.h"
Markus Armbrustercdb66102018-02-26 16:29:21 -0600331
Markus Armbruster3bef3aa2019-11-20 19:25:51 +0100332'''))
Markus Armbrustercdb66102018-02-26 16:29:21 -0600333
John Snowb4c0aa52020-10-09 12:15:58 -0400334 def _begin_user_module(self, name: str) -> None:
Markus Armbruster9af23982018-02-11 10:36:01 +0100335 types = self._module_basename('qapi-types', name)
336 visit = self._module_basename('qapi-visit', name)
Markus Armbruster71b3f042018-02-26 13:50:08 -0600337 self._genc.preamble_add(mcgen('''
338#include "qemu/osdep.h"
Markus Armbruster71b3f042018-02-26 13:50:08 -0600339#include "qapi/error.h"
340#include "qapi/qmp/qerror.h"
Markus Armbruster9af23982018-02-11 10:36:01 +0100341#include "%(visit)s.h"
Markus Armbruster71b3f042018-02-26 13:50:08 -0600342''',
Marc-André Lureaua48e7542018-03-21 12:51:23 +0100343 visit=visit))
Markus Armbruster71b3f042018-02-26 13:50:08 -0600344 self._genh.preamble_add(mcgen('''
Markus Armbrustereb815e22018-02-11 10:36:05 +0100345#include "qapi/qapi-builtin-visit.h"
Markus Armbruster9af23982018-02-11 10:36:01 +0100346#include "%(types)s.h"
Markus Armbruster71b3f042018-02-26 13:50:08 -0600347
348''',
Markus Armbruster9af23982018-02-11 10:36:01 +0100349 types=types))
Markus Armbruster441cbac2015-09-16 13:06:10 +0200350
John Snowb4c0aa52020-10-09 12:15:58 -0400351 def visit_enum_type(self,
352 name: str,
John Snow4a82e462021-02-01 14:37:46 -0500353 info: Optional[QAPISourceInfo],
Marc-André Lureauf17539c2021-08-04 12:30:57 +0400354 ifcond: QAPISchemaIfCond,
John Snowb4c0aa52020-10-09 12:15:58 -0400355 features: List[QAPISchemaFeature],
356 members: List[QAPISchemaEnumMember],
357 prefix: Optional[str]) -> None:
Markus Armbruster9f88c662018-07-03 17:56:45 +0200358 with ifcontext(ifcond, self._genh, self._genc):
359 self._genh.add(gen_visit_decl(name, scalar=True))
360 self._genc.add(gen_visit_enum(name))
Markus Armbruster441cbac2015-09-16 13:06:10 +0200361
John Snowb4c0aa52020-10-09 12:15:58 -0400362 def visit_array_type(self,
363 name: str,
364 info: Optional[QAPISourceInfo],
Marc-André Lureauf17539c2021-08-04 12:30:57 +0400365 ifcond: QAPISchemaIfCond,
John Snowb4c0aa52020-10-09 12:15:58 -0400366 element_type: QAPISchemaType) -> None:
Markus Armbruster9f88c662018-07-03 17:56:45 +0200367 with ifcontext(ifcond, self._genh, self._genc):
368 self._genh.add(gen_visit_decl(name))
369 self._genc.add(gen_visit_list(name, element_type))
Markus Armbruster441cbac2015-09-16 13:06:10 +0200370
John Snowb4c0aa52020-10-09 12:15:58 -0400371 def visit_object_type(self,
372 name: str,
373 info: Optional[QAPISourceInfo],
Marc-André Lureauf17539c2021-08-04 12:30:57 +0400374 ifcond: QAPISchemaIfCond,
John Snowb4c0aa52020-10-09 12:15:58 -0400375 features: List[QAPISchemaFeature],
376 base: Optional[QAPISchemaObjectType],
377 members: List[QAPISchemaObjectTypeMember],
378 variants: Optional[QAPISchemaVariants]) -> None:
Eric Blake7ce106a2016-03-17 16:48:30 -0600379 # Nothing to do for the special empty builtin
380 if name == 'q_empty':
381 return
Markus Armbruster9f88c662018-07-03 17:56:45 +0200382 with ifcontext(ifcond, self._genh, self._genc):
383 self._genh.add(gen_visit_members_decl(name))
384 self._genc.add(gen_visit_object_members(name, base,
385 members, variants))
386 # TODO Worth changing the visitor signature, so we could
387 # directly use rather than repeat type.is_implicit()?
388 if not name.startswith('q_'):
389 # only explicit types need an allocating visit
390 self._genh.add(gen_visit_decl(name))
John Snow2cc1eef2020-10-09 12:15:57 -0400391 self._genc.add(gen_visit_object(name))
Markus Armbruster441cbac2015-09-16 13:06:10 +0200392
John Snowb4c0aa52020-10-09 12:15:58 -0400393 def visit_alternate_type(self,
394 name: str,
John Snow4a82e462021-02-01 14:37:46 -0500395 info: Optional[QAPISourceInfo],
Marc-André Lureauf17539c2021-08-04 12:30:57 +0400396 ifcond: QAPISchemaIfCond,
John Snowb4c0aa52020-10-09 12:15:58 -0400397 features: List[QAPISchemaFeature],
398 variants: QAPISchemaVariants) -> None:
Markus Armbruster9f88c662018-07-03 17:56:45 +0200399 with ifcontext(ifcond, self._genh, self._genc):
400 self._genh.add(gen_visit_decl(name))
401 self._genc.add(gen_visit_alternate(name, variants))
Markus Armbruster441cbac2015-09-16 13:06:10 +0200402
Avi Kivity8d3bc512011-12-27 16:02:16 +0200403
John Snowb4c0aa52020-10-09 12:15:58 -0400404def gen_visit(schema: QAPISchema,
405 output_dir: str,
406 prefix: str,
407 opt_builtins: bool) -> None:
Markus Armbrustercdb66102018-02-26 16:29:21 -0600408 vis = QAPISchemaGenVisitVisitor(prefix)
Markus Armbruster26df4e72018-02-26 13:39:37 -0600409 schema.visit(vis)
Markus Armbrustercdb66102018-02-26 16:29:21 -0600410 vis.write(output_dir, opt_builtins)