blob: d19acda7d3394bf41ef32f559414b336939829f8 [file] [log] [blame]
Wenchao Xia21cd70d2014-06-18 08:43:28 +02001#
2# QAPI event generator
3#
4# Copyright (c) 2014 Wenchao Xia
Markus Armbruster05f43a92015-09-16 13:06:14 +02005# Copyright (c) 2015 Red Hat Inc.
Wenchao Xia21cd70d2014-06-18 08:43:28 +02006#
7# Authors:
8# Wenchao Xia <wenchaoqemu@gmail.com>
Markus Armbruster05f43a92015-09-16 13:06:14 +02009# Markus Armbruster <armbru@redhat.com>
Wenchao Xia21cd70d2014-06-18 08:43:28 +020010#
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
Wenchao Xia21cd70d2014-06-18 08:43:28 +020014from qapi import *
Wenchao Xia21cd70d2014-06-18 08:43:28 +020015
16def _generate_event_api_name(event_name, params):
Eric Blake18df5152015-05-14 06:50:48 -060017 api_name = "void qapi_event_send_%s(" % c_name(event_name).lower();
Wenchao Xia21cd70d2014-06-18 08:43:28 +020018 l = len(api_name)
19
20 if params:
Markus Armbruster05f43a92015-09-16 13:06:14 +020021 for m in params.members:
22 if m.optional:
23 api_name += "bool has_%s,\n" % c_name(m.name)
Wenchao Xia21cd70d2014-06-18 08:43:28 +020024 api_name += "".ljust(l)
25
Markus Armbruster05f43a92015-09-16 13:06:14 +020026 api_name += "%s %s,\n" % (m.type.c_type(is_param=True),
27 c_name(m.name))
Wenchao Xia21cd70d2014-06-18 08:43:28 +020028 api_name += "".ljust(l)
29
30 api_name += "Error **errp)"
31 return api_name;
32
33
34# Following are the core functions that generate C APIs to emit event.
35
36def generate_event_declaration(api_name):
37 return mcgen('''
38
39%(api_name)s;
40''',
41 api_name = api_name)
42
43def generate_event_implement(api_name, event_name, params):
44 # step 1: declare any variables
45 ret = mcgen("""
46
47%(api_name)s
48{
49 QDict *qmp;
50 Error *local_err = NULL;
51 QMPEventFuncEmit emit;
52""",
53 api_name = api_name)
54
Markus Armbruster05f43a92015-09-16 13:06:14 +020055 if params and params.members:
Wenchao Xia21cd70d2014-06-18 08:43:28 +020056 ret += mcgen("""
57 QmpOutputVisitor *qov;
58 Visitor *v;
59 QObject *obj;
60
61""")
62
63 # step 2: check emit function, create a dict
64 ret += mcgen("""
65 emit = qmp_event_get_func_emit();
66 if (!emit) {
67 return;
68 }
69
70 qmp = qmp_event_build_dict("%(event_name)s");
71
72""",
73 event_name = event_name)
74
75 # step 3: visit the params if params != None
Markus Armbruster05f43a92015-09-16 13:06:14 +020076 if params and params.members:
Wenchao Xia21cd70d2014-06-18 08:43:28 +020077 ret += mcgen("""
78 qov = qmp_output_visitor_new();
79 g_assert(qov);
80
81 v = qmp_output_get_visitor(qov);
82 g_assert(v);
83
84 /* Fake visit, as if all members are under a structure */
85 visit_start_struct(v, NULL, "", "%(event_name)s", 0, &local_err);
86 if (local_err) {
87 goto clean;
88 }
89
90""",
91 event_name = event_name)
92
Markus Armbruster05f43a92015-09-16 13:06:14 +020093 for memb in params.members:
94 if memb.optional:
Wenchao Xia21cd70d2014-06-18 08:43:28 +020095 ret += mcgen("""
96 if (has_%(var)s) {
97""",
Markus Armbruster05f43a92015-09-16 13:06:14 +020098 var=c_name(memb.name))
Wenchao Xia21cd70d2014-06-18 08:43:28 +020099 push_indent()
100
Markus Armbruster05f43a92015-09-16 13:06:14 +0200101 if memb.type.name == "str":
Wenchao Xia21cd70d2014-06-18 08:43:28 +0200102 var_type = "(char **)"
103 else:
104 var_type = ""
105
106 ret += mcgen("""
107 visit_type_%(type)s(v, %(var_type)s&%(var)s, "%(name)s", &local_err);
108 if (local_err) {
109 goto clean;
110 }
111""",
112 var_type = var_type,
Markus Armbruster05f43a92015-09-16 13:06:14 +0200113 var=c_name(memb.name),
114 type=memb.type.c_name(),
115 name=memb.name)
Wenchao Xia21cd70d2014-06-18 08:43:28 +0200116
Markus Armbruster05f43a92015-09-16 13:06:14 +0200117 if memb.optional:
Wenchao Xia21cd70d2014-06-18 08:43:28 +0200118 pop_indent()
119 ret += mcgen("""
120 }
121""")
122
123 ret += mcgen("""
124
125 visit_end_struct(v, &local_err);
126 if (local_err) {
127 goto clean;
128 }
129
130 obj = qmp_output_get_qobject(qov);
131 g_assert(obj != NULL);
132
133 qdict_put_obj(qmp, "data", obj);
134""")
135
136 # step 4: call qmp event api
137 ret += mcgen("""
138 emit(%(event_enum_value)s, qmp, &local_err);
139
140""",
Markus Armbruster7b246262015-09-16 13:06:13 +0200141 event_enum_value = c_enum_const(event_enum_name, event_name))
Wenchao Xia21cd70d2014-06-18 08:43:28 +0200142
143 # step 5: clean up
Markus Armbruster05f43a92015-09-16 13:06:14 +0200144 if params and params.members:
Wenchao Xia21cd70d2014-06-18 08:43:28 +0200145 ret += mcgen("""
146 clean:
147 qmp_output_visitor_cleanup(qov);
148""")
149 ret += mcgen("""
150 error_propagate(errp, local_err);
151 QDECREF(qmp);
152}
153""")
154
155 return ret
156
Markus Armbruster05f43a92015-09-16 13:06:14 +0200157
158class QAPISchemaGenEventVisitor(QAPISchemaVisitor):
159 def __init__(self):
160 self.decl = None
161 self.defn = None
162 self._event_names = None
163
164 def visit_begin(self, schema):
165 self.decl = ''
166 self.defn = ''
167 self._event_names = []
168
169 def visit_end(self):
170 self.decl += generate_enum(event_enum_name, self._event_names)
171 self.defn += generate_enum_lookup(event_enum_name, self._event_names)
172 self._event_names = None
173
174 def visit_event(self, name, info, arg_type):
175 api_name = _generate_event_api_name(name, arg_type)
176 self.decl += generate_event_declaration(api_name)
177 self.defn += generate_event_implement(api_name, name, arg_type)
178 self._event_names.append(name)
179
180
Markus Armbruster2114f5a2015-04-02 13:12:21 +0200181(input_file, output_dir, do_c, do_h, prefix, dummy) = parse_command_line()
Wenchao Xia21cd70d2014-06-18 08:43:28 +0200182
Markus Armbruster12f8e1b2015-04-02 14:46:39 +0200183c_comment = '''
Wenchao Xia21cd70d2014-06-18 08:43:28 +0200184/*
185 * schema-defined QAPI event functions
186 *
187 * Copyright (c) 2014 Wenchao Xia
188 *
189 * Authors:
190 * Wenchao Xia <wenchaoqemu@gmail.com>
191 *
192 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
193 * See the COPYING.LIB file in the top-level directory.
194 *
195 */
Markus Armbruster12f8e1b2015-04-02 14:46:39 +0200196'''
197h_comment = '''
Wenchao Xia21cd70d2014-06-18 08:43:28 +0200198/*
199 * schema-defined QAPI event functions
200 *
201 * Copyright (c) 2014 Wenchao Xia
202 *
203 * Authors:
204 * Wenchao Xia <wenchaoqemu@gmail.com>
205 *
206 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
207 * See the COPYING.LIB file in the top-level directory.
208 *
209 */
Markus Armbruster12f8e1b2015-04-02 14:46:39 +0200210'''
Wenchao Xia21cd70d2014-06-18 08:43:28 +0200211
Markus Armbruster12f8e1b2015-04-02 14:46:39 +0200212(fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix,
213 'qapi-event.c', 'qapi-event.h',
214 c_comment, h_comment)
Wenchao Xia21cd70d2014-06-18 08:43:28 +0200215
Markus Armbruster12f8e1b2015-04-02 14:46:39 +0200216fdef.write(mcgen('''
217#include "qemu-common.h"
218#include "%(prefix)sqapi-event.h"
219#include "%(prefix)sqapi-visit.h"
220#include "qapi/qmp-output-visitor.h"
221#include "qapi/qmp-event.h"
222
223''',
224 prefix=prefix))
225
226fdecl.write(mcgen('''
Wenchao Xia21cd70d2014-06-18 08:43:28 +0200227#include "qapi/error.h"
228#include "qapi/qmp/qdict.h"
229#include "%(prefix)sqapi-types.h"
230
231''',
Markus Armbruster12f8e1b2015-04-02 14:46:39 +0200232 prefix=prefix))
Wenchao Xia21cd70d2014-06-18 08:43:28 +0200233
Markus Armbruster016a3352015-07-01 12:59:40 +0200234event_enum_name = c_name(prefix + "QAPIEvent", protect=False)
Wenchao Xia21cd70d2014-06-18 08:43:28 +0200235
Markus Armbruster05f43a92015-09-16 13:06:14 +0200236schema = QAPISchema(input_file)
237gen = QAPISchemaGenEventVisitor()
238schema.visit(gen)
239fdef.write(gen.defn)
240fdecl.write(gen.decl)
Wenchao Xia21cd70d2014-06-18 08:43:28 +0200241
Markus Armbruster12f8e1b2015-04-02 14:46:39 +0200242close_output(fdef, fdecl)