1# 2# QAPI event generator 3# 4# Copyright (c) 2014 Wenchao Xia 5# 6# Authors: 7# Wenchao Xia <wenchaoqemu@gmail.com> 8# 9# This work is licensed under the terms of the GNU GPL, version 2. 10# See the COPYING file in the top-level directory. 11 12from ordereddict import OrderedDict 13from qapi import * 14 15def _generate_event_api_name(event_name, params): 16 api_name = "void qapi_event_send_%s(" % c_name(event_name).lower(); 17 l = len(api_name) 18 19 if params: 20 for argname, argentry, optional in parse_args(params): 21 if optional: 22 api_name += "bool has_%s,\n" % c_name(argname) 23 api_name += "".ljust(l) 24 25 api_name += "%s %s,\n" % (c_type(argentry, is_param=True), 26 c_name(argname)) 27 api_name += "".ljust(l) 28 29 api_name += "Error **errp)" 30 return api_name; 31 32 33# Following are the core functions that generate C APIs to emit event. 34 35def generate_event_declaration(api_name): 36 return mcgen(''' 37 38%(api_name)s; 39''', 40 api_name = api_name) 41 42def generate_event_implement(api_name, event_name, params): 43 # step 1: declare any variables 44 ret = mcgen(""" 45 46%(api_name)s 47{ 48 QDict *qmp; 49 Error *local_err = NULL; 50 QMPEventFuncEmit emit; 51""", 52 api_name = api_name) 53 54 if params: 55 ret += mcgen(""" 56 QmpOutputVisitor *qov; 57 Visitor *v; 58 QObject *obj; 59 60""") 61 62 # step 2: check emit function, create a dict 63 ret += mcgen(""" 64 emit = qmp_event_get_func_emit(); 65 if (!emit) { 66 return; 67 } 68 69 qmp = qmp_event_build_dict("%(event_name)s"); 70 71""", 72 event_name = event_name) 73 74 # step 3: visit the params if params != None 75 if params: 76 ret += mcgen(""" 77 qov = qmp_output_visitor_new(); 78 g_assert(qov); 79 80 v = qmp_output_get_visitor(qov); 81 g_assert(v); 82 83 /* Fake visit, as if all members are under a structure */ 84 visit_start_struct(v, NULL, "", "%(event_name)s", 0, &local_err); 85 if (local_err) { 86 goto clean; 87 } 88 89""", 90 event_name = event_name) 91 92 for argname, argentry, optional in parse_args(params): 93 if optional: 94 ret += mcgen(""" 95 if (has_%(var)s) { 96""", 97 var = c_name(argname)) 98 push_indent() 99 100 if argentry == "str": 101 var_type = "(char **)" 102 else: 103 var_type = "" 104 105 ret += mcgen(""" 106 visit_type_%(type)s(v, %(var_type)s&%(var)s, "%(name)s", &local_err); 107 if (local_err) { 108 goto clean; 109 } 110""", 111 var_type = var_type, 112 var = c_name(argname), 113 type = type_name(argentry), 114 name = argname) 115 116 if optional: 117 pop_indent() 118 ret += mcgen(""" 119 } 120""") 121 122 ret += mcgen(""" 123 124 visit_end_struct(v, &local_err); 125 if (local_err) { 126 goto clean; 127 } 128 129 obj = qmp_output_get_qobject(qov); 130 g_assert(obj != NULL); 131 132 qdict_put_obj(qmp, "data", obj); 133""") 134 135 # step 4: call qmp event api 136 ret += mcgen(""" 137 emit(%(event_enum_value)s, qmp, &local_err); 138 139""", 140 event_enum_value = c_enum_const(event_enum_name, event_name)) 141 142 # step 5: clean up 143 if params: 144 ret += mcgen(""" 145 clean: 146 qmp_output_visitor_cleanup(qov); 147""") 148 ret += mcgen(""" 149 error_propagate(errp, local_err); 150 QDECREF(qmp); 151} 152""") 153 154 return ret 155 156(input_file, output_dir, do_c, do_h, prefix, dummy) = parse_command_line() 157 158c_comment = ''' 159/* 160 * schema-defined QAPI event functions 161 * 162 * Copyright (c) 2014 Wenchao Xia 163 * 164 * Authors: 165 * Wenchao Xia <wenchaoqemu@gmail.com> 166 * 167 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. 168 * See the COPYING.LIB file in the top-level directory. 169 * 170 */ 171''' 172h_comment = ''' 173/* 174 * schema-defined QAPI event functions 175 * 176 * Copyright (c) 2014 Wenchao Xia 177 * 178 * Authors: 179 * Wenchao Xia <wenchaoqemu@gmail.com> 180 * 181 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. 182 * See the COPYING.LIB file in the top-level directory. 183 * 184 */ 185''' 186 187(fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix, 188 'qapi-event.c', 'qapi-event.h', 189 c_comment, h_comment) 190 191fdef.write(mcgen(''' 192#include "qemu-common.h" 193#include "%(prefix)sqapi-event.h" 194#include "%(prefix)sqapi-visit.h" 195#include "qapi/qmp-output-visitor.h" 196#include "qapi/qmp-event.h" 197 198''', 199 prefix=prefix)) 200 201fdecl.write(mcgen(''' 202#include "qapi/error.h" 203#include "qapi/qmp/qdict.h" 204#include "%(prefix)sqapi-types.h" 205 206''', 207 prefix=prefix)) 208 209exprs = QAPISchema(input_file).get_exprs() 210 211event_enum_name = c_name(prefix + "QAPIEvent", protect=False) 212event_names = [] 213 214for expr in exprs: 215 if expr.has_key('event'): 216 event_name = expr['event'] 217 params = expr.get('data') 218 if params and len(params) == 0: 219 params = None 220 221 api_name = _generate_event_api_name(event_name, params) 222 ret = generate_event_declaration(api_name) 223 fdecl.write(ret) 224 225 # We need an enum value per event 226 ret = generate_event_implement(api_name, event_name, params) 227 fdef.write(ret) 228 229 # Record it, and generate enum later 230 event_names.append(event_name) 231 232ret = generate_enum(event_enum_name, event_names) 233fdecl.write(ret) 234ret = generate_enum_lookup(event_enum_name, event_names) 235fdef.write(ret) 236 237close_output(fdef, fdecl) 238