]> git.proxmox.com Git - qemu.git/blame - scripts/qapi-types.py
qga: Fix two format strings for MinGW
[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 <aliguori@us.ibm.com>
8#
9# This work is licensed under the terms of the GNU GPLv2.
10# See the COPYING.LIB file in the top-level directory.
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
f01f594b
LC
130def generate_enum_name(name):
131 if name.isupper():
eda50a65 132 return c_fun(name, False)
f01f594b 133 new_name = ''
eda50a65 134 for c in c_fun(name, False):
f01f594b
LC
135 if c.isupper():
136 new_name += '_'
137 new_name += c
138 return new_name.lstrip('_').upper()
139
fb3182ce
MR
140def generate_enum(name, values):
141 lookup_decl = mcgen('''
142extern const char *%(name)s_lookup[];
143''',
144 name=name)
145
146 enum_decl = mcgen('''
147typedef enum %(name)s
148{
149''',
150 name=name)
151
303b54b1
LC
152 # append automatically generated _MAX value
153 enum_values = values + [ 'MAX' ]
154
fb3182ce 155 i = 0
303b54b1 156 for value in enum_values:
fb3182ce
MR
157 enum_decl += mcgen('''
158 %(abbrev)s_%(value)s = %(i)d,
159''',
160 abbrev=de_camel_case(name).upper(),
f01f594b 161 value=generate_enum_name(value),
fb3182ce
MR
162 i=i)
163 i += 1
164
165 enum_decl += mcgen('''
166} %(name)s;
167''',
168 name=name)
169
170 return lookup_decl + enum_decl
171
69dd62df
KW
172def generate_anon_union_qtypes(expr):
173
174 name = expr['union']
175 members = expr['data']
176
177 ret = mcgen('''
178const int %(name)s_qtypes[QTYPE_MAX] = {
179''',
180 name=name)
181
182 for key in members:
183 qapi_type = members[key]
184 if builtin_type_qtypes.has_key(qapi_type):
185 qtype = builtin_type_qtypes[qapi_type]
186 elif find_struct(qapi_type):
187 qtype = "QTYPE_QDICT"
188 elif find_union(qapi_type):
189 qtype = "QTYPE_QDICT"
190 else:
191 assert False, "Invalid anonymous union member"
192
193 ret += mcgen('''
194 [ %(qtype)s ] = %(abbrev)s_KIND_%(enum)s,
195''',
196 qtype = qtype,
197 abbrev = de_camel_case(name).upper(),
198 enum = c_fun(de_camel_case(key),False).upper())
199
200 ret += mcgen('''
201};
202''')
203 return ret
204
205
e2503f5e
KW
206def generate_union(expr):
207
208 name = expr['union']
209 typeinfo = expr['data']
50f2bdc7 210
e2503f5e 211 base = expr.get('base')
50f2bdc7 212 discriminator = expr.get('discriminator')
e2503f5e 213
fb3182ce
MR
214 ret = mcgen('''
215struct %(name)s
216{
217 %(name)sKind kind;
218 union {
dc8fb6df 219 void *data;
fb3182ce
MR
220''',
221 name=name)
222
223 for key in typeinfo:
224 ret += mcgen('''
225 %(c_type)s %(c_name)s;
226''',
227 c_type=c_type(typeinfo[key]),
c9da228b 228 c_name=c_fun(key))
fb3182ce
MR
229
230 ret += mcgen('''
231 };
e2503f5e
KW
232''')
233
234 if base:
50f2bdc7
KW
235 base_fields = find_struct(base)['data']
236 if discriminator:
237 base_fields = base_fields.copy()
238 del base_fields[discriminator]
239 ret += generate_struct_fields(base_fields)
240 else:
241 assert not discriminator
e2503f5e
KW
242
243 ret += mcgen('''
fb3182ce
MR
244};
245''')
69dd62df
KW
246 if discriminator == {}:
247 ret += mcgen('''
248extern const int %(name)s_qtypes[];
249''',
250 name=name)
251
fb3182ce
MR
252
253 return ret
254
255def generate_type_cleanup_decl(name):
256 ret = mcgen('''
257void qapi_free_%(type)s(%(c_type)s obj);
258''',
259 c_type=c_type(name),type=name)
260 return ret
261
262def generate_type_cleanup(name):
263 ret = mcgen('''
c0afa9c5 264
fb3182ce
MR
265void qapi_free_%(type)s(%(c_type)s obj)
266{
267 QapiDeallocVisitor *md;
268 Visitor *v;
269
270 if (!obj) {
271 return;
272 }
273
274 md = qapi_dealloc_visitor_new();
275 v = qapi_dealloc_get_visitor(md);
276 visit_type_%(type)s(v, &obj, NULL, NULL);
277 qapi_dealloc_visitor_cleanup(md);
278}
279''',
280 c_type=c_type(name),type=name)
281 return ret
282
283
284try:
c0afa9c5
MR
285 opts, args = getopt.gnu_getopt(sys.argv[1:], "chbp:o:",
286 ["source", "header", "builtins",
287 "prefix=", "output-dir="])
fb3182ce
MR
288except getopt.GetoptError, err:
289 print str(err)
290 sys.exit(1)
291
292output_dir = ""
293prefix = ""
294c_file = 'qapi-types.c'
295h_file = 'qapi-types.h'
296
8d3bc517
AK
297do_c = False
298do_h = False
c0afa9c5 299do_builtins = False
8d3bc517 300
fb3182ce
MR
301for o, a in opts:
302 if o in ("-p", "--prefix"):
303 prefix = a
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 <aliguori@us.ibm.com>
346 * Michael Roth <mdroth@linux.vnet.ibm.com>
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 <aliguori@us.ibm.com>
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
384exprs = parse_schema(sys.stdin)
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"
402 ret += generate_enum('%sKind' % expr['union'], expr['data'].keys())
dc8fb6df 403 fdef.write(generate_enum_lookup('%sKind' % expr['union'], expr['data'].keys()))
69dd62df
KW
404 if expr.get('discriminator') == {}:
405 fdef.write(generate_anon_union_qtypes(expr))
fb3182ce
MR
406 else:
407 continue
408 fdecl.write(ret)
409
c0afa9c5
MR
410# to avoid header dependency hell, we always generate declarations
411# for built-in types in our header files and simply guard them
412fdecl.write(guardstart("QAPI_TYPES_BUILTIN_CLEANUP_DECL"))
413for typename in builtin_types:
414 fdecl.write(generate_type_cleanup_decl(typename + "List"))
415fdecl.write(guardend("QAPI_TYPES_BUILTIN_CLEANUP_DECL"))
416
417# ...this doesn't work for cases where we link in multiple objects that
418# have the functions defined, so we use -b option to provide control
419# over these cases
420if do_builtins:
421 fdef.write(guardstart("QAPI_TYPES_BUILTIN_CLEANUP_DEF"))
422 for typename in builtin_types:
423 fdef.write(generate_type_cleanup(typename + "List"))
424 fdef.write(guardend("QAPI_TYPES_BUILTIN_CLEANUP_DEF"))
425
fb3182ce
MR
426for expr in exprs:
427 ret = "\n"
428 if expr.has_key('type'):
14d36307 429 ret += generate_struct(expr) + "\n"
75b96aca
MR
430 ret += generate_type_cleanup_decl(expr['type'] + "List")
431 fdef.write(generate_type_cleanup(expr['type'] + "List") + "\n")
fb3182ce
MR
432 ret += generate_type_cleanup_decl(expr['type'])
433 fdef.write(generate_type_cleanup(expr['type']) + "\n")
434 elif expr.has_key('union'):
e2503f5e 435 ret += generate_union(expr)
dc8fb6df
PB
436 ret += generate_type_cleanup_decl(expr['union'] + "List")
437 fdef.write(generate_type_cleanup(expr['union'] + "List") + "\n")
438 ret += generate_type_cleanup_decl(expr['union'])
439 fdef.write(generate_type_cleanup(expr['union']) + "\n")
b9c4b48d
AK
440 elif expr.has_key('enum'):
441 ret += generate_type_cleanup_decl(expr['enum'] + "List")
442 fdef.write(generate_type_cleanup(expr['enum'] + "List") + "\n")
fb3182ce
MR
443 else:
444 continue
445 fdecl.write(ret)
446
447fdecl.write('''
448#endif
449''')
450
451fdecl.flush()
452fdecl.close()
776574d6
AL
453
454fdef.flush()
455fdef.close()