]>
Commit | Line | Data |
---|---|---|
06d64c62 MR |
1 | # |
2 | # QAPI visitor generator | |
3 | # | |
4 | # Copyright IBM, Corp. 2011 | |
5 | # | |
6 | # Authors: | |
7 | # Anthony Liguori <[email protected]> | |
8 | # Michael Roth <[email protected]> | |
9 | # | |
10 | # This work is licensed under the terms of the GNU GPLv2. | |
11 | # See the COPYING.LIB file in the top-level directory. | |
12 | ||
13 | from ordereddict import OrderedDict | |
14 | from qapi import * | |
15 | import sys | |
16 | import os | |
17 | import getopt | |
18 | import errno | |
19 | ||
d195325b PB |
20 | def generate_visit_struct_body(field_prefix, name, members): |
21 | ret = mcgen(''' | |
22 | if (!error_is_set(errp)) { | |
23 | ''') | |
24 | push_indent() | |
25 | ||
06d64c62 MR |
26 | if len(field_prefix): |
27 | field_prefix = field_prefix + "." | |
d195325b PB |
28 | ret += mcgen(''' |
29 | Error **errp = &err; /* from outer scope */ | |
30 | Error *err = NULL; | |
31 | visit_start_struct(m, NULL, "", "%(name)s", 0, &err); | |
32 | ''', | |
33 | name=name) | |
34 | else: | |
35 | ret += mcgen(''' | |
36 | Error *err = NULL; | |
37 | visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(name)s), &err); | |
38 | ''', | |
39 | name=name) | |
40 | ||
41 | ret += mcgen(''' | |
42 | if (!err) { | |
43 | if (!obj || *obj) { | |
44 | ''') | |
45 | ||
46 | push_indent() | |
47 | push_indent() | |
06d64c62 MR |
48 | for argname, argentry, optional, structured in parse_args(members): |
49 | if optional: | |
50 | ret += mcgen(''' | |
d195325b PB |
51 | visit_start_optional(m, obj ? &(*obj)->%(c_prefix)shas_%(c_name)s : NULL, "%(name)s", &err); |
52 | if (obj && (*obj)->%(prefix)shas_%(c_name)s) { | |
06d64c62 MR |
53 | ''', |
54 | c_prefix=c_var(field_prefix), prefix=field_prefix, | |
55 | c_name=c_var(argname), name=argname) | |
56 | push_indent() | |
57 | ||
58 | if structured: | |
d195325b | 59 | ret += generate_visit_struct_body(field_prefix + argname, argname, argentry) |
06d64c62 MR |
60 | else: |
61 | ret += mcgen(''' | |
d195325b | 62 | visit_type_%(type)s(m, obj ? &(*obj)->%(c_prefix)s%(c_name)s : NULL, "%(name)s", &err); |
06d64c62 MR |
63 | ''', |
64 | c_prefix=c_var(field_prefix), prefix=field_prefix, | |
65 | type=type_name(argentry), c_name=c_var(argname), | |
66 | name=argname) | |
67 | ||
68 | if optional: | |
69 | pop_indent() | |
70 | ret += mcgen(''' | |
71 | } | |
d195325b PB |
72 | visit_end_optional(m, &err); |
73 | ''') | |
74 | ||
75 | pop_indent() | |
76 | ret += mcgen(''' | |
77 | ||
78 | error_propagate(errp, err); | |
79 | err = NULL; | |
80 | } | |
81 | ''') | |
82 | ||
83 | pop_indent() | |
84 | pop_indent() | |
85 | ret += mcgen(''' | |
86 | /* Always call end_struct if start_struct succeeded. */ | |
87 | visit_end_struct(m, &err); | |
88 | } | |
89 | error_propagate(errp, err); | |
90 | } | |
06d64c62 MR |
91 | ''') |
92 | return ret | |
93 | ||
94 | def generate_visit_struct(name, members): | |
95 | ret = mcgen(''' | |
96 | ||
97 | void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **errp) | |
98 | { | |
06d64c62 MR |
99 | ''', |
100 | name=name) | |
d195325b | 101 | |
06d64c62 | 102 | push_indent() |
d195325b | 103 | ret += generate_visit_struct_body("", name, members) |
06d64c62 MR |
104 | pop_indent() |
105 | ||
106 | ret += mcgen(''' | |
06d64c62 MR |
107 | } |
108 | ''') | |
109 | return ret | |
110 | ||
111 | def generate_visit_list(name, members): | |
112 | return mcgen(''' | |
113 | ||
114 | void visit_type_%(name)sList(Visitor *m, %(name)sList ** obj, const char *name, Error **errp) | |
115 | { | |
3a86a0fa | 116 | GenericList *i, **prev = (GenericList **)obj; |
d195325b | 117 | Error *err = NULL; |
06d64c62 | 118 | |
d195325b PB |
119 | if (!error_is_set(errp)) { |
120 | visit_start_list(m, name, &err); | |
121 | if (!err) { | |
122 | for (; (i = visit_next_list(m, prev, &err)) != NULL; prev = &i) { | |
123 | %(name)sList *native_i = (%(name)sList *)i; | |
124 | visit_type_%(name)s(m, &native_i->value, NULL, &err); | |
125 | } | |
126 | error_propagate(errp, err); | |
127 | err = NULL; | |
128 | ||
129 | /* Always call end_list if start_list succeeded. */ | |
130 | visit_end_list(m, &err); | |
131 | } | |
132 | error_propagate(errp, err); | |
06d64c62 | 133 | } |
06d64c62 MR |
134 | } |
135 | ''', | |
136 | name=name) | |
137 | ||
138 | def generate_visit_enum(name, members): | |
139 | return mcgen(''' | |
140 | ||
141 | void visit_type_%(name)s(Visitor *m, %(name)s * obj, const char *name, Error **errp) | |
142 | { | |
143 | visit_type_enum(m, (int *)obj, %(name)s_lookup, "%(name)s", name, errp); | |
144 | } | |
145 | ''', | |
146 | name=name) | |
147 | ||
148 | def generate_visit_union(name, members): | |
149 | ret = generate_visit_enum('%sKind' % name, members.keys()) | |
150 | ||
151 | ret += mcgen(''' | |
152 | ||
153 | void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **errp) | |
154 | { | |
dc8fb6df PB |
155 | Error *err = NULL; |
156 | ||
d195325b PB |
157 | if (!error_is_set(errp)) { |
158 | visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(name)s), &err); | |
159 | if (!err) { | |
227ccf6b | 160 | if (obj && *obj) { |
d195325b PB |
161 | visit_type_%(name)sKind(m, &(*obj)->kind, "type", &err); |
162 | if (!err) { | |
163 | switch ((*obj)->kind) { | |
06d64c62 MR |
164 | ''', |
165 | name=name) | |
166 | ||
d195325b PB |
167 | push_indent() |
168 | push_indent() | |
dc8fb6df PB |
169 | for key in members: |
170 | ret += mcgen(''' | |
d195325b PB |
171 | case %(abbrev)s_KIND_%(enum)s: |
172 | visit_type_%(c_type)s(m, &(*obj)->%(c_name)s, "data", &err); | |
173 | break; | |
dc8fb6df PB |
174 | ''', |
175 | abbrev = de_camel_case(name).upper(), | |
eda50a65 | 176 | enum = c_fun(de_camel_case(key),False).upper(), |
dc8fb6df | 177 | c_type=members[key], |
c9da228b | 178 | c_name=c_fun(key)) |
dc8fb6df PB |
179 | |
180 | ret += mcgen(''' | |
d195325b PB |
181 | default: |
182 | abort(); | |
183 | } | |
184 | } | |
185 | error_propagate(errp, err); | |
186 | err = NULL; | |
187 | } | |
188 | ''') | |
189 | pop_indent() | |
190 | ret += mcgen(''' | |
191 | /* Always call end_struct if start_struct succeeded. */ | |
192 | visit_end_struct(m, &err); | |
dc8fb6df | 193 | } |
d195325b PB |
194 | error_propagate(errp, err); |
195 | } | |
196 | ''') | |
197 | ||
198 | pop_indent(); | |
199 | ret += mcgen(''' | |
dc8fb6df PB |
200 | } |
201 | ''') | |
202 | ||
06d64c62 MR |
203 | return ret |
204 | ||
205 | def generate_declaration(name, members, genlist=True): | |
206 | ret = mcgen(''' | |
207 | ||
208 | void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **errp); | |
209 | ''', | |
210 | name=name) | |
211 | ||
212 | if genlist: | |
213 | ret += mcgen(''' | |
214 | void visit_type_%(name)sList(Visitor *m, %(name)sList ** obj, const char *name, Error **errp); | |
215 | ''', | |
216 | name=name) | |
217 | ||
218 | return ret | |
219 | ||
b9c4b48d AK |
220 | def generate_enum_declaration(name, members, genlist=True): |
221 | ret = "" | |
222 | if genlist: | |
223 | ret += mcgen(''' | |
224 | void visit_type_%(name)sList(Visitor *m, %(name)sList ** obj, const char *name, Error **errp); | |
225 | ''', | |
226 | name=name) | |
227 | ||
228 | return ret | |
229 | ||
06d64c62 MR |
230 | def generate_decl_enum(name, members, genlist=True): |
231 | return mcgen(''' | |
232 | ||
233 | void visit_type_%(name)s(Visitor *m, %(name)s * obj, const char *name, Error **errp); | |
234 | ''', | |
235 | name=name) | |
236 | ||
237 | try: | |
8d3bc517 AK |
238 | opts, args = getopt.gnu_getopt(sys.argv[1:], "chp:o:", |
239 | ["source", "header", "prefix=", "output-dir="]) | |
06d64c62 MR |
240 | except getopt.GetoptError, err: |
241 | print str(err) | |
242 | sys.exit(1) | |
243 | ||
244 | output_dir = "" | |
245 | prefix = "" | |
246 | c_file = 'qapi-visit.c' | |
247 | h_file = 'qapi-visit.h' | |
248 | ||
8d3bc517 AK |
249 | do_c = False |
250 | do_h = False | |
251 | ||
06d64c62 MR |
252 | for o, a in opts: |
253 | if o in ("-p", "--prefix"): | |
254 | prefix = a | |
255 | elif o in ("-o", "--output-dir"): | |
256 | output_dir = a + "/" | |
8d3bc517 | 257 | elif o in ("-c", "--source"): |
8d3bc517 | 258 | do_c = True |
19bf7c87 AK |
259 | elif o in ("-h", "--header"): |
260 | do_h = True | |
8d3bc517 AK |
261 | |
262 | if not do_c and not do_h: | |
263 | do_c = True | |
264 | do_h = True | |
06d64c62 MR |
265 | |
266 | c_file = output_dir + prefix + c_file | |
267 | h_file = output_dir + prefix + h_file | |
268 | ||
269 | try: | |
270 | os.makedirs(output_dir) | |
271 | except os.error, e: | |
272 | if e.errno != errno.EEXIST: | |
273 | raise | |
274 | ||
8d3bc517 | 275 | def maybe_open(really, name, opt): |
8d3bc517 AK |
276 | if really: |
277 | return open(name, opt) | |
19bf7c87 AK |
278 | else: |
279 | import StringIO | |
280 | return StringIO.StringIO() | |
8d3bc517 AK |
281 | |
282 | fdef = maybe_open(do_c, c_file, 'w') | |
283 | fdecl = maybe_open(do_h, h_file, 'w') | |
06d64c62 MR |
284 | |
285 | fdef.write(mcgen(''' | |
286 | /* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */ | |
287 | ||
288 | /* | |
289 | * schema-defined QAPI visitor functions | |
290 | * | |
291 | * Copyright IBM, Corp. 2011 | |
292 | * | |
293 | * Authors: | |
294 | * Anthony Liguori <[email protected]> | |
295 | * | |
296 | * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. | |
297 | * See the COPYING.LIB file in the top-level directory. | |
298 | * | |
299 | */ | |
300 | ||
79ee7df8 | 301 | #include "qemu-common.h" |
06d64c62 MR |
302 | #include "%(header)s" |
303 | ''', | |
304 | header=basename(h_file))) | |
305 | ||
306 | fdecl.write(mcgen(''' | |
307 | /* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */ | |
308 | ||
309 | /* | |
310 | * schema-defined QAPI visitor function | |
311 | * | |
312 | * Copyright IBM, Corp. 2011 | |
313 | * | |
314 | * Authors: | |
315 | * Anthony Liguori <[email protected]> | |
316 | * | |
317 | * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. | |
318 | * See the COPYING.LIB file in the top-level directory. | |
319 | * | |
320 | */ | |
321 | ||
322 | #ifndef %(guard)s | |
323 | #define %(guard)s | |
324 | ||
7b1b5d19 | 325 | #include "qapi/visitor.h" |
06d64c62 MR |
326 | #include "%(prefix)sqapi-types.h" |
327 | ''', | |
328 | prefix=prefix, guard=guardname(h_file))) | |
329 | ||
330 | exprs = parse_schema(sys.stdin) | |
331 | ||
332 | for expr in exprs: | |
333 | if expr.has_key('type'): | |
334 | ret = generate_visit_struct(expr['type'], expr['data']) | |
335 | ret += generate_visit_list(expr['type'], expr['data']) | |
336 | fdef.write(ret) | |
337 | ||
338 | ret = generate_declaration(expr['type'], expr['data']) | |
339 | fdecl.write(ret) | |
340 | elif expr.has_key('union'): | |
341 | ret = generate_visit_union(expr['union'], expr['data']) | |
dc8fb6df | 342 | ret += generate_visit_list(expr['union'], expr['data']) |
06d64c62 MR |
343 | fdef.write(ret) |
344 | ||
345 | ret = generate_decl_enum('%sKind' % expr['union'], expr['data'].keys()) | |
346 | ret += generate_declaration(expr['union'], expr['data']) | |
347 | fdecl.write(ret) | |
348 | elif expr.has_key('enum'): | |
b9c4b48d AK |
349 | ret = generate_visit_list(expr['enum'], expr['data']) |
350 | ret += generate_visit_enum(expr['enum'], expr['data']) | |
06d64c62 MR |
351 | fdef.write(ret) |
352 | ||
353 | ret = generate_decl_enum(expr['enum'], expr['data']) | |
b9c4b48d | 354 | ret += generate_enum_declaration(expr['enum'], expr['data']) |
06d64c62 MR |
355 | fdecl.write(ret) |
356 | ||
357 | fdecl.write(''' | |
358 | #endif | |
359 | ''') | |
360 | ||
361 | fdecl.flush() | |
362 | fdecl.close() | |
363 | ||
364 | fdef.flush() | |
365 | fdef.close() |