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