1fb0bc835SMarkus Armbruster""" 2fb0bc835SMarkus ArmbrusterQAPI command marshaller generator 3fb0bc835SMarkus Armbruster 4fb0bc835SMarkus ArmbrusterCopyright IBM, Corp. 2011 5fb0bc835SMarkus ArmbrusterCopyright (C) 2014-2018 Red Hat, Inc. 6fb0bc835SMarkus Armbruster 7fb0bc835SMarkus ArmbrusterAuthors: 8fb0bc835SMarkus Armbruster Anthony Liguori <aliguori@us.ibm.com> 9fb0bc835SMarkus Armbruster Michael Roth <mdroth@linux.vnet.ibm.com> 10fb0bc835SMarkus Armbruster Markus Armbruster <armbru@redhat.com> 11fb0bc835SMarkus Armbruster 12fb0bc835SMarkus ArmbrusterThis work is licensed under the terms of the GNU GPL, version 2. 13fb0bc835SMarkus ArmbrusterSee the COPYING file in the top-level directory. 14fb0bc835SMarkus Armbruster""" 15fb0bc835SMarkus Armbruster 167304721fSJohn Snowfrom typing import ( 177304721fSJohn Snow Dict, 187304721fSJohn Snow List, 197304721fSJohn Snow Optional, 207304721fSJohn Snow Set, 217304721fSJohn Snow) 227304721fSJohn Snow 23e6a34cd7SJohn Snowfrom .common import c_name, mcgen 24e6a34cd7SJohn Snowfrom .gen import ( 257304721fSJohn Snow QAPIGenC, 26e6a34cd7SJohn Snow QAPISchemaModularCVisitor, 27e6a34cd7SJohn Snow build_params, 286604e475SMarkus Armbruster gen_special_features, 2990254ec4SJohn Snow ifcontext, 30e6a34cd7SJohn Snow) 317304721fSJohn Snowfrom .schema import ( 327304721fSJohn Snow QAPISchema, 337304721fSJohn Snow QAPISchemaFeature, 34f17539c8SMarc-André Lureau QAPISchemaIfCond, 357304721fSJohn Snow QAPISchemaObjectType, 367304721fSJohn Snow QAPISchemaType, 377304721fSJohn Snow) 387304721fSJohn Snowfrom .source import QAPISourceInfo 39fb0bc835SMarkus Armbruster 40fb0bc835SMarkus Armbruster 417304721fSJohn Snowdef gen_command_decl(name: str, 427304721fSJohn Snow arg_type: Optional[QAPISchemaObjectType], 437304721fSJohn Snow boxed: bool, 44cf9d4e68SPaolo Bonzini ret_type: Optional[QAPISchemaType], 45cf9d4e68SPaolo Bonzini coroutine: bool) -> str: 46fb0bc835SMarkus Armbruster return mcgen(''' 47cf9d4e68SPaolo Bonzini%(c_type)s %(coroutine_fn)sqmp_%(c_name)s(%(params)s); 48fb0bc835SMarkus Armbruster''', 49fb0bc835SMarkus Armbruster c_type=(ret_type and ret_type.c_type()) or 'void', 50cf9d4e68SPaolo Bonzini coroutine_fn='coroutine_fn ' if coroutine else '', 51fb0bc835SMarkus Armbruster c_name=c_name(name), 52fb0bc835SMarkus Armbruster params=build_params(arg_type, boxed, 'Error **errp')) 53fb0bc835SMarkus Armbruster 54fb0bc835SMarkus Armbruster 557304721fSJohn Snowdef gen_call(name: str, 567304721fSJohn Snow arg_type: Optional[QAPISchemaObjectType], 577304721fSJohn Snow boxed: bool, 58bd2017bcSVladimir Sementsov-Ogievskiy ret_type: Optional[QAPISchemaType], 59bd2017bcSVladimir Sementsov-Ogievskiy gen_tracing: bool) -> str: 60fb0bc835SMarkus Armbruster ret = '' 61fb0bc835SMarkus Armbruster 62fb0bc835SMarkus Armbruster argstr = '' 63fb0bc835SMarkus Armbruster if boxed: 64675b214bSMarkus Armbruster assert arg_type 65fb0bc835SMarkus Armbruster argstr = '&arg, ' 66fb0bc835SMarkus Armbruster elif arg_type: 67*3ff2a5a3SMarkus Armbruster assert not arg_type.branches 68fb0bc835SMarkus Armbruster for memb in arg_type.members: 69de3b3f52SMarkus Armbruster assert not memb.ifcond.is_present() 7044ea9d9bSMarkus Armbruster if memb.need_has(): 71fb0bc835SMarkus Armbruster argstr += 'arg.has_%s, ' % c_name(memb.name) 72fb0bc835SMarkus Armbruster argstr += 'arg.%s, ' % c_name(memb.name) 73fb0bc835SMarkus Armbruster 74fb0bc835SMarkus Armbruster lhs = '' 75fb0bc835SMarkus Armbruster if ret_type: 76fb0bc835SMarkus Armbruster lhs = 'retval = ' 77fb0bc835SMarkus Armbruster 78bd2017bcSVladimir Sementsov-Ogievskiy name = c_name(name) 79bd2017bcSVladimir Sementsov-Ogievskiy upper = name.upper() 80fb0bc835SMarkus Armbruster 81bd2017bcSVladimir Sementsov-Ogievskiy if gen_tracing: 82bd2017bcSVladimir Sementsov-Ogievskiy ret += mcgen(''' 83bd2017bcSVladimir Sementsov-Ogievskiy 84bd2017bcSVladimir Sementsov-Ogievskiy if (trace_event_get_state_backends(TRACE_QMP_ENTER_%(upper)s)) { 85bd2017bcSVladimir Sementsov-Ogievskiy g_autoptr(GString) req_json = qobject_to_json(QOBJECT(args)); 86bd2017bcSVladimir Sementsov-Ogievskiy 87bd2017bcSVladimir Sementsov-Ogievskiy trace_qmp_enter_%(name)s(req_json->str); 88bd2017bcSVladimir Sementsov-Ogievskiy } 89fb0bc835SMarkus Armbruster''', 90bd2017bcSVladimir Sementsov-Ogievskiy upper=upper, name=name) 91bd2017bcSVladimir Sementsov-Ogievskiy 92bd2017bcSVladimir Sementsov-Ogievskiy ret += mcgen(''' 93bd2017bcSVladimir Sementsov-Ogievskiy 94bd2017bcSVladimir Sementsov-Ogievskiy %(lhs)sqmp_%(name)s(%(args)s&err); 95bd2017bcSVladimir Sementsov-Ogievskiy''', 96bd2017bcSVladimir Sementsov-Ogievskiy name=name, args=argstr, lhs=lhs) 97167d913fSVladimir Sementsov-Ogievskiy 98fb0bc835SMarkus Armbruster ret += mcgen(''' 99fb0bc835SMarkus Armbruster if (err) { 100bd2017bcSVladimir Sementsov-Ogievskiy''') 101bd2017bcSVladimir Sementsov-Ogievskiy 102bd2017bcSVladimir Sementsov-Ogievskiy if gen_tracing: 103bd2017bcSVladimir Sementsov-Ogievskiy ret += mcgen(''' 104bd2017bcSVladimir Sementsov-Ogievskiy trace_qmp_exit_%(name)s(error_get_pretty(err), false); 105bd2017bcSVladimir Sementsov-Ogievskiy''', 106bd2017bcSVladimir Sementsov-Ogievskiy name=name) 107bd2017bcSVladimir Sementsov-Ogievskiy 108bd2017bcSVladimir Sementsov-Ogievskiy ret += mcgen(''' 109167d913fSVladimir Sementsov-Ogievskiy error_propagate(errp, err); 110fb0bc835SMarkus Armbruster goto out; 111fb0bc835SMarkus Armbruster } 112167d913fSVladimir Sementsov-Ogievskiy''') 113167d913fSVladimir Sementsov-Ogievskiy 114167d913fSVladimir Sementsov-Ogievskiy if ret_type: 115167d913fSVladimir Sementsov-Ogievskiy ret += mcgen(''' 116fb0bc835SMarkus Armbruster 117cdd2b228SMarkus Armbruster qmp_marshal_output_%(c_name)s(retval, ret, errp); 118fb0bc835SMarkus Armbruster''', 119fb0bc835SMarkus Armbruster c_name=ret_type.c_name()) 120bd2017bcSVladimir Sementsov-Ogievskiy 121bd2017bcSVladimir Sementsov-Ogievskiy if gen_tracing: 122bd2017bcSVladimir Sementsov-Ogievskiy if ret_type: 123bd2017bcSVladimir Sementsov-Ogievskiy ret += mcgen(''' 124bd2017bcSVladimir Sementsov-Ogievskiy 125bd2017bcSVladimir Sementsov-Ogievskiy if (trace_event_get_state_backends(TRACE_QMP_EXIT_%(upper)s)) { 126bd2017bcSVladimir Sementsov-Ogievskiy g_autoptr(GString) ret_json = qobject_to_json(*ret); 127bd2017bcSVladimir Sementsov-Ogievskiy 128bd2017bcSVladimir Sementsov-Ogievskiy trace_qmp_exit_%(name)s(ret_json->str, true); 129bd2017bcSVladimir Sementsov-Ogievskiy } 130bd2017bcSVladimir Sementsov-Ogievskiy''', 131bd2017bcSVladimir Sementsov-Ogievskiy upper=upper, name=name) 132bd2017bcSVladimir Sementsov-Ogievskiy else: 133bd2017bcSVladimir Sementsov-Ogievskiy ret += mcgen(''' 134bd2017bcSVladimir Sementsov-Ogievskiy 135bd2017bcSVladimir Sementsov-Ogievskiy trace_qmp_exit_%(name)s("{}", true); 136bd2017bcSVladimir Sementsov-Ogievskiy''', 137bd2017bcSVladimir Sementsov-Ogievskiy name=name) 138bd2017bcSVladimir Sementsov-Ogievskiy 139fb0bc835SMarkus Armbruster return ret 140fb0bc835SMarkus Armbruster 141fb0bc835SMarkus Armbruster 1427304721fSJohn Snowdef gen_marshal_output(ret_type: QAPISchemaType) -> str: 143fb0bc835SMarkus Armbruster return mcgen(''' 144fb0bc835SMarkus Armbruster 14542c0dd12SJohn Snowstatic void qmp_marshal_output_%(c_name)s(%(c_type)s ret_in, 14642c0dd12SJohn Snow QObject **ret_out, Error **errp) 147fb0bc835SMarkus Armbruster{ 148fb0bc835SMarkus Armbruster Visitor *v; 149fb0bc835SMarkus Armbruster 15091fa93e5SMarkus Armbruster v = qobject_output_visitor_new_qmp(ret_out); 151cdd2b228SMarkus Armbruster if (visit_type_%(c_name)s(v, "unused", &ret_in, errp)) { 152fb0bc835SMarkus Armbruster visit_complete(v, ret_out); 153fb0bc835SMarkus Armbruster } 154fb0bc835SMarkus Armbruster visit_free(v); 155fb0bc835SMarkus Armbruster v = qapi_dealloc_visitor_new(); 156fb0bc835SMarkus Armbruster visit_type_%(c_name)s(v, "unused", &ret_in, NULL); 157fb0bc835SMarkus Armbruster visit_free(v); 158fb0bc835SMarkus Armbruster} 159fb0bc835SMarkus Armbruster''', 160fb0bc835SMarkus Armbruster c_type=ret_type.c_type(), c_name=ret_type.c_name()) 161fb0bc835SMarkus Armbruster 162fb0bc835SMarkus Armbruster 163cf9d4e68SPaolo Bonzinidef build_marshal_proto(name: str, 164cf9d4e68SPaolo Bonzini coroutine: bool) -> str: 165cf9d4e68SPaolo Bonzini return ('void %(coroutine_fn)sqmp_marshal_%(c_name)s(%(params)s)' % { 166cf9d4e68SPaolo Bonzini 'coroutine_fn': 'coroutine_fn ' if coroutine else '', 167cf9d4e68SPaolo Bonzini 'c_name': c_name(name), 168cf9d4e68SPaolo Bonzini 'params': 'QDict *args, QObject **ret, Error **errp', 169cf9d4e68SPaolo Bonzini }) 170fb0bc835SMarkus Armbruster 171fb0bc835SMarkus Armbruster 172cf9d4e68SPaolo Bonzinidef gen_marshal_decl(name: str, 173cf9d4e68SPaolo Bonzini coroutine: bool) -> str: 174fb0bc835SMarkus Armbruster return mcgen(''' 175fb0bc835SMarkus Armbruster%(proto)s; 176fb0bc835SMarkus Armbruster''', 177cf9d4e68SPaolo Bonzini proto=build_marshal_proto(name, coroutine)) 178fb0bc835SMarkus Armbruster 179fb0bc835SMarkus Armbruster 180bd2017bcSVladimir Sementsov-Ogievskiydef gen_trace(name: str) -> str: 181bd2017bcSVladimir Sementsov-Ogievskiy return mcgen(''' 182bd2017bcSVladimir Sementsov-Ogievskiyqmp_enter_%(name)s(const char *json) "%%s" 183bd2017bcSVladimir Sementsov-Ogievskiyqmp_exit_%(name)s(const char *result, bool succeeded) "%%s %%d" 184bd2017bcSVladimir Sementsov-Ogievskiy''', 185bd2017bcSVladimir Sementsov-Ogievskiy name=c_name(name)) 186bd2017bcSVladimir Sementsov-Ogievskiy 187bd2017bcSVladimir Sementsov-Ogievskiy 1887304721fSJohn Snowdef gen_marshal(name: str, 1897304721fSJohn Snow arg_type: Optional[QAPISchemaObjectType], 1907304721fSJohn Snow boxed: bool, 191bd2017bcSVladimir Sementsov-Ogievskiy ret_type: Optional[QAPISchemaType], 192cf9d4e68SPaolo Bonzini gen_tracing: bool, 193cf9d4e68SPaolo Bonzini coroutine: bool) -> str: 194675b214bSMarkus Armbruster have_args = boxed or (arg_type and not arg_type.is_empty()) 195ec9697abSJohn Snow if have_args: 196ec9697abSJohn Snow assert arg_type is not None 197ec9697abSJohn Snow arg_type_c_name = arg_type.c_name() 198fb0bc835SMarkus Armbruster 199fb0bc835SMarkus Armbruster ret = mcgen(''' 200fb0bc835SMarkus Armbruster 201fb0bc835SMarkus Armbruster%(proto)s 202fb0bc835SMarkus Armbruster{ 203fb0bc835SMarkus Armbruster Error *err = NULL; 204cdd2b228SMarkus Armbruster bool ok = false; 2052061487bSMarkus Armbruster Visitor *v; 206fb0bc835SMarkus Armbruster''', 207cf9d4e68SPaolo Bonzini proto=build_marshal_proto(name, coroutine)) 208fb0bc835SMarkus Armbruster 209fb0bc835SMarkus Armbruster if ret_type: 210fb0bc835SMarkus Armbruster ret += mcgen(''' 211fb0bc835SMarkus Armbruster %(c_type)s retval; 212fb0bc835SMarkus Armbruster''', 213fb0bc835SMarkus Armbruster c_type=ret_type.c_type()) 214fb0bc835SMarkus Armbruster 215fb0bc835SMarkus Armbruster if have_args: 216fb0bc835SMarkus Armbruster ret += mcgen(''' 217fb0bc835SMarkus Armbruster %(c_name)s arg = {0}; 218fb0bc835SMarkus Armbruster''', 219ec9697abSJohn Snow c_name=arg_type_c_name) 220fb0bc835SMarkus Armbruster 221fb0bc835SMarkus Armbruster ret += mcgen(''' 2222061487bSMarkus Armbruster 223db291641SMarkus Armbruster v = qobject_input_visitor_new_qmp(QOBJECT(args)); 224cdd2b228SMarkus Armbruster if (!visit_start_struct(v, NULL, NULL, 0, errp)) { 225fb0bc835SMarkus Armbruster goto out; 226fb0bc835SMarkus Armbruster } 22789bf68f9SMarkus Armbruster''') 22889bf68f9SMarkus Armbruster 22989bf68f9SMarkus Armbruster if have_args: 23089bf68f9SMarkus Armbruster ret += mcgen(''' 231cdd2b228SMarkus Armbruster if (visit_type_%(c_arg_type)s_members(v, &arg, errp)) { 232cdd2b228SMarkus Armbruster ok = visit_check_struct(v, errp); 233fb0bc835SMarkus Armbruster } 23489bf68f9SMarkus Armbruster''', 235ec9697abSJohn Snow c_arg_type=arg_type_c_name) 23689bf68f9SMarkus Armbruster else: 23789bf68f9SMarkus Armbruster ret += mcgen(''' 238cdd2b228SMarkus Armbruster ok = visit_check_struct(v, errp); 23989bf68f9SMarkus Armbruster''') 24089bf68f9SMarkus Armbruster 24189bf68f9SMarkus Armbruster ret += mcgen(''' 242fb0bc835SMarkus Armbruster visit_end_struct(v, NULL); 243cdd2b228SMarkus Armbruster if (!ok) { 244fb0bc835SMarkus Armbruster goto out; 245fb0bc835SMarkus Armbruster } 24689bf68f9SMarkus Armbruster''') 247fb0bc835SMarkus Armbruster 248bd2017bcSVladimir Sementsov-Ogievskiy ret += gen_call(name, arg_type, boxed, ret_type, gen_tracing) 249fb0bc835SMarkus Armbruster 250fb0bc835SMarkus Armbruster ret += mcgen(''' 251fb0bc835SMarkus Armbruster 252fb0bc835SMarkus Armbrusterout: 253fb0bc835SMarkus Armbruster visit_free(v); 254fb0bc835SMarkus Armbruster''') 255fb0bc835SMarkus Armbruster 256fb0bc835SMarkus Armbruster ret += mcgen(''' 257fb0bc835SMarkus Armbruster v = qapi_dealloc_visitor_new(); 258fb0bc835SMarkus Armbruster visit_start_struct(v, NULL, NULL, 0, NULL); 25989bf68f9SMarkus Armbruster''') 26089bf68f9SMarkus Armbruster 26189bf68f9SMarkus Armbruster if have_args: 26289bf68f9SMarkus Armbruster ret += mcgen(''' 26389bf68f9SMarkus Armbruster visit_type_%(c_arg_type)s_members(v, &arg, NULL); 26489bf68f9SMarkus Armbruster''', 265ec9697abSJohn Snow c_arg_type=arg_type_c_name) 26689bf68f9SMarkus Armbruster 26789bf68f9SMarkus Armbruster ret += mcgen(''' 268fb0bc835SMarkus Armbruster visit_end_struct(v, NULL); 269fb0bc835SMarkus Armbruster visit_free(v); 27089bf68f9SMarkus Armbruster''') 271fb0bc835SMarkus Armbruster 272fb0bc835SMarkus Armbruster ret += mcgen(''' 273fb0bc835SMarkus Armbruster} 274fb0bc835SMarkus Armbruster''') 275fb0bc835SMarkus Armbruster return ret 276fb0bc835SMarkus Armbruster 277fb0bc835SMarkus Armbruster 2787304721fSJohn Snowdef gen_register_command(name: str, 279d2032598SMarkus Armbruster features: List[QAPISchemaFeature], 2807304721fSJohn Snow success_response: bool, 2817304721fSJohn Snow allow_oob: bool, 2827304721fSJohn Snow allow_preconfig: bool, 2837304721fSJohn Snow coroutine: bool) -> str: 284876c6751SPeter Xu options = [] 285876c6751SPeter Xu 286fb0bc835SMarkus Armbruster if not success_response: 287876c6751SPeter Xu options += ['QCO_NO_SUCCESS_RESP'] 288876c6751SPeter Xu if allow_oob: 289876c6751SPeter Xu options += ['QCO_ALLOW_OOB'] 290d6fe3d02SIgor Mammedov if allow_preconfig: 291d6fe3d02SIgor Mammedov options += ['QCO_ALLOW_PRECONFIG'] 29204f22362SKevin Wolf if coroutine: 29304f22362SKevin Wolf options += ['QCO_COROUTINE'] 294876c6751SPeter Xu 295fb0bc835SMarkus Armbruster ret = mcgen(''' 296fb0bc835SMarkus Armbruster qmp_register_command(cmds, "%(name)s", 2976604e475SMarkus Armbruster qmp_marshal_%(c_name)s, %(opts)s, %(feats)s); 298fb0bc835SMarkus Armbruster''', 299fb0bc835SMarkus Armbruster name=name, c_name=c_name(name), 3006604e475SMarkus Armbruster opts=' | '.join(options) or 0, 3016604e475SMarkus Armbruster feats=gen_special_features(features)) 302fb0bc835SMarkus Armbruster return ret 303fb0bc835SMarkus Armbruster 304fb0bc835SMarkus Armbruster 305252dc310SMarkus Armbrusterclass QAPISchemaGenCommandVisitor(QAPISchemaModularCVisitor): 306bd2017bcSVladimir Sementsov-Ogievskiy def __init__(self, prefix: str, gen_tracing: bool): 3072cae67bcSMarkus Armbruster super().__init__( 3082cae67bcSMarkus Armbruster prefix, 'qapi-commands', 309bd2017bcSVladimir Sementsov-Ogievskiy ' * Schema-defined QAPI/QMP commands', None, __doc__, 310bd2017bcSVladimir Sementsov-Ogievskiy gen_tracing=gen_tracing) 3117304721fSJohn Snow self._visited_ret_types: Dict[QAPIGenC, Set[QAPISchemaType]] = {} 312bd2017bcSVladimir Sementsov-Ogievskiy self._gen_tracing = gen_tracing 313252dc310SMarkus Armbruster 3147304721fSJohn Snow def _begin_user_module(self, name: str) -> None: 315252dc310SMarkus Armbruster self._visited_ret_types[self._genc] = set() 3169af23989SMarkus Armbruster commands = self._module_basename('qapi-commands', name) 3179af23989SMarkus Armbruster types = self._module_basename('qapi-types', name) 3189af23989SMarkus Armbruster visit = self._module_basename('qapi-visit', name) 31971b3f045SMarkus Armbruster self._genc.add(mcgen(''' 320fb0bc835SMarkus Armbruster#include "qemu/osdep.h" 32191fa93e5SMarkus Armbruster#include "qapi/compat-policy.h" 322fb0bc835SMarkus Armbruster#include "qapi/visitor.h" 323fb0bc835SMarkus Armbruster#include "qapi/qmp/qdict.h" 324fb0bc835SMarkus Armbruster#include "qapi/dealloc-visitor.h" 325fb0bc835SMarkus Armbruster#include "qapi/error.h" 3269af23989SMarkus Armbruster#include "%(visit)s.h" 3279af23989SMarkus Armbruster#include "%(commands)s.h" 328fb0bc835SMarkus Armbruster''', 3299af23989SMarkus Armbruster commands=commands, visit=visit)) 330bd2017bcSVladimir Sementsov-Ogievskiy 331bd2017bcSVladimir Sementsov-Ogievskiy if self._gen_tracing and commands != 'qapi-commands': 332bd2017bcSVladimir Sementsov-Ogievskiy self._genc.add(mcgen(''' 333bd2017bcSVladimir Sementsov-Ogievskiy#include "qapi/qmp/qjson.h" 334bd2017bcSVladimir Sementsov-Ogievskiy#include "trace/trace-%(nm)s_trace_events.h" 335bd2017bcSVladimir Sementsov-Ogievskiy''', 336bd2017bcSVladimir Sementsov-Ogievskiy nm=c_name(commands, protect=False))) 337bd2017bcSVladimir Sementsov-Ogievskiy # We use c_name(commands, protect=False) to turn '-' into '_', to 338bd2017bcSVladimir Sementsov-Ogievskiy # match .underscorify() in trace/meson.build 339bd2017bcSVladimir Sementsov-Ogievskiy 34071b3f045SMarkus Armbruster self._genh.add(mcgen(''' 3419af23989SMarkus Armbruster#include "%(types)s.h" 342fb0bc835SMarkus Armbruster 343fb0bc835SMarkus Armbruster''', 3449af23989SMarkus Armbruster types=types)) 345fb0bc835SMarkus Armbruster 346c6cd7e41SMarkus Armbruster def visit_begin(self, schema: QAPISchema) -> None: 3474ab0ff6dSMarkus Armbruster self._add_module('./init', ' * QAPI Commands initialization') 34800ca24ffSMarkus Armbruster self._genh.add(mcgen(''' 34900ca24ffSMarkus Armbruster#include "qapi/qmp/dispatch.h" 35000ca24ffSMarkus Armbruster 351252dc310SMarkus Armbrustervoid %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds); 352252dc310SMarkus Armbruster''', 353252dc310SMarkus Armbruster c_prefix=c_name(self._prefix, protect=False))) 354c6cd7e41SMarkus Armbruster self._genc.add(mcgen(''' 35500ca24ffSMarkus Armbruster#include "qemu/osdep.h" 35600ca24ffSMarkus Armbruster#include "%(prefix)sqapi-commands.h" 35700ca24ffSMarkus Armbruster#include "%(prefix)sqapi-init-commands.h" 358c6cd7e41SMarkus Armbruster 359c6cd7e41SMarkus Armbrustervoid %(c_prefix)sqmp_init_marshal(QmpCommandList *cmds) 360c6cd7e41SMarkus Armbruster{ 361c6cd7e41SMarkus Armbruster QTAILQ_INIT(cmds); 362c6cd7e41SMarkus Armbruster 36300ca24ffSMarkus Armbruster''', 364c6cd7e41SMarkus Armbruster prefix=self._prefix, 365c6cd7e41SMarkus Armbruster c_prefix=c_name(self._prefix, protect=False))) 366c6cd7e41SMarkus Armbruster 367c6cd7e41SMarkus Armbruster def visit_end(self) -> None: 368c6cd7e41SMarkus Armbruster with self._temp_module('./init'): 369c6cd7e41SMarkus Armbruster self._genc.add(mcgen(''' 370c6cd7e41SMarkus Armbruster} 371c6cd7e41SMarkus Armbruster''')) 37271b3f045SMarkus Armbruster 3737304721fSJohn Snow def visit_command(self, 3747304721fSJohn Snow name: str, 3754a82e468SJohn Snow info: Optional[QAPISourceInfo], 376f17539c8SMarc-André Lureau ifcond: QAPISchemaIfCond, 3777304721fSJohn Snow features: List[QAPISchemaFeature], 3787304721fSJohn Snow arg_type: Optional[QAPISchemaObjectType], 3797304721fSJohn Snow ret_type: Optional[QAPISchemaType], 3807304721fSJohn Snow gen: bool, 3817304721fSJohn Snow success_response: bool, 3827304721fSJohn Snow boxed: bool, 3837304721fSJohn Snow allow_oob: bool, 3847304721fSJohn Snow allow_preconfig: bool, 3857304721fSJohn Snow coroutine: bool) -> None: 38671b3f045SMarkus Armbruster if not gen: 38771b3f045SMarkus Armbruster return 3881f7b9f31SMarc-André Lureau # FIXME: If T is a user-defined type, the user is responsible 3891f7b9f31SMarc-André Lureau # for making this work, i.e. to make T's condition the 3901f7b9f31SMarc-André Lureau # conjunction of the T-returning commands' conditions. If T 3911f7b9f31SMarc-André Lureau # is a built-in type, this isn't possible: the 3921f7b9f31SMarc-André Lureau # qmp_marshal_output_T() will be generated unconditionally. 393252dc310SMarkus Armbruster if ret_type and ret_type not in self._visited_ret_types[self._genc]: 394252dc310SMarkus Armbruster self._visited_ret_types[self._genc].add(ret_type) 3951f7b9f31SMarc-André Lureau with ifcontext(ret_type.ifcond, 396c6cd7e41SMarkus Armbruster self._genh, self._genc): 39771b3f045SMarkus Armbruster self._genc.add(gen_marshal_output(ret_type)) 398c6cd7e41SMarkus Armbruster with ifcontext(ifcond, self._genh, self._genc): 399cf9d4e68SPaolo Bonzini self._genh.add(gen_command_decl(name, arg_type, boxed, 400cf9d4e68SPaolo Bonzini ret_type, coroutine)) 401cf9d4e68SPaolo Bonzini self._genh.add(gen_marshal_decl(name, coroutine)) 402bd2017bcSVladimir Sementsov-Ogievskiy self._genc.add(gen_marshal(name, arg_type, boxed, ret_type, 403cf9d4e68SPaolo Bonzini self._gen_tracing, coroutine)) 404bd2017bcSVladimir Sementsov-Ogievskiy if self._gen_tracing: 405bd2017bcSVladimir Sementsov-Ogievskiy self._gen_trace_events.add(gen_trace(name)) 406c6cd7e41SMarkus Armbruster with self._temp_module('./init'): 407c6cd7e41SMarkus Armbruster with ifcontext(ifcond, self._genh, self._genc): 408d2032598SMarkus Armbruster self._genc.add(gen_register_command( 409d2032598SMarkus Armbruster name, features, success_response, allow_oob, 410d2032598SMarkus Armbruster allow_preconfig, coroutine)) 41171b3f045SMarkus Armbruster 41271b3f045SMarkus Armbruster 4137304721fSJohn Snowdef gen_commands(schema: QAPISchema, 4147304721fSJohn Snow output_dir: str, 415bd2017bcSVladimir Sementsov-Ogievskiy prefix: str, 416bd2017bcSVladimir Sementsov-Ogievskiy gen_tracing: bool) -> None: 417bd2017bcSVladimir Sementsov-Ogievskiy vis = QAPISchemaGenCommandVisitor(prefix, gen_tracing) 418fb0bc835SMarkus Armbruster schema.visit(vis) 41971b3f045SMarkus Armbruster vis.write(output_dir) 420