15ddeec83SMarkus Armbruster""" 25ddeec83SMarkus ArmbrusterQAPI types generator 35ddeec83SMarkus Armbruster 45ddeec83SMarkus ArmbrusterCopyright IBM, Corp. 2011 55ddeec83SMarkus ArmbrusterCopyright (c) 2013-2018 Red Hat Inc. 65ddeec83SMarkus Armbruster 75ddeec83SMarkus ArmbrusterAuthors: 85ddeec83SMarkus Armbruster Anthony Liguori <aliguori@us.ibm.com> 95ddeec83SMarkus Armbruster Michael Roth <mdroth@linux.vnet.ibm.com> 105ddeec83SMarkus Armbruster Markus Armbruster <armbru@redhat.com> 115ddeec83SMarkus Armbruster 125ddeec83SMarkus ArmbrusterThis work is licensed under the terms of the GNU GPL, version 2. 13678e48a2SMarkus Armbruster# See the COPYING file in the top-level directory. 145ddeec83SMarkus Armbruster""" 15fb3182ceSMichael Roth 16f17539c8SMarc-André Lureaufrom typing import List, Optional 17cd073c8fSJohn Snow 181889e57aSMarkus Armbrusterfrom .common import c_enum_const, c_name, mcgen 19ba27dcccSDaniel P. Berrangéfrom .gen import QAPISchemaModularCVisitor, gen_features, ifcontext 20cd073c8fSJohn Snowfrom .schema import ( 21cd073c8fSJohn Snow QAPISchema, 221d067e39SMarkus Armbruster QAPISchemaAlternatives, 231d067e39SMarkus Armbruster QAPISchemaBranches, 24cd073c8fSJohn Snow QAPISchemaEnumMember, 25cd073c8fSJohn Snow QAPISchemaFeature, 26f17539c8SMarc-André Lureau QAPISchemaIfCond, 27cd073c8fSJohn Snow QAPISchemaObjectType, 28cd073c8fSJohn Snow QAPISchemaObjectTypeMember, 29cd073c8fSJohn Snow QAPISchemaType, 30cd073c8fSJohn Snow QAPISchemaVariants, 31cd073c8fSJohn Snow) 32cd073c8fSJohn Snowfrom .source import QAPISourceInfo 33fb3182ceSMichael Roth 34e98859a9SMarkus Armbruster 351de5d4caSEric Blake# variants must be emitted before their container; track what has already 361de5d4caSEric Blake# been output 371de5d4caSEric Blakeobjects_seen = set() 381de5d4caSEric Blake 391de5d4caSEric Blake 40cd073c8fSJohn Snowdef gen_enum_lookup(name: str, 41cd073c8fSJohn Snow members: List[QAPISchemaEnumMember], 42cd073c8fSJohn Snow prefix: Optional[str] = None) -> str: 43aa237044SMarkus Armbruster max_index = c_enum_const(name, '_MAX', prefix) 44c8688760SMarkus Armbruster feats = '' 4561bfb2e1SMarkus Armbruster ret = mcgen(''' 4661bfb2e1SMarkus Armbruster 4761bfb2e1SMarkus Armbrusterconst QEnumLookup %(c_name)s_lookup = { 4861bfb2e1SMarkus Armbruster .array = (const char *const[]) { 4961bfb2e1SMarkus Armbruster''', 5061bfb2e1SMarkus Armbruster c_name=c_name(name)) 51dec44d3dSJohn Snow for memb in members: 521889e57aSMarkus Armbruster ret += memb.ifcond.gen_if() 53dec44d3dSJohn Snow index = c_enum_const(name, memb.name, prefix) 5461bfb2e1SMarkus Armbruster ret += mcgen(''' 5561bfb2e1SMarkus Armbruster [%(index)s] = "%(name)s", 5661bfb2e1SMarkus Armbruster''', 57dec44d3dSJohn Snow index=index, name=memb.name) 581889e57aSMarkus Armbruster ret += memb.ifcond.gen_endif() 59aa237044SMarkus Armbruster 60ba27dcccSDaniel P. Berrangé features = gen_features(memb.features) 61ba27dcccSDaniel P. Berrangé if features != '0': 62c8688760SMarkus Armbruster feats += mcgen(''' 63ba27dcccSDaniel P. Berrangé [%(index)s] = %(features)s, 64c8688760SMarkus Armbruster''', 65ba27dcccSDaniel P. Berrangé index=index, features=features) 66c8688760SMarkus Armbruster 67c8688760SMarkus Armbruster if feats: 68aa237044SMarkus Armbruster ret += mcgen(''' 69aa237044SMarkus Armbruster }, 70696ae1acSDaniel P. Berrangé .features = (const uint64_t[%(max_index)s]) { 71aa237044SMarkus Armbruster''', 72aa237044SMarkus Armbruster max_index=max_index) 73c8688760SMarkus Armbruster ret += feats 7461bfb2e1SMarkus Armbruster 7561bfb2e1SMarkus Armbruster ret += mcgen(''' 7661bfb2e1SMarkus Armbruster }, 7761bfb2e1SMarkus Armbruster .size = %(max_index)s 7861bfb2e1SMarkus Armbruster}; 7961bfb2e1SMarkus Armbruster''', 80aa237044SMarkus Armbruster max_index=max_index) 8161bfb2e1SMarkus Armbruster return ret 8261bfb2e1SMarkus Armbruster 8361bfb2e1SMarkus Armbruster 84cd073c8fSJohn Snowdef gen_enum(name: str, 85cd073c8fSJohn Snow members: List[QAPISchemaEnumMember], 86cd073c8fSJohn Snow prefix: Optional[str] = None) -> str: 8761bfb2e1SMarkus Armbruster # append automatically generated _MAX value 8861bfb2e1SMarkus Armbruster enum_members = members + [QAPISchemaEnumMember('_MAX', None)] 8961bfb2e1SMarkus Armbruster 9061bfb2e1SMarkus Armbruster ret = mcgen(''' 9161bfb2e1SMarkus Armbruster 9261bfb2e1SMarkus Armbrustertypedef enum %(c_name)s { 9361bfb2e1SMarkus Armbruster''', 9461bfb2e1SMarkus Armbruster c_name=c_name(name)) 9561bfb2e1SMarkus Armbruster 96dec44d3dSJohn Snow for memb in enum_members: 971889e57aSMarkus Armbruster ret += memb.ifcond.gen_if() 9861bfb2e1SMarkus Armbruster ret += mcgen(''' 9961bfb2e1SMarkus Armbruster %(c_enum)s, 10061bfb2e1SMarkus Armbruster''', 101dec44d3dSJohn Snow c_enum=c_enum_const(name, memb.name, prefix)) 1021889e57aSMarkus Armbruster ret += memb.ifcond.gen_endif() 10361bfb2e1SMarkus Armbruster 10461bfb2e1SMarkus Armbruster ret += mcgen(''' 10561bfb2e1SMarkus Armbruster} %(c_name)s; 10661bfb2e1SMarkus Armbruster''', 10761bfb2e1SMarkus Armbruster c_name=c_name(name)) 10861bfb2e1SMarkus Armbruster 10961bfb2e1SMarkus Armbruster ret += mcgen(''' 11061bfb2e1SMarkus Armbruster 11161bfb2e1SMarkus Armbruster#define %(c_name)s_str(val) \\ 11261bfb2e1SMarkus Armbruster qapi_enum_lookup(&%(c_name)s_lookup, (val)) 11361bfb2e1SMarkus Armbruster 11461bfb2e1SMarkus Armbrusterextern const QEnumLookup %(c_name)s_lookup; 11561bfb2e1SMarkus Armbruster''', 11661bfb2e1SMarkus Armbruster c_name=c_name(name)) 11761bfb2e1SMarkus Armbruster return ret 11861bfb2e1SMarkus Armbruster 11961bfb2e1SMarkus Armbruster 120cd073c8fSJohn Snowdef gen_fwd_object_or_array(name: str) -> str: 121c0afa9c5SMichael Roth return mcgen(''' 122c0afa9c5SMichael Roth 123e98859a9SMarkus Armbrustertypedef struct %(c_name)s %(c_name)s; 124fb3182ceSMichael Roth''', 125e98859a9SMarkus Armbruster c_name=c_name(name)) 126e98859a9SMarkus Armbruster 127fb3182ceSMichael Roth 128cd073c8fSJohn Snowdef gen_array(name: str, element_type: QAPISchemaType) -> str: 129b9c4b48dSAmos Kong return mcgen(''' 1303a864e7cSMarkus Armbruster 131e98859a9SMarkus Armbrusterstruct %(c_name)s { 132e98859a9SMarkus Armbruster %(c_name)s *next; 133e65d89bfSEric Blake %(c_type)s value; 1342b162ccbSMarkus Armbruster}; 135b9c4b48dSAmos Kong''', 136e98859a9SMarkus Armbruster c_name=c_name(name), c_type=element_type.c_type()) 137e98859a9SMarkus Armbruster 138b9c4b48dSAmos Kong 139cd073c8fSJohn Snowdef gen_struct_members(members: List[QAPISchemaObjectTypeMember]) -> str: 14001537030SKevin Wolf ret = '' 1417d9586f9SEric Blake for memb in members: 1421889e57aSMarkus Armbruster ret += memb.ifcond.gen_if() 14344ea9d9bSMarkus Armbruster if memb.need_has(): 144fb3182ceSMichael Roth ret += mcgen(''' 145fb3182ceSMichael Roth bool has_%(c_name)s; 146fb3182ceSMichael Roth''', 1477d9586f9SEric Blake c_name=c_name(memb.name)) 148fb3182ceSMichael Roth ret += mcgen(''' 149fb3182ceSMichael Roth %(c_type)s %(c_name)s; 150fb3182ceSMichael Roth''', 1517d9586f9SEric Blake c_type=memb.type.c_type(), c_name=c_name(memb.name)) 1521889e57aSMarkus Armbruster ret += memb.ifcond.gen_endif() 1532b162ccbSMarkus Armbruster return ret 15414d36307SKevin Wolf 155e98859a9SMarkus Armbruster 156f17539c8SMarc-André Lureaudef gen_object(name: str, ifcond: QAPISchemaIfCond, 157cd073c8fSJohn Snow base: Optional[QAPISchemaObjectType], 158cd073c8fSJohn Snow members: List[QAPISchemaObjectTypeMember], 159cd073c8fSJohn Snow variants: Optional[QAPISchemaVariants]) -> str: 1601de5d4caSEric Blake if name in objects_seen: 1611de5d4caSEric Blake return '' 1621de5d4caSEric Blake objects_seen.add(name) 1631de5d4caSEric Blake 1641de5d4caSEric Blake ret = '' 165dec44d3dSJohn Snow for var in variants.variants if variants else (): 166dec44d3dSJohn Snow obj = var.type 167dec44d3dSJohn Snow if not isinstance(obj, QAPISchemaObjectType): 168dec44d3dSJohn Snow continue 169dec44d3dSJohn Snow ret += gen_object(obj.name, obj.ifcond, obj.base, 1703ff2a5a3SMarkus Armbruster obj.local_members, obj.branches) 1711de5d4caSEric Blake 1721de5d4caSEric Blake ret += mcgen(''' 1733a864e7cSMarkus Armbruster 1749f88c662SMarkus Armbruster''') 1751889e57aSMarkus Armbruster ret += ifcond.gen_if() 1769f88c662SMarkus Armbruster ret += mcgen(''' 177e98859a9SMarkus Armbrusterstruct %(c_name)s { 17801537030SKevin Wolf''', 179e98859a9SMarkus Armbruster c_name=c_name(name)) 18001537030SKevin Wolf 1817d9586f9SEric Blake if base: 182ac4338f8SEric Blake if not base.is_implicit(): 1837d9586f9SEric Blake ret += mcgen(''' 1847d9586f9SEric Blake /* Members inherited from %(c_name)s: */ 1857d9586f9SEric Blake''', 1867d9586f9SEric Blake c_name=base.c_name()) 18714f00c6cSEric Blake ret += gen_struct_members(base.members) 188ac4338f8SEric Blake if not base.is_implicit(): 1897d9586f9SEric Blake ret += mcgen(''' 1907d9586f9SEric Blake /* Own members: */ 1917d9586f9SEric Blake''') 19214f00c6cSEric Blake ret += gen_struct_members(members) 19301537030SKevin Wolf 194570cd8d1SEric Blake if variants: 195570cd8d1SEric Blake ret += gen_variants(variants) 196570cd8d1SEric Blake 19714f00c6cSEric Blake # Make sure that all structs have at least one member; this avoids 198e98859a9SMarkus Armbruster # potential issues with attempting to malloc space for zero-length 199e98859a9SMarkus Armbruster # structs in C, and also incompatibility with C++ (where an empty 200e98859a9SMarkus Armbruster # struct is size 1). 201b6167706SEric Blake if (not base or base.is_empty()) and not members and not variants: 20283ecb22bSPeter Maydell ret += mcgen(''' 203c81200b0SEric Blake char qapi_dummy_for_empty_struct; 20483ecb22bSPeter Maydell''') 20583ecb22bSPeter Maydell 206fb3182ceSMichael Roth ret += mcgen(''' 207e1d4210cSMarkus Armbruster}; 208e1d4210cSMarkus Armbruster''') 2091889e57aSMarkus Armbruster ret += ifcond.gen_endif() 210fb3182ceSMichael Roth 211fb3182ceSMichael Roth return ret 212fb3182ceSMichael Roth 213e98859a9SMarkus Armbruster 214cd073c8fSJohn Snowdef gen_upcast(name: str, base: QAPISchemaObjectType) -> str: 21530594fe1SEric Blake # C makes const-correctness ugly. We have to cast away const to let 21630594fe1SEric Blake # this function work for both const and non-const obj. 21730594fe1SEric Blake return mcgen(''' 21830594fe1SEric Blake 21930594fe1SEric Blakestatic inline %(base)s *qapi_%(c_name)s_base(const %(c_name)s *obj) 22030594fe1SEric Blake{ 22130594fe1SEric Blake return (%(base)s *)obj; 22230594fe1SEric Blake} 22330594fe1SEric Blake''', 22430594fe1SEric Blake c_name=c_name(name), base=base.c_name()) 22530594fe1SEric Blake 22630594fe1SEric Blake 227cd073c8fSJohn Snowdef gen_variants(variants: QAPISchemaVariants) -> str: 228570cd8d1SEric Blake ret = mcgen(''' 2291e6c1616SMarkus Armbruster union { /* union tag is @%(c_name)s */ 230fb3182ceSMichael Roth''', 231f51d8fabSEric Blake c_name=c_name(variants.tag_member.name)) 232fb3182ceSMichael Roth 2332b162ccbSMarkus Armbruster for var in variants.variants: 234800877bbSAnton Nefedov if var.type.name == 'q_empty': 235800877bbSAnton Nefedov continue 2361889e57aSMarkus Armbruster ret += var.ifcond.gen_if() 237e4ba22b3SEric Blake ret += mcgen(''' 238fb3182ceSMichael Roth %(c_type)s %(c_name)s; 239fb3182ceSMichael Roth''', 24032bafa8fSEric Blake c_type=var.type.c_unboxed_type(), 2412b162ccbSMarkus Armbruster c_name=c_name(var.name)) 2421889e57aSMarkus Armbruster ret += var.ifcond.gen_endif() 243fb3182ceSMichael Roth 244fb3182ceSMichael Roth ret += mcgen(''' 245f51d8fabSEric Blake } u; 246fb3182ceSMichael Roth''') 247fb3182ceSMichael Roth 248fb3182ceSMichael Roth return ret 249fb3182ceSMichael Roth 250e98859a9SMarkus Armbruster 251cd073c8fSJohn Snowdef gen_type_cleanup_decl(name: str) -> str: 252fb3182ceSMichael Roth ret = mcgen(''' 2532b162ccbSMarkus Armbruster 254e98859a9SMarkus Armbrustervoid qapi_free_%(c_name)s(%(c_name)s *obj); 255221db5daSDaniel P. BerrangéG_DEFINE_AUTOPTR_CLEANUP_FUNC(%(c_name)s, qapi_free_%(c_name)s) 256fb3182ceSMichael Roth''', 257e98859a9SMarkus Armbruster c_name=c_name(name)) 258fb3182ceSMichael Roth return ret 259fb3182ceSMichael Roth 260e98859a9SMarkus Armbruster 261cd073c8fSJohn Snowdef gen_type_cleanup(name: str) -> str: 262fb3182ceSMichael Roth ret = mcgen(''' 263c0afa9c5SMichael Roth 264e98859a9SMarkus Armbrustervoid qapi_free_%(c_name)s(%(c_name)s *obj) 265fb3182ceSMichael Roth{ 266fb3182ceSMichael Roth Visitor *v; 267fb3182ceSMichael Roth 268fb3182ceSMichael Roth if (!obj) { 269fb3182ceSMichael Roth return; 270fb3182ceSMichael Roth } 271fb3182ceSMichael Roth 2722c0ef9f4SEric Blake v = qapi_dealloc_visitor_new(); 27351e72bc1SEric Blake visit_type_%(c_name)s(v, NULL, &obj, NULL); 2742c0ef9f4SEric Blake visit_free(v); 275fb3182ceSMichael Roth} 276fb3182ceSMichael Roth''', 277e98859a9SMarkus Armbruster c_name=c_name(name)) 278fb3182ceSMichael Roth return ret 279fb3182ceSMichael Roth 2802b162ccbSMarkus Armbruster 281cdb6610aSMarkus Armbrusterclass QAPISchemaGenTypeVisitor(QAPISchemaModularCVisitor): 28271b3f045SMarkus Armbruster 283cd073c8fSJohn Snow def __init__(self, prefix: str): 2842cae67bcSMarkus Armbruster super().__init__( 2852cae67bcSMarkus Armbruster prefix, 'qapi-types', ' * Schema-defined QAPI types', 2863bef3aaeSMarkus Armbruster ' * Built-in QAPI types', __doc__) 2873bef3aaeSMarkus Armbruster 288f3a70592SMarkus Armbruster def _begin_builtin_module(self) -> None: 289cdb6610aSMarkus Armbruster self._genc.preamble_add(mcgen(''' 290cdb6610aSMarkus Armbruster#include "qemu/osdep.h" 291cdb6610aSMarkus Armbruster#include "qapi/dealloc-visitor.h" 292eb815e24SMarkus Armbruster#include "qapi/qapi-builtin-types.h" 293eb815e24SMarkus Armbruster#include "qapi/qapi-builtin-visit.h" 294cdb6610aSMarkus Armbruster''')) 295cdb6610aSMarkus Armbruster self._genh.preamble_add(mcgen(''' 296cdb6610aSMarkus Armbruster#include "qapi/util.h" 297cdb6610aSMarkus Armbruster''')) 298cdb6610aSMarkus Armbruster 299cd073c8fSJohn Snow def _begin_user_module(self, name: str) -> None: 3009af23989SMarkus Armbruster types = self._module_basename('qapi-types', name) 3019af23989SMarkus Armbruster visit = self._module_basename('qapi-visit', name) 30271b3f045SMarkus Armbruster self._genc.preamble_add(mcgen(''' 30371b3f045SMarkus Armbruster#include "qemu/osdep.h" 30471b3f045SMarkus Armbruster#include "qapi/dealloc-visitor.h" 3059af23989SMarkus Armbruster#include "%(types)s.h" 3069af23989SMarkus Armbruster#include "%(visit)s.h" 307*2ebb09f3SDaniel P. Berrangé#include "%(prefix)sqapi-features.h" 30871b3f045SMarkus Armbruster''', 309*2ebb09f3SDaniel P. Berrangé types=types, visit=visit, 310*2ebb09f3SDaniel P. Berrangé prefix=self._prefix)) 31171b3f045SMarkus Armbruster self._genh.preamble_add(mcgen(''' 312eb815e24SMarkus Armbruster#include "qapi/qapi-builtin-types.h" 313*2ebb09f3SDaniel P. Berrangé''', 314*2ebb09f3SDaniel P. Berrangé prefix=self._prefix)) 3152b162ccbSMarkus Armbruster 316cd073c8fSJohn Snow def visit_begin(self, schema: QAPISchema) -> None: 3177ce106a9SEric Blake # gen_object() is recursive, ensure it doesn't visit the empty type 3187ce106a9SEric Blake objects_seen.add(schema.the_empty_object_type.name) 3192b162ccbSMarkus Armbruster 320cd073c8fSJohn Snow def _gen_type_cleanup(self, name: str) -> None: 32171b3f045SMarkus Armbruster self._genh.add(gen_type_cleanup_decl(name)) 32271b3f045SMarkus Armbruster self._genc.add(gen_type_cleanup(name)) 3232b162ccbSMarkus Armbruster 324cd073c8fSJohn Snow def visit_enum_type(self, 325cd073c8fSJohn Snow name: str, 326cd073c8fSJohn Snow info: Optional[QAPISourceInfo], 327f17539c8SMarc-André Lureau ifcond: QAPISchemaIfCond, 328cd073c8fSJohn Snow features: List[QAPISchemaFeature], 329cd073c8fSJohn Snow members: List[QAPISchemaEnumMember], 330cd073c8fSJohn Snow prefix: Optional[str]) -> None: 3319f88c662SMarkus Armbruster with ifcontext(ifcond, self._genh, self._genc): 3321962bd39SMarc-André Lureau self._genh.preamble_add(gen_enum(name, members, prefix)) 3331962bd39SMarc-André Lureau self._genc.add(gen_enum_lookup(name, members, prefix)) 3342b162ccbSMarkus Armbruster 335cd073c8fSJohn Snow def visit_array_type(self, 336cd073c8fSJohn Snow name: str, 337cd073c8fSJohn Snow info: Optional[QAPISourceInfo], 338f17539c8SMarc-André Lureau ifcond: QAPISchemaIfCond, 339cd073c8fSJohn Snow element_type: QAPISchemaType) -> None: 3409f88c662SMarkus Armbruster with ifcontext(ifcond, self._genh, self._genc): 34171b3f045SMarkus Armbruster self._genh.preamble_add(gen_fwd_object_or_array(name)) 34271b3f045SMarkus Armbruster self._genh.add(gen_array(name, element_type)) 3432b162ccbSMarkus Armbruster self._gen_type_cleanup(name) 3442b162ccbSMarkus Armbruster 345cd073c8fSJohn Snow def visit_object_type(self, 346cd073c8fSJohn Snow name: str, 347cd073c8fSJohn Snow info: Optional[QAPISourceInfo], 348f17539c8SMarc-André Lureau ifcond: QAPISchemaIfCond, 349cd073c8fSJohn Snow features: List[QAPISchemaFeature], 350cd073c8fSJohn Snow base: Optional[QAPISchemaObjectType], 351cd073c8fSJohn Snow members: List[QAPISchemaObjectTypeMember], 352d1da8af8SMarkus Armbruster branches: Optional[QAPISchemaBranches]) -> None: 3537ce106a9SEric Blake # Nothing to do for the special empty builtin 3547ce106a9SEric Blake if name == 'q_empty': 3557ce106a9SEric Blake return 3569f88c662SMarkus Armbruster with ifcontext(ifcond, self._genh): 35771b3f045SMarkus Armbruster self._genh.preamble_add(gen_fwd_object_or_array(name)) 358d1da8af8SMarkus Armbruster self._genh.add(gen_object(name, ifcond, base, members, branches)) 3599f88c662SMarkus Armbruster with ifcontext(ifcond, self._genh, self._genc): 360ac4338f8SEric Blake if base and not base.is_implicit(): 36171b3f045SMarkus Armbruster self._genh.add(gen_upcast(name, base)) 3627ce106a9SEric Blake # TODO Worth changing the visitor signature, so we could 3637ce106a9SEric Blake # directly use rather than repeat type.is_implicit()? 3647ce106a9SEric Blake if not name.startswith('q_'): 3657ce106a9SEric Blake # implicit types won't be directly allocated/freed 3662b162ccbSMarkus Armbruster self._gen_type_cleanup(name) 3672b162ccbSMarkus Armbruster 368cd073c8fSJohn Snow def visit_alternate_type(self, 369cd073c8fSJohn Snow name: str, 3704a82e468SJohn Snow info: Optional[QAPISourceInfo], 371f17539c8SMarc-André Lureau ifcond: QAPISchemaIfCond, 372cd073c8fSJohn Snow features: List[QAPISchemaFeature], 37341d0ad1dSMarkus Armbruster alternatives: QAPISchemaAlternatives) -> None: 3749f88c662SMarkus Armbruster with ifcontext(ifcond, self._genh): 37571b3f045SMarkus Armbruster self._genh.preamble_add(gen_fwd_object_or_array(name)) 3769f88c662SMarkus Armbruster self._genh.add(gen_object(name, ifcond, None, 37741d0ad1dSMarkus Armbruster [alternatives.tag_member], alternatives)) 3789f88c662SMarkus Armbruster with ifcontext(ifcond, self._genh, self._genc): 3792b162ccbSMarkus Armbruster self._gen_type_cleanup(name) 3802b162ccbSMarkus Armbruster 38126df4e7fSMarkus Armbruster 382cd073c8fSJohn Snowdef gen_types(schema: QAPISchema, 383cd073c8fSJohn Snow output_dir: str, 384cd073c8fSJohn Snow prefix: str, 385cd073c8fSJohn Snow opt_builtins: bool) -> None: 386cdb6610aSMarkus Armbruster vis = QAPISchemaGenTypeVisitor(prefix) 387d46eec42SMarkus Armbruster schema.visit(vis) 388cdb6610aSMarkus Armbruster vis.write(output_dir, opt_builtins) 389