]>
Commit | Line | Data |
---|---|---|
06d64c62 MR |
1 | # |
2 | # QAPI visitor generator | |
3 | # | |
4 | # Copyright IBM, Corp. 2011 | |
297a3646 | 5 | # Copyright (C) 2014 Red Hat, Inc. |
06d64c62 MR |
6 | # |
7 | # Authors: | |
8 | # Anthony Liguori <[email protected]> | |
9 | # Michael Roth <[email protected]> | |
297a3646 | 10 | # Markus Armbruster <[email protected]> |
06d64c62 | 11 | # |
678e48a2 MA |
12 | # This work is licensed under the terms of the GNU GPL, version 2. |
13 | # See the COPYING file in the top-level directory. | |
06d64c62 MR |
14 | |
15 | from ordereddict import OrderedDict | |
16 | from qapi import * | |
297a3646 | 17 | import re |
06d64c62 MR |
18 | import sys |
19 | import os | |
20 | import getopt | |
21 | import errno | |
22 | ||
be3c7717 MA |
23 | implicit_structs = [] |
24 | ||
25 | def generate_visit_implicit_struct(type): | |
26 | global implicit_structs | |
27 | if type in implicit_structs: | |
28 | return '' | |
29 | implicit_structs.append(type) | |
30 | return mcgen(''' | |
31 | ||
32 | static void visit_type_implicit_%(c_type)s(Visitor *m, %(c_type)s **obj, Error **errp) | |
33 | { | |
34 | Error *err = NULL; | |
35 | ||
36 | visit_start_implicit_struct(m, (void **)obj, sizeof(%(c_type)s), &err); | |
37 | if (!err) { | |
297a3646 | 38 | visit_type_%(c_type)s_fields(m, obj, errp); |
be3c7717 MA |
39 | visit_end_implicit_struct(m, &err); |
40 | } | |
41 | error_propagate(errp, err); | |
42 | } | |
43 | ''', | |
44 | c_type=type_name(type)) | |
45 | ||
622f557f | 46 | def generate_visit_struct_fields(name, field_prefix, fn_prefix, members, base = None): |
50f2bdc7 | 47 | substructs = [] |
d131c897 | 48 | ret = '' |
7b75d9d6 RH |
49 | if not fn_prefix: |
50 | full_name = name | |
51 | else: | |
52 | full_name = "%s_%s" % (name, fn_prefix) | |
50f2bdc7 KW |
53 | |
54 | for argname, argentry, optional, structured in parse_args(members): | |
55 | if structured: | |
56 | if not fn_prefix: | |
57 | nested_fn_prefix = argname | |
58 | else: | |
59 | nested_fn_prefix = "%s_%s" % (fn_prefix, argname) | |
60 | ||
61 | nested_field_prefix = "%s%s." % (field_prefix, argname) | |
62 | ret += generate_visit_struct_fields(name, nested_field_prefix, | |
63 | nested_fn_prefix, argentry) | |
4fa953f2 MA |
64 | ret += mcgen(''' |
65 | ||
66 | static void visit_type_%(full_name)s_field_%(c_name)s(Visitor *m, %(name)s **obj, Error **errp) | |
67 | { | |
4fa953f2 MA |
68 | ''', |
69 | name=name, full_name=full_name, c_name=c_var(argname)) | |
4fa953f2 | 70 | ret += generate_visit_struct_body(full_name, argname, argentry) |
4fa953f2 MA |
71 | ret += mcgen(''' |
72 | } | |
73 | ''') | |
50f2bdc7 | 74 | |
be3c7717 MA |
75 | if base: |
76 | ret += generate_visit_implicit_struct(base) | |
77 | ||
50f2bdc7 KW |
78 | ret += mcgen(''' |
79 | ||
638ca8ad | 80 | static void visit_type_%(full_name)s_fields(Visitor *m, %(name)s **obj, Error **errp) |
50f2bdc7 KW |
81 | { |
82 | Error *err = NULL; | |
83 | ''', | |
84 | name=name, full_name=full_name) | |
85 | push_indent() | |
d195325b | 86 | |
622f557f KW |
87 | if base: |
88 | ret += mcgen(''' | |
be3c7717 | 89 | visit_type_implicit_%(type)s(m, &(*obj)->%(c_prefix)s%(c_name)s, &err); |
297a3646 MA |
90 | if (err) { |
91 | goto out; | |
92 | } | |
622f557f KW |
93 | ''', |
94 | c_prefix=c_var(field_prefix), | |
95 | type=type_name(base), c_name=c_var('base')) | |
96 | ||
06d64c62 MR |
97 | for argname, argentry, optional, structured in parse_args(members): |
98 | if optional: | |
99 | ret += mcgen(''' | |
e2cd0f4f | 100 | visit_optional(m, &(*obj)->%(c_prefix)shas_%(c_name)s, "%(name)s", &err); |
297a3646 | 101 | if (!err && (*obj)->%(prefix)shas_%(c_name)s) { |
06d64c62 MR |
102 | ''', |
103 | c_prefix=c_var(field_prefix), prefix=field_prefix, | |
104 | c_name=c_var(argname), name=argname) | |
105 | push_indent() | |
106 | ||
107 | if structured: | |
4fa953f2 MA |
108 | ret += mcgen(''' |
109 | visit_type_%(full_name)s_field_%(c_name)s(m, obj, &err); | |
110 | ''', | |
111 | full_name=full_name, c_name=c_var(argname)) | |
06d64c62 MR |
112 | else: |
113 | ret += mcgen(''' | |
949ceeb3 | 114 | visit_type_%(type)s(m, &(*obj)->%(c_prefix)s%(c_name)s, "%(name)s", &err); |
06d64c62 MR |
115 | ''', |
116 | c_prefix=c_var(field_prefix), prefix=field_prefix, | |
117 | type=type_name(argentry), c_name=c_var(argname), | |
118 | name=argname) | |
119 | ||
120 | if optional: | |
121 | pop_indent() | |
122 | ret += mcgen(''' | |
123 | } | |
297a3646 MA |
124 | ''') |
125 | ret += mcgen(''' | |
126 | if (err) { | |
127 | goto out; | |
128 | } | |
d195325b PB |
129 | ''') |
130 | ||
50f2bdc7 | 131 | pop_indent() |
297a3646 MA |
132 | if re.search('^ *goto out\\;', ret, re.MULTILINE): |
133 | ret += mcgen(''' | |
50f2bdc7 | 134 | |
297a3646 MA |
135 | out: |
136 | ''') | |
137 | ret += mcgen(''' | |
50f2bdc7 KW |
138 | error_propagate(errp, err); |
139 | } | |
140 | ''') | |
d131c897 KW |
141 | return ret |
142 | ||
143 | ||
144 | def generate_visit_struct_body(field_prefix, name, members): | |
145 | ret = mcgen(''' | |
297a3646 MA |
146 | Error *err = NULL; |
147 | ||
d131c897 | 148 | ''') |
d131c897 | 149 | |
7b75d9d6 RH |
150 | if not field_prefix: |
151 | full_name = name | |
152 | else: | |
153 | full_name = "%s_%s" % (field_prefix, name) | |
50f2bdc7 | 154 | |
d131c897 | 155 | if len(field_prefix): |
d131c897 | 156 | ret += mcgen(''' |
297a3646 | 157 | visit_start_struct(m, NULL, "", "%(name)s", 0, &err); |
d131c897 KW |
158 | ''', |
159 | name=name) | |
160 | else: | |
161 | ret += mcgen(''' | |
297a3646 | 162 | visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(name)s), &err); |
d131c897 KW |
163 | ''', |
164 | name=name) | |
165 | ||
d195325b | 166 | ret += mcgen(''' |
297a3646 MA |
167 | if (!err) { |
168 | if (*obj) { | |
169 | visit_type_%(name)s_fields(m, obj, errp); | |
170 | } | |
171 | visit_end_struct(m, &err); | |
50f2bdc7 | 172 | } |
297a3646 | 173 | error_propagate(errp, err); |
50f2bdc7 KW |
174 | ''', |
175 | name=full_name) | |
d195325b | 176 | |
06d64c62 MR |
177 | return ret |
178 | ||
14d36307 KW |
179 | def generate_visit_struct(expr): |
180 | ||
181 | name = expr['type'] | |
182 | members = expr['data'] | |
622f557f | 183 | base = expr.get('base') |
14d36307 | 184 | |
622f557f | 185 | ret = generate_visit_struct_fields(name, "", "", members, base) |
50f2bdc7 KW |
186 | |
187 | ret += mcgen(''' | |
06d64c62 | 188 | |
638ca8ad | 189 | void visit_type_%(name)s(Visitor *m, %(name)s **obj, const char *name, Error **errp) |
06d64c62 | 190 | { |
06d64c62 MR |
191 | ''', |
192 | name=name) | |
d195325b | 193 | |
d195325b | 194 | ret += generate_visit_struct_body("", name, members) |
06d64c62 MR |
195 | |
196 | ret += mcgen(''' | |
06d64c62 MR |
197 | } |
198 | ''') | |
199 | return ret | |
200 | ||
201 | def generate_visit_list(name, members): | |
202 | return mcgen(''' | |
203 | ||
638ca8ad | 204 | void visit_type_%(name)sList(Visitor *m, %(name)sList **obj, const char *name, Error **errp) |
06d64c62 | 205 | { |
d195325b | 206 | Error *err = NULL; |
297a3646 | 207 | GenericList *i, **prev; |
06d64c62 | 208 | |
297a3646 MA |
209 | visit_start_list(m, name, &err); |
210 | if (err) { | |
211 | goto out; | |
212 | } | |
213 | ||
214 | for (prev = (GenericList **)obj; | |
215 | !err && (i = visit_next_list(m, prev, &err)) != NULL; | |
216 | prev = &i) { | |
217 | %(name)sList *native_i = (%(name)sList *)i; | |
218 | visit_type_%(name)s(m, &native_i->value, NULL, &err); | |
06d64c62 | 219 | } |
297a3646 MA |
220 | |
221 | error_propagate(errp, err); | |
222 | err = NULL; | |
223 | visit_end_list(m, &err); | |
224 | out: | |
225 | error_propagate(errp, err); | |
06d64c62 MR |
226 | } |
227 | ''', | |
228 | name=name) | |
229 | ||
230 | def generate_visit_enum(name, members): | |
231 | return mcgen(''' | |
232 | ||
638ca8ad | 233 | void visit_type_%(name)s(Visitor *m, %(name)s *obj, const char *name, Error **errp) |
06d64c62 MR |
234 | { |
235 | visit_type_enum(m, (int *)obj, %(name)s_lookup, "%(name)s", name, errp); | |
236 | } | |
237 | ''', | |
238 | name=name) | |
239 | ||
69dd62df KW |
240 | def generate_visit_anon_union(name, members): |
241 | ret = mcgen(''' | |
242 | ||
638ca8ad | 243 | void visit_type_%(name)s(Visitor *m, %(name)s **obj, const char *name, Error **errp) |
69dd62df KW |
244 | { |
245 | Error *err = NULL; | |
246 | ||
297a3646 MA |
247 | visit_start_implicit_struct(m, (void**) obj, sizeof(%(name)s), &err); |
248 | if (err) { | |
249 | goto out; | |
250 | } | |
251 | visit_get_next_type(m, (int*) &(*obj)->kind, %(name)s_qtypes, name, &err); | |
252 | if (err) { | |
253 | goto out_end; | |
254 | } | |
255 | switch ((*obj)->kind) { | |
69dd62df KW |
256 | ''', |
257 | name=name) | |
258 | ||
b0b58195 WX |
259 | # For anon union, always use the default enum type automatically generated |
260 | # as "'%sKind' % (name)" | |
261 | disc_type = '%sKind' % (name) | |
262 | ||
69dd62df KW |
263 | for key in members: |
264 | assert (members[key] in builtin_types | |
265 | or find_struct(members[key]) | |
e775ba77 HR |
266 | or find_union(members[key]) |
267 | or find_enum(members[key])), "Invalid anonymous union member" | |
69dd62df | 268 | |
b0b58195 | 269 | enum_full_value = generate_enum_full_value(disc_type, key) |
69dd62df | 270 | ret += mcgen(''' |
297a3646 MA |
271 | case %(enum_full_value)s: |
272 | visit_type_%(c_type)s(m, &(*obj)->%(c_name)s, name, &err); | |
273 | break; | |
69dd62df | 274 | ''', |
b0b58195 | 275 | enum_full_value = enum_full_value, |
69dd62df KW |
276 | c_type = type_name(members[key]), |
277 | c_name = c_fun(key)) | |
278 | ||
279 | ret += mcgen(''' | |
297a3646 MA |
280 | default: |
281 | abort(); | |
69dd62df | 282 | } |
297a3646 MA |
283 | out_end: |
284 | error_propagate(errp, err); | |
285 | err = NULL; | |
286 | visit_end_implicit_struct(m, &err); | |
287 | out: | |
288 | error_propagate(errp, err); | |
69dd62df KW |
289 | } |
290 | ''') | |
291 | ||
292 | return ret | |
293 | ||
294 | ||
0aef92b9 KW |
295 | def generate_visit_union(expr): |
296 | ||
297 | name = expr['union'] | |
298 | members = expr['data'] | |
299 | ||
300 | base = expr.get('base') | |
50f2bdc7 | 301 | discriminator = expr.get('discriminator') |
0aef92b9 | 302 | |
69dd62df KW |
303 | if discriminator == {}: |
304 | assert not base | |
305 | return generate_visit_anon_union(name, members) | |
306 | ||
bceae769 WX |
307 | enum_define = discriminator_find_enum_define(expr) |
308 | if enum_define: | |
309 | # Use the enum type as discriminator | |
310 | ret = "" | |
311 | disc_type = enum_define['enum_name'] | |
312 | else: | |
313 | # There will always be a discriminator in the C switch code, by default it | |
314 | # is an enum type generated silently as "'%sKind' % (name)" | |
315 | ret = generate_visit_enum('%sKind' % name, members.keys()) | |
316 | disc_type = '%sKind' % (name) | |
06d64c62 | 317 | |
50f2bdc7 KW |
318 | if base: |
319 | base_fields = find_struct(base)['data'] | |
320 | if discriminator: | |
321 | base_fields = base_fields.copy() | |
322 | del base_fields[discriminator] | |
323 | ret += generate_visit_struct_fields(name, "", "", base_fields) | |
324 | ||
be3c7717 MA |
325 | if discriminator: |
326 | for key in members: | |
327 | ret += generate_visit_implicit_struct(members[key]) | |
328 | ||
06d64c62 MR |
329 | ret += mcgen(''' |
330 | ||
638ca8ad | 331 | void visit_type_%(name)s(Visitor *m, %(name)s **obj, const char *name, Error **errp) |
06d64c62 | 332 | { |
dc8fb6df PB |
333 | Error *err = NULL; |
334 | ||
297a3646 MA |
335 | visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(name)s), &err); |
336 | if (err) { | |
337 | goto out; | |
338 | } | |
339 | if (*obj) { | |
06d64c62 MR |
340 | ''', |
341 | name=name) | |
342 | ||
0aef92b9 | 343 | if base: |
50f2bdc7 | 344 | ret += mcgen(''' |
468866b8 | 345 | visit_type_%(name)s_fields(m, obj, &err); |
297a3646 MA |
346 | if (err) { |
347 | goto out_obj; | |
348 | } | |
50f2bdc7 KW |
349 | ''', |
350 | name=name) | |
0aef92b9 | 351 | |
7b75d9d6 | 352 | if not discriminator: |
bceae769 | 353 | disc_key = "type" |
7b75d9d6 | 354 | else: |
bceae769 | 355 | disc_key = discriminator |
0aef92b9 | 356 | ret += mcgen(''' |
bceae769 | 357 | visit_type_%(disc_type)s(m, &(*obj)->kind, "%(disc_key)s", &err); |
297a3646 MA |
358 | if (err) { |
359 | goto out_obj; | |
360 | } | |
cee2dedb MR |
361 | if (!visit_start_union(m, !!(*obj)->data, &err) || err) { |
362 | goto out_obj; | |
363 | } | |
297a3646 | 364 | switch ((*obj)->kind) { |
0aef92b9 | 365 | ''', |
bceae769 WX |
366 | disc_type = disc_type, |
367 | disc_key = disc_key) | |
0aef92b9 | 368 | |
dc8fb6df | 369 | for key in members: |
50f2bdc7 KW |
370 | if not discriminator: |
371 | fmt = 'visit_type_%(c_type)s(m, &(*obj)->%(c_name)s, "data", &err);' | |
372 | else: | |
be3c7717 | 373 | fmt = 'visit_type_implicit_%(c_type)s(m, &(*obj)->%(c_name)s, &err);' |
50f2bdc7 | 374 | |
b0b58195 | 375 | enum_full_value = generate_enum_full_value(disc_type, key) |
dc8fb6df | 376 | ret += mcgen(''' |
297a3646 MA |
377 | case %(enum_full_value)s: |
378 | ''' + fmt + ''' | |
379 | break; | |
dc8fb6df | 380 | ''', |
b0b58195 | 381 | enum_full_value = enum_full_value, |
c664aef5 | 382 | c_type=type_name(members[key]), |
c9da228b | 383 | c_name=c_fun(key)) |
dc8fb6df PB |
384 | |
385 | ret += mcgen(''' | |
297a3646 MA |
386 | default: |
387 | abort(); | |
d195325b | 388 | } |
297a3646 | 389 | out_obj: |
d195325b PB |
390 | error_propagate(errp, err); |
391 | err = NULL; | |
cee2dedb MR |
392 | visit_end_union(m, !!(*obj)->data, &err); |
393 | error_propagate(errp, err); | |
394 | err = NULL; | |
468866b8 | 395 | } |
297a3646 MA |
396 | visit_end_struct(m, &err); |
397 | out: | |
398 | error_propagate(errp, err); | |
dc8fb6df PB |
399 | } |
400 | ''') | |
401 | ||
06d64c62 MR |
402 | return ret |
403 | ||
7c946bc4 MR |
404 | def generate_declaration(name, members, genlist=True, builtin_type=False): |
405 | ret = "" | |
406 | if not builtin_type: | |
407 | ret += mcgen(''' | |
06d64c62 | 408 | |
638ca8ad | 409 | void visit_type_%(name)s(Visitor *m, %(name)s **obj, const char *name, Error **errp); |
06d64c62 | 410 | ''', |
7c946bc4 | 411 | name=name) |
06d64c62 MR |
412 | |
413 | if genlist: | |
414 | ret += mcgen(''' | |
638ca8ad | 415 | void visit_type_%(name)sList(Visitor *m, %(name)sList **obj, const char *name, Error **errp); |
06d64c62 MR |
416 | ''', |
417 | name=name) | |
418 | ||
419 | return ret | |
420 | ||
b9c4b48d AK |
421 | def generate_enum_declaration(name, members, genlist=True): |
422 | ret = "" | |
423 | if genlist: | |
424 | ret += mcgen(''' | |
638ca8ad | 425 | void visit_type_%(name)sList(Visitor *m, %(name)sList **obj, const char *name, Error **errp); |
b9c4b48d AK |
426 | ''', |
427 | name=name) | |
428 | ||
429 | return ret | |
430 | ||
06d64c62 MR |
431 | def generate_decl_enum(name, members, genlist=True): |
432 | return mcgen(''' | |
433 | ||
638ca8ad | 434 | void visit_type_%(name)s(Visitor *m, %(name)s *obj, const char *name, Error **errp); |
06d64c62 MR |
435 | ''', |
436 | name=name) | |
437 | ||
438 | try: | |
33aaad52 | 439 | opts, args = getopt.gnu_getopt(sys.argv[1:], "chbp:i:o:", |
7c946bc4 | 440 | ["source", "header", "builtins", "prefix=", |
33aaad52 | 441 | "input-file=", "output-dir="]) |
06d64c62 MR |
442 | except getopt.GetoptError, err: |
443 | print str(err) | |
444 | sys.exit(1) | |
445 | ||
33aaad52 | 446 | input_file = "" |
06d64c62 MR |
447 | output_dir = "" |
448 | prefix = "" | |
449 | c_file = 'qapi-visit.c' | |
450 | h_file = 'qapi-visit.h' | |
451 | ||
8d3bc517 AK |
452 | do_c = False |
453 | do_h = False | |
7c946bc4 | 454 | do_builtins = False |
8d3bc517 | 455 | |
06d64c62 MR |
456 | for o, a in opts: |
457 | if o in ("-p", "--prefix"): | |
458 | prefix = a | |
33aaad52 LV |
459 | elif o in ("-i", "--input-file"): |
460 | input_file = a | |
06d64c62 MR |
461 | elif o in ("-o", "--output-dir"): |
462 | output_dir = a + "/" | |
8d3bc517 | 463 | elif o in ("-c", "--source"): |
8d3bc517 | 464 | do_c = True |
19bf7c87 AK |
465 | elif o in ("-h", "--header"): |
466 | do_h = True | |
7c946bc4 MR |
467 | elif o in ("-b", "--builtins"): |
468 | do_builtins = True | |
8d3bc517 AK |
469 | |
470 | if not do_c and not do_h: | |
471 | do_c = True | |
472 | do_h = True | |
06d64c62 MR |
473 | |
474 | c_file = output_dir + prefix + c_file | |
475 | h_file = output_dir + prefix + h_file | |
476 | ||
477 | try: | |
478 | os.makedirs(output_dir) | |
479 | except os.error, e: | |
480 | if e.errno != errno.EEXIST: | |
481 | raise | |
482 | ||
8d3bc517 | 483 | def maybe_open(really, name, opt): |
8d3bc517 AK |
484 | if really: |
485 | return open(name, opt) | |
19bf7c87 AK |
486 | else: |
487 | import StringIO | |
488 | return StringIO.StringIO() | |
8d3bc517 AK |
489 | |
490 | fdef = maybe_open(do_c, c_file, 'w') | |
491 | fdecl = maybe_open(do_h, h_file, 'w') | |
06d64c62 MR |
492 | |
493 | fdef.write(mcgen(''' | |
494 | /* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */ | |
495 | ||
496 | /* | |
497 | * schema-defined QAPI visitor functions | |
498 | * | |
499 | * Copyright IBM, Corp. 2011 | |
500 | * | |
501 | * Authors: | |
502 | * Anthony Liguori <[email protected]> | |
503 | * | |
504 | * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. | |
505 | * See the COPYING.LIB file in the top-level directory. | |
506 | * | |
507 | */ | |
508 | ||
79ee7df8 | 509 | #include "qemu-common.h" |
06d64c62 MR |
510 | #include "%(header)s" |
511 | ''', | |
512 | header=basename(h_file))) | |
513 | ||
514 | fdecl.write(mcgen(''' | |
515 | /* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */ | |
516 | ||
517 | /* | |
297a3646 | 518 | * schema-defined QAPI visitor functions |
06d64c62 MR |
519 | * |
520 | * Copyright IBM, Corp. 2011 | |
521 | * | |
522 | * Authors: | |
523 | * Anthony Liguori <[email protected]> | |
524 | * | |
525 | * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. | |
526 | * See the COPYING.LIB file in the top-level directory. | |
527 | * | |
528 | */ | |
529 | ||
530 | #ifndef %(guard)s | |
531 | #define %(guard)s | |
532 | ||
7b1b5d19 | 533 | #include "qapi/visitor.h" |
06d64c62 | 534 | #include "%(prefix)sqapi-types.h" |
7c946bc4 | 535 | |
06d64c62 MR |
536 | ''', |
537 | prefix=prefix, guard=guardname(h_file))) | |
538 | ||
33aaad52 | 539 | exprs = parse_schema(input_file) |
06d64c62 | 540 | |
7c946bc4 MR |
541 | # to avoid header dependency hell, we always generate declarations |
542 | # for built-in types in our header files and simply guard them | |
543 | fdecl.write(guardstart("QAPI_VISIT_BUILTIN_VISITOR_DECL")) | |
544 | for typename in builtin_types: | |
545 | fdecl.write(generate_declaration(typename, None, genlist=True, | |
546 | builtin_type=True)) | |
547 | fdecl.write(guardend("QAPI_VISIT_BUILTIN_VISITOR_DECL")) | |
548 | ||
549 | # ...this doesn't work for cases where we link in multiple objects that | |
550 | # have the functions defined, so we use -b option to provide control | |
551 | # over these cases | |
552 | if do_builtins: | |
7c946bc4 MR |
553 | for typename in builtin_types: |
554 | fdef.write(generate_visit_list(typename, None)) | |
7c946bc4 | 555 | |
06d64c62 MR |
556 | for expr in exprs: |
557 | if expr.has_key('type'): | |
14d36307 | 558 | ret = generate_visit_struct(expr) |
06d64c62 MR |
559 | ret += generate_visit_list(expr['type'], expr['data']) |
560 | fdef.write(ret) | |
561 | ||
562 | ret = generate_declaration(expr['type'], expr['data']) | |
563 | fdecl.write(ret) | |
564 | elif expr.has_key('union'): | |
0aef92b9 | 565 | ret = generate_visit_union(expr) |
dc8fb6df | 566 | ret += generate_visit_list(expr['union'], expr['data']) |
06d64c62 MR |
567 | fdef.write(ret) |
568 | ||
bceae769 WX |
569 | enum_define = discriminator_find_enum_define(expr) |
570 | ret = "" | |
571 | if not enum_define: | |
572 | ret = generate_decl_enum('%sKind' % expr['union'], | |
573 | expr['data'].keys()) | |
06d64c62 MR |
574 | ret += generate_declaration(expr['union'], expr['data']) |
575 | fdecl.write(ret) | |
576 | elif expr.has_key('enum'): | |
b9c4b48d AK |
577 | ret = generate_visit_list(expr['enum'], expr['data']) |
578 | ret += generate_visit_enum(expr['enum'], expr['data']) | |
06d64c62 MR |
579 | fdef.write(ret) |
580 | ||
581 | ret = generate_decl_enum(expr['enum'], expr['data']) | |
b9c4b48d | 582 | ret += generate_enum_declaration(expr['enum'], expr['data']) |
06d64c62 MR |
583 | fdecl.write(ret) |
584 | ||
585 | fdecl.write(''' | |
586 | #endif | |
587 | ''') | |
588 | ||
589 | fdecl.flush() | |
590 | fdecl.close() | |
591 | ||
592 | fdef.flush() | |
593 | fdef.close() |