]>
Commit | Line | Data |
---|---|---|
5ddeec83 MA |
1 | """ |
2 | QAPI event generator | |
3 | ||
4 | Copyright (c) 2014 Wenchao Xia | |
5 | Copyright (c) 2015-2018 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 | """ | |
21cd70df | 14 | |
fb0bc835 | 15 | from qapi.common import * |
21cd70df | 16 | |
e98859a9 | 17 | |
086ee7a6 | 18 | def build_event_send_proto(name, arg_type, boxed): |
03b4367a MA |
19 | return 'void qapi_event_send_%(c_name)s(%(param)s)' % { |
20 | 'c_name': c_name(name.lower()), | |
086ee7a6 | 21 | 'param': build_params(arg_type, boxed, 'Error **errp')} |
21cd70df | 22 | |
21cd70df | 23 | |
48825ca4 | 24 | def gen_event_send_decl(name, arg_type, boxed): |
21cd70df WX |
25 | return mcgen(''' |
26 | ||
e98859a9 | 27 | %(proto)s; |
21cd70df | 28 | ''', |
086ee7a6 | 29 | proto=build_event_send_proto(name, arg_type, boxed)) |
e98859a9 | 30 | |
21cd70df | 31 | |
086ee7a6 | 32 | # Declare and initialize an object 'qapi' using parameters from build_params() |
0949e95b EB |
33 | def gen_param_var(typ): |
34 | assert not typ.variants | |
35 | ret = mcgen(''' | |
36 | %(c_name)s param = { | |
37 | ''', | |
38 | c_name=typ.c_name()) | |
39 | sep = ' ' | |
40 | for memb in typ.members: | |
41 | ret += sep | |
42 | sep = ', ' | |
43 | if memb.optional: | |
44 | ret += 'has_' + c_name(memb.name) + sep | |
45 | if memb.type.name == 'str': | |
086ee7a6 | 46 | # Cast away const added in build_params() |
0949e95b EB |
47 | ret += '(char *)' |
48 | ret += c_name(memb.name) | |
49 | ret += mcgen(''' | |
50 | ||
51 | }; | |
52 | ''') | |
4d0b268f EB |
53 | if not typ.is_implicit(): |
54 | ret += mcgen(''' | |
55 | %(c_name)s *arg = ¶m; | |
56 | ''', | |
57 | c_name=typ.c_name()) | |
0949e95b EB |
58 | return ret |
59 | ||
60 | ||
93b564c4 | 61 | def gen_event_send(name, arg_type, boxed, event_enum_name): |
0949e95b EB |
62 | # FIXME: Our declaration of local variables (and of 'errp' in the |
63 | # parameter list) can collide with exploded members of the event's | |
64 | # data type passed in as parameters. If this collision ever hits in | |
65 | # practice, we can rename our local variables with a leading _ prefix, | |
66 | # or split the code into a wrapper function that creates a boxed | |
67 | # 'param' object then calls another to do the real work. | |
e98859a9 | 68 | ret = mcgen(''' |
21cd70df | 69 | |
e98859a9 | 70 | %(proto)s |
21cd70df WX |
71 | { |
72 | QDict *qmp; | |
2a0f50e8 | 73 | Error *err = NULL; |
21cd70df | 74 | QMPEventFuncEmit emit; |
e98859a9 | 75 | ''', |
086ee7a6 | 76 | proto=build_event_send_proto(name, arg_type, boxed)) |
21cd70df | 77 | |
b6167706 | 78 | if arg_type and not arg_type.is_empty(): |
e98859a9 | 79 | ret += mcgen(''' |
3b098d56 | 80 | QObject *obj; |
21cd70df | 81 | Visitor *v; |
e98859a9 | 82 | ''') |
c818408e EB |
83 | if not boxed: |
84 | ret += gen_param_var(arg_type) | |
85 | else: | |
86 | assert not boxed | |
21cd70df | 87 | |
e98859a9 | 88 | ret += mcgen(''' |
0949e95b | 89 | |
21cd70df WX |
90 | emit = qmp_event_get_func_emit(); |
91 | if (!emit) { | |
92 | return; | |
93 | } | |
94 | ||
e98859a9 | 95 | qmp = qmp_event_build_dict("%(name)s"); |
21cd70df | 96 | |
e98859a9 MA |
97 | ''', |
98 | name=name) | |
21cd70df | 99 | |
b6167706 | 100 | if arg_type and not arg_type.is_empty(): |
e98859a9 | 101 | ret += mcgen(''' |
7d5e199a | 102 | v = qobject_output_visitor_new(&obj); |
4d0b268f EB |
103 | ''') |
104 | if not arg_type.is_implicit(): | |
105 | ret += mcgen(''' | |
106 | visit_type_%(c_name)s(v, "%(name)s", &arg, &err); | |
107 | ''', | |
108 | name=name, c_name=arg_type.c_name()) | |
109 | else: | |
110 | ret += mcgen(''' | |
21cd70df | 111 | |
337283df | 112 | visit_start_struct(v, "%(name)s", NULL, 0, &err); |
0949e95b EB |
113 | if (err) { |
114 | goto out; | |
115 | } | |
116 | visit_type_%(c_name)s_members(v, ¶m, &err); | |
15c2f669 EB |
117 | if (!err) { |
118 | visit_check_struct(v, &err); | |
119 | } | |
1158bb2a | 120 | visit_end_struct(v, NULL); |
4d0b268f EB |
121 | ''', |
122 | name=name, c_name=arg_type.c_name()) | |
123 | ret += mcgen(''' | |
2a0f50e8 | 124 | if (err) { |
f782399c | 125 | goto out; |
21cd70df WX |
126 | } |
127 | ||
3b098d56 EB |
128 | visit_complete(v, &obj); |
129 | qdict_put_obj(qmp, "data", obj); | |
4d0b268f | 130 | ''') |
21cd70df | 131 | |
e98859a9 | 132 | ret += mcgen(''' |
2a0f50e8 | 133 | emit(%(c_enum)s, qmp, &err); |
21cd70df | 134 | |
e98859a9 MA |
135 | ''', |
136 | c_enum=c_enum_const(event_enum_name, name)) | |
21cd70df | 137 | |
b6167706 | 138 | if arg_type and not arg_type.is_empty(): |
e98859a9 | 139 | ret += mcgen(''' |
f782399c | 140 | out: |
2c0ef9f4 | 141 | visit_free(v); |
e98859a9 MA |
142 | ''') |
143 | ret += mcgen(''' | |
2a0f50e8 | 144 | error_propagate(errp, err); |
cb3e7f08 | 145 | qobject_unref(qmp); |
21cd70df | 146 | } |
e98859a9 | 147 | ''') |
21cd70df WX |
148 | return ret |
149 | ||
05f43a96 | 150 | |
252dc310 | 151 | class QAPISchemaGenEventVisitor(QAPISchemaModularCVisitor): |
71b3f045 | 152 | |
93b564c4 | 153 | def __init__(self, prefix): |
252dc310 MA |
154 | QAPISchemaModularCVisitor.__init__( |
155 | self, prefix, 'qapi-events', | |
71b3f045 | 156 | ' * Schema-defined QAPI/QMP events', __doc__) |
93b564c4 | 157 | self._enum_name = c_name(prefix + 'QAPIEvent', protect=False) |
05f43a96 | 158 | self._event_names = [] |
252dc310 | 159 | |
252dc310 | 160 | def _begin_module(self, name): |
9af23989 MA |
161 | types = self._module_basename('qapi-types', name) |
162 | visit = self._module_basename('qapi-visit', name) | |
71b3f045 | 163 | self._genc.add(mcgen(''' |
9167ebd9 | 164 | #include "qemu/osdep.h" |
12f8e1b9 | 165 | #include "qemu-common.h" |
eb815e24 | 166 | #include "%(prefix)sqapi-events.h" |
9af23989 | 167 | #include "%(visit)s.h" |
e688df6b | 168 | #include "qapi/error.h" |
452fcdbc | 169 | #include "qapi/qmp/qdict.h" |
b3db211f | 170 | #include "qapi/qobject-output-visitor.h" |
12f8e1b9 MA |
171 | #include "qapi/qmp-event.h" |
172 | ||
173 | ''', | |
9af23989 | 174 | visit=visit, prefix=self._prefix)) |
71b3f045 | 175 | self._genh.add(mcgen(''' |
5b5f825d | 176 | #include "qapi/util.h" |
9af23989 | 177 | #include "%(types)s.h" |
21cd70df WX |
178 | |
179 | ''', | |
9af23989 | 180 | types=types)) |
26df4e7f | 181 | |
71b3f045 MA |
182 | def visit_end(self): |
183 | self._genh.add(gen_enum(self._enum_name, self._event_names)) | |
184 | self._genc.add(gen_enum_lookup(self._enum_name, self._event_names)) | |
185 | ||
186 | def visit_event(self, name, info, arg_type, boxed): | |
187 | self._genh.add(gen_event_send_decl(name, arg_type, boxed)) | |
188 | self._genc.add(gen_event_send(name, arg_type, boxed, self._enum_name)) | |
189 | self._event_names.append(name) | |
190 | ||
191 | ||
192 | def gen_events(schema, output_dir, prefix): | |
26df4e7f MA |
193 | vis = QAPISchemaGenEventVisitor(prefix) |
194 | schema.visit(vis) | |
71b3f045 | 195 | vis.write(output_dir) |