]> Git Repo - qemu.git/blame - scripts/qapi-types.py
qapi: skip redundant includes
[qemu.git] / scripts / qapi-types.py
CommitLineData
fb3182ce
MR
1#
2# QAPI types generator
3#
4# Copyright IBM, Corp. 2011
5#
6# Authors:
7# Anthony Liguori <[email protected]>
8#
678e48a2
MA
9# This work is licensed under the terms of the GNU GPL, version 2.
10# See the COPYING file in the top-level directory.
fb3182ce
MR
11
12from ordereddict import OrderedDict
13from qapi import *
14import sys
15import os
16import getopt
17import errno
18
c0afa9c5
MR
19def generate_fwd_struct(name, members, builtin_type=False):
20 if builtin_type:
21 return mcgen('''
22
23typedef struct %(name)sList
24{
a678e26c
MR
25 union {
26 %(type)s value;
27 uint64_t padding;
28 };
c0afa9c5
MR
29 struct %(name)sList *next;
30} %(name)sList;
31''',
32 type=c_type(name),
33 name=name)
34
fb3182ce 35 return mcgen('''
c0afa9c5 36
fb3182ce
MR
37typedef struct %(name)s %(name)s;
38
39typedef struct %(name)sList
40{
a678e26c
MR
41 union {
42 %(name)s *value;
43 uint64_t padding;
44 };
fb3182ce
MR
45 struct %(name)sList *next;
46} %(name)sList;
47''',
48 name=name)
49
b9c4b48d
AK
50def generate_fwd_enum_struct(name, members):
51 return mcgen('''
52typedef struct %(name)sList
53{
02dc4bf5
CR
54 union {
55 %(name)s value;
56 uint64_t padding;
57 };
b9c4b48d
AK
58 struct %(name)sList *next;
59} %(name)sList;
60''',
61 name=name)
62
01537030
KW
63def generate_struct_fields(members):
64 ret = ''
fb3182ce
MR
65
66 for argname, argentry, optional, structured in parse_args(members):
67 if optional:
68 ret += mcgen('''
69 bool has_%(c_name)s;
70''',
71 c_name=c_var(argname))
72 if structured:
73 push_indent()
14d36307 74 ret += generate_struct({ "field": argname, "data": argentry})
fb3182ce
MR
75 pop_indent()
76 else:
77 ret += mcgen('''
78 %(c_type)s %(c_name)s;
79''',
80 c_type=c_type(argentry), c_name=c_var(argname))
81
01537030
KW
82 return ret
83
14d36307
KW
84def generate_struct(expr):
85
86 structname = expr.get('type', "")
87 fieldname = expr.get('field', "")
88 members = expr['data']
622f557f 89 base = expr.get('base')
14d36307 90
01537030
KW
91 ret = mcgen('''
92struct %(name)s
93{
94''',
95 name=structname)
96
622f557f
KW
97 if base:
98 ret += generate_struct_fields({'base': base})
99
01537030
KW
100 ret += generate_struct_fields(members)
101
fb3182ce
MR
102 if len(fieldname):
103 fieldname = " " + fieldname
104 ret += mcgen('''
105}%(field)s;
106''',
107 field=fieldname)
108
109 return ret
110
111def generate_enum_lookup(name, values):
112 ret = mcgen('''
113const char *%(name)s_lookup[] = {
114''',
115 name=name)
116 i = 0
117 for value in values:
118 ret += mcgen('''
119 "%(value)s",
120''',
ac4ff701 121 value=value)
fb3182ce
MR
122
123 ret += mcgen('''
124 NULL,
125};
126
127''')
128 return ret
129
130def generate_enum(name, values):
131 lookup_decl = mcgen('''
132extern const char *%(name)s_lookup[];
133''',
134 name=name)
135
136 enum_decl = mcgen('''
137typedef enum %(name)s
138{
139''',
140 name=name)
141
303b54b1
LC
142 # append automatically generated _MAX value
143 enum_values = values + [ 'MAX' ]
144
fb3182ce 145 i = 0
303b54b1 146 for value in enum_values:
b0b58195 147 enum_full_value = generate_enum_full_value(name, value)
fb3182ce 148 enum_decl += mcgen('''
b0b58195 149 %(enum_full_value)s = %(i)d,
fb3182ce 150''',
b0b58195 151 enum_full_value = enum_full_value,
fb3182ce
MR
152 i=i)
153 i += 1
154
155 enum_decl += mcgen('''
156} %(name)s;
157''',
158 name=name)
159
160 return lookup_decl + enum_decl
161
69dd62df
KW
162def generate_anon_union_qtypes(expr):
163
164 name = expr['union']
165 members = expr['data']
166
167 ret = mcgen('''
168const int %(name)s_qtypes[QTYPE_MAX] = {
169''',
170 name=name)
171
172 for key in members:
173 qapi_type = members[key]
174 if builtin_type_qtypes.has_key(qapi_type):
175 qtype = builtin_type_qtypes[qapi_type]
176 elif find_struct(qapi_type):
177 qtype = "QTYPE_QDICT"
178 elif find_union(qapi_type):
179 qtype = "QTYPE_QDICT"
180 else:
181 assert False, "Invalid anonymous union member"
182
183 ret += mcgen('''
184 [ %(qtype)s ] = %(abbrev)s_KIND_%(enum)s,
185''',
186 qtype = qtype,
187 abbrev = de_camel_case(name).upper(),
188 enum = c_fun(de_camel_case(key),False).upper())
189
190 ret += mcgen('''
191};
192''')
193 return ret
194
195
e2503f5e
KW
196def generate_union(expr):
197
198 name = expr['union']
199 typeinfo = expr['data']
50f2bdc7 200
e2503f5e 201 base = expr.get('base')
50f2bdc7 202 discriminator = expr.get('discriminator')
e2503f5e 203
bceae769
WX
204 enum_define = discriminator_find_enum_define(expr)
205 if enum_define:
206 discriminator_type_name = enum_define['enum_name']
207 else:
208 discriminator_type_name = '%sKind' % (name)
209
fb3182ce
MR
210 ret = mcgen('''
211struct %(name)s
212{
bceae769 213 %(discriminator_type_name)s kind;
fb3182ce 214 union {
dc8fb6df 215 void *data;
fb3182ce 216''',
bceae769
WX
217 name=name,
218 discriminator_type_name=discriminator_type_name)
fb3182ce
MR
219
220 for key in typeinfo:
221 ret += mcgen('''
222 %(c_type)s %(c_name)s;
223''',
224 c_type=c_type(typeinfo[key]),
c9da228b 225 c_name=c_fun(key))
fb3182ce
MR
226
227 ret += mcgen('''
228 };
e2503f5e
KW
229''')
230
231 if base:
50f2bdc7
KW
232 base_fields = find_struct(base)['data']
233 if discriminator:
234 base_fields = base_fields.copy()
235 del base_fields[discriminator]
236 ret += generate_struct_fields(base_fields)
237 else:
238 assert not discriminator
e2503f5e
KW
239
240 ret += mcgen('''
fb3182ce
MR
241};
242''')
69dd62df
KW
243 if discriminator == {}:
244 ret += mcgen('''
245extern const int %(name)s_qtypes[];
246''',
247 name=name)
248
fb3182ce
MR
249
250 return ret
251
252def generate_type_cleanup_decl(name):
253 ret = mcgen('''
254void qapi_free_%(type)s(%(c_type)s obj);
255''',
256 c_type=c_type(name),type=name)
257 return ret
258
259def generate_type_cleanup(name):
260 ret = mcgen('''
c0afa9c5 261
fb3182ce
MR
262void qapi_free_%(type)s(%(c_type)s obj)
263{
264 QapiDeallocVisitor *md;
265 Visitor *v;
266
267 if (!obj) {
268 return;
269 }
270
271 md = qapi_dealloc_visitor_new();
272 v = qapi_dealloc_get_visitor(md);
273 visit_type_%(type)s(v, &obj, NULL, NULL);
274 qapi_dealloc_visitor_cleanup(md);
275}
276''',
277 c_type=c_type(name),type=name)
278 return ret
279
280
281try:
33aaad52 282 opts, args = getopt.gnu_getopt(sys.argv[1:], "chbp:i:o:",
c0afa9c5 283 ["source", "header", "builtins",
33aaad52 284 "prefix=", "input-file=", "output-dir="])
fb3182ce
MR
285except getopt.GetoptError, err:
286 print str(err)
287 sys.exit(1)
288
289output_dir = ""
33aaad52 290input_file = ""
fb3182ce
MR
291prefix = ""
292c_file = 'qapi-types.c'
293h_file = 'qapi-types.h'
294
8d3bc517
AK
295do_c = False
296do_h = False
c0afa9c5 297do_builtins = False
8d3bc517 298
fb3182ce
MR
299for o, a in opts:
300 if o in ("-p", "--prefix"):
301 prefix = a
33aaad52
LV
302 elif o in ("-i", "--input-file"):
303 input_file = a
fb3182ce
MR
304 elif o in ("-o", "--output-dir"):
305 output_dir = a + "/"
8d3bc517 306 elif o in ("-c", "--source"):
8d3bc517 307 do_c = True
19bf7c87
AK
308 elif o in ("-h", "--header"):
309 do_h = True
c0afa9c5
MR
310 elif o in ("-b", "--builtins"):
311 do_builtins = True
8d3bc517
AK
312
313if not do_c and not do_h:
314 do_c = True
315 do_h = True
fb3182ce
MR
316
317c_file = output_dir + prefix + c_file
318h_file = output_dir + prefix + h_file
319
320try:
321 os.makedirs(output_dir)
322except os.error, e:
323 if e.errno != errno.EEXIST:
324 raise
325
8d3bc517 326def maybe_open(really, name, opt):
8d3bc517
AK
327 if really:
328 return open(name, opt)
19bf7c87
AK
329 else:
330 import StringIO
331 return StringIO.StringIO()
8d3bc517
AK
332
333fdef = maybe_open(do_c, c_file, 'w')
334fdecl = maybe_open(do_h, h_file, 'w')
fb3182ce
MR
335
336fdef.write(mcgen('''
337/* AUTOMATICALLY GENERATED, DO NOT MODIFY */
338
339/*
340 * deallocation functions for schema-defined QAPI types
341 *
342 * Copyright IBM, Corp. 2011
343 *
344 * Authors:
345 * Anthony Liguori <[email protected]>
346 * Michael Roth <[email protected]>
347 *
348 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
349 * See the COPYING.LIB file in the top-level directory.
350 *
351 */
352
7b1b5d19 353#include "qapi/dealloc-visitor.h"
fb3182ce
MR
354#include "%(prefix)sqapi-types.h"
355#include "%(prefix)sqapi-visit.h"
356
357''', prefix=prefix))
358
359fdecl.write(mcgen('''
360/* AUTOMATICALLY GENERATED, DO NOT MODIFY */
361
362/*
363 * schema-defined QAPI types
364 *
365 * Copyright IBM, Corp. 2011
366 *
367 * Authors:
368 * Anthony Liguori <[email protected]>
369 *
370 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
371 * See the COPYING.LIB file in the top-level directory.
372 *
373 */
374
375#ifndef %(guard)s
376#define %(guard)s
377
da4fea06
IM
378#include <stdbool.h>
379#include <stdint.h>
b68a8472 380
fb3182ce
MR
381''',
382 guard=guardname(h_file)))
383
33aaad52 384exprs = parse_schema(input_file)
5dbee474 385exprs = filter(lambda expr: not expr.has_key('gen'), exprs)
fb3182ce 386
c0afa9c5
MR
387fdecl.write(guardstart("QAPI_TYPES_BUILTIN_STRUCT_DECL"))
388for typename in builtin_types:
389 fdecl.write(generate_fwd_struct(typename, None, builtin_type=True))
390fdecl.write(guardend("QAPI_TYPES_BUILTIN_STRUCT_DECL"))
391
fb3182ce
MR
392for expr in exprs:
393 ret = "\n"
394 if expr.has_key('type'):
395 ret += generate_fwd_struct(expr['type'], expr['data'])
396 elif expr.has_key('enum'):
b9c4b48d
AK
397 ret += generate_enum(expr['enum'], expr['data']) + "\n"
398 ret += generate_fwd_enum_struct(expr['enum'], expr['data'])
fb3182ce
MR
399 fdef.write(generate_enum_lookup(expr['enum'], expr['data']))
400 elif expr.has_key('union'):
401 ret += generate_fwd_struct(expr['union'], expr['data']) + "\n"
bceae769
WX
402 enum_define = discriminator_find_enum_define(expr)
403 if not enum_define:
404 ret += generate_enum('%sKind' % expr['union'], expr['data'].keys())
405 fdef.write(generate_enum_lookup('%sKind' % expr['union'],
406 expr['data'].keys()))
69dd62df
KW
407 if expr.get('discriminator') == {}:
408 fdef.write(generate_anon_union_qtypes(expr))
fb3182ce
MR
409 else:
410 continue
411 fdecl.write(ret)
412
c0afa9c5
MR
413# to avoid header dependency hell, we always generate declarations
414# for built-in types in our header files and simply guard them
415fdecl.write(guardstart("QAPI_TYPES_BUILTIN_CLEANUP_DECL"))
416for typename in builtin_types:
417 fdecl.write(generate_type_cleanup_decl(typename + "List"))
418fdecl.write(guardend("QAPI_TYPES_BUILTIN_CLEANUP_DECL"))
419
420# ...this doesn't work for cases where we link in multiple objects that
421# have the functions defined, so we use -b option to provide control
422# over these cases
423if do_builtins:
424 fdef.write(guardstart("QAPI_TYPES_BUILTIN_CLEANUP_DEF"))
425 for typename in builtin_types:
426 fdef.write(generate_type_cleanup(typename + "List"))
427 fdef.write(guardend("QAPI_TYPES_BUILTIN_CLEANUP_DEF"))
428
fb3182ce
MR
429for expr in exprs:
430 ret = "\n"
431 if expr.has_key('type'):
14d36307 432 ret += generate_struct(expr) + "\n"
75b96aca
MR
433 ret += generate_type_cleanup_decl(expr['type'] + "List")
434 fdef.write(generate_type_cleanup(expr['type'] + "List") + "\n")
fb3182ce
MR
435 ret += generate_type_cleanup_decl(expr['type'])
436 fdef.write(generate_type_cleanup(expr['type']) + "\n")
437 elif expr.has_key('union'):
e2503f5e 438 ret += generate_union(expr)
dc8fb6df
PB
439 ret += generate_type_cleanup_decl(expr['union'] + "List")
440 fdef.write(generate_type_cleanup(expr['union'] + "List") + "\n")
441 ret += generate_type_cleanup_decl(expr['union'])
442 fdef.write(generate_type_cleanup(expr['union']) + "\n")
b9c4b48d
AK
443 elif expr.has_key('enum'):
444 ret += generate_type_cleanup_decl(expr['enum'] + "List")
445 fdef.write(generate_type_cleanup(expr['enum'] + "List") + "\n")
fb3182ce
MR
446 else:
447 continue
448 fdecl.write(ret)
449
450fdecl.write('''
451#endif
452''')
453
454fdecl.flush()
455fdecl.close()
776574d6
AL
456
457fdef.flush()
458fdef.close()
This page took 0.367576 seconds and 4 git commands to generate.