1# 2# QAPI event generator 3# 4# Copyright (c) 2014 Wenchao Xia 5# Copyright (c) 2015 Red Hat Inc. 6# 7# Authors: 8# Wenchao Xia <wenchaoqemu@gmail.com> 9# Markus Armbruster <armbru@redhat.com> 10# 11# This work is licensed under the terms of the GNU GPL, version 2. 12# See the COPYING file in the top-level directory. 13 14from qapi import * 15 16 17def gen_event_send_proto(name, arg_type): 18 return 'void qapi_event_send_%(c_name)s(%(param)s)' % { 19 'c_name': c_name(name.lower()), 20 'param': gen_params(arg_type, 'Error **errp')} 21 22 23def gen_event_send_decl(name, arg_type): 24 return mcgen(''' 25 26%(proto)s; 27''', 28 proto=gen_event_send_proto(name, arg_type)) 29 30 31def gen_event_send(name, arg_type): 32 ret = mcgen(''' 33 34%(proto)s 35{ 36 QDict *qmp; 37 Error *err = NULL; 38 QMPEventFuncEmit emit; 39''', 40 proto=gen_event_send_proto(name, arg_type)) 41 42 if arg_type and arg_type.members: 43 ret += mcgen(''' 44 QmpOutputVisitor *qov; 45 Visitor *v; 46 QObject *obj; 47 48''') 49 50 ret += mcgen(''' 51 emit = qmp_event_get_func_emit(); 52 if (!emit) { 53 return; 54 } 55 56 qmp = qmp_event_build_dict("%(name)s"); 57 58''', 59 name=name) 60 61 if arg_type and arg_type.members: 62 ret += mcgen(''' 63 qov = qmp_output_visitor_new(); 64 g_assert(qov); 65 66 v = qmp_output_get_visitor(qov); 67 g_assert(v); 68 69 /* Fake visit, as if all members are under a structure */ 70 visit_start_struct(v, NULL, "", "%(name)s", 0, &err); 71 if (err) { 72 goto clean; 73 } 74 75''', 76 name=name) 77 78 for memb in arg_type.members: 79 if memb.optional: 80 ret += mcgen(''' 81 if (has_%(c_name)s) { 82''', 83 c_name=c_name(memb.name)) 84 push_indent() 85 86 # Ugly: need to cast away the const 87 if memb.type.name == "str": 88 cast = '(char **)' 89 else: 90 cast = '' 91 92 ret += mcgen(''' 93 visit_type_%(c_type)s(v, %(cast)s&%(c_name)s, "%(name)s", &err); 94 if (err) { 95 goto clean; 96 } 97''', 98 cast=cast, 99 c_name=c_name(memb.name), 100 c_type=memb.type.c_name(), 101 name=memb.name) 102 103 if memb.optional: 104 pop_indent() 105 ret += mcgen(''' 106 } 107''') 108 109 ret += mcgen(''' 110 111 visit_end_struct(v, &err); 112 if (err) { 113 goto clean; 114 } 115 116 obj = qmp_output_get_qobject(qov); 117 g_assert(obj != NULL); 118 119 qdict_put_obj(qmp, "data", obj); 120''') 121 122 ret += mcgen(''' 123 emit(%(c_enum)s, qmp, &err); 124 125''', 126 c_enum=c_enum_const(event_enum_name, name)) 127 128 if arg_type and arg_type.members: 129 ret += mcgen(''' 130 clean: 131 qmp_output_visitor_cleanup(qov); 132''') 133 ret += mcgen(''' 134 error_propagate(errp, err); 135 QDECREF(qmp); 136} 137''') 138 return ret 139 140 141class QAPISchemaGenEventVisitor(QAPISchemaVisitor): 142 def __init__(self): 143 self.decl = None 144 self.defn = None 145 self._event_names = None 146 147 def visit_begin(self, schema): 148 self.decl = '' 149 self.defn = '' 150 self._event_names = [] 151 152 def visit_end(self): 153 self.decl += gen_enum(event_enum_name, self._event_names) 154 self.defn += gen_enum_lookup(event_enum_name, self._event_names) 155 self._event_names = None 156 157 def visit_event(self, name, info, arg_type): 158 self.decl += gen_event_send_decl(name, arg_type) 159 self.defn += gen_event_send(name, arg_type) 160 self._event_names.append(name) 161 162 163(input_file, output_dir, do_c, do_h, prefix, dummy) = parse_command_line() 164 165c_comment = ''' 166/* 167 * schema-defined QAPI event functions 168 * 169 * Copyright (c) 2014 Wenchao Xia 170 * 171 * Authors: 172 * Wenchao Xia <wenchaoqemu@gmail.com> 173 * 174 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. 175 * See the COPYING.LIB file in the top-level directory. 176 * 177 */ 178''' 179h_comment = ''' 180/* 181 * schema-defined QAPI event functions 182 * 183 * Copyright (c) 2014 Wenchao Xia 184 * 185 * Authors: 186 * Wenchao Xia <wenchaoqemu@gmail.com> 187 * 188 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. 189 * See the COPYING.LIB file in the top-level directory. 190 * 191 */ 192''' 193 194(fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix, 195 'qapi-event.c', 'qapi-event.h', 196 c_comment, h_comment) 197 198fdef.write(mcgen(''' 199#include "qemu-common.h" 200#include "%(prefix)sqapi-event.h" 201#include "%(prefix)sqapi-visit.h" 202#include "qapi/qmp-output-visitor.h" 203#include "qapi/qmp-event.h" 204 205''', 206 prefix=prefix)) 207 208fdecl.write(mcgen(''' 209#include "qapi/error.h" 210#include "qapi/qmp/qdict.h" 211#include "%(prefix)sqapi-types.h" 212 213''', 214 prefix=prefix)) 215 216event_enum_name = c_name(prefix + "QAPIEvent", protect=False) 217 218schema = QAPISchema(input_file) 219gen = QAPISchemaGenEventVisitor() 220schema.visit(gen) 221fdef.write(gen.defn) 222fdecl.write(gen.decl) 223 224close_output(fdef, fdecl) 225