]> Git Repo - qemu.git/blame - scripts/qapi-types.py
qapi: Factor open_output(), close_output() out of generators
[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 *
fb3182ce 14
c0afa9c5
MR
15def generate_fwd_struct(name, members, builtin_type=False):
16 if builtin_type:
17 return mcgen('''
18
19typedef struct %(name)sList
20{
a678e26c
MR
21 union {
22 %(type)s value;
23 uint64_t padding;
24 };
c0afa9c5
MR
25 struct %(name)sList *next;
26} %(name)sList;
27''',
28 type=c_type(name),
29 name=name)
30
fb3182ce 31 return mcgen('''
c0afa9c5 32
fb3182ce
MR
33typedef struct %(name)s %(name)s;
34
35typedef struct %(name)sList
36{
a678e26c
MR
37 union {
38 %(name)s *value;
39 uint64_t padding;
40 };
fb3182ce
MR
41 struct %(name)sList *next;
42} %(name)sList;
43''',
83a02706 44 name=c_name(name))
fb3182ce 45
b9c4b48d
AK
46def generate_fwd_enum_struct(name, members):
47 return mcgen('''
48typedef struct %(name)sList
49{
02dc4bf5
CR
50 union {
51 %(name)s value;
52 uint64_t padding;
53 };
b9c4b48d
AK
54 struct %(name)sList *next;
55} %(name)sList;
56''',
fce384b8 57 name=c_name(name))
b9c4b48d 58
01537030
KW
59def generate_struct_fields(members):
60 ret = ''
fb3182ce 61
6b5abc7d 62 for argname, argentry, optional in parse_args(members):
fb3182ce
MR
63 if optional:
64 ret += mcgen('''
65 bool has_%(c_name)s;
66''',
18df515e 67 c_name=c_name(argname))
6b5abc7d 68 ret += mcgen('''
fb3182ce
MR
69 %(c_type)s %(c_name)s;
70''',
18df515e 71 c_type=c_type(argentry), c_name=c_name(argname))
fb3182ce 72
01537030
KW
73 return ret
74
14d36307
KW
75def generate_struct(expr):
76
fd41dd4e 77 structname = expr.get('struct', "")
14d36307
KW
78 fieldname = expr.get('field', "")
79 members = expr['data']
622f557f 80 base = expr.get('base')
14d36307 81
01537030
KW
82 ret = mcgen('''
83struct %(name)s
84{
85''',
83a02706 86 name=c_name(structname))
01537030 87
622f557f
KW
88 if base:
89 ret += generate_struct_fields({'base': base})
90
01537030
KW
91 ret += generate_struct_fields(members)
92
83ecb22b
PM
93 # Make sure that all structs have at least one field; this avoids
94 # potential issues with attempting to malloc space for zero-length structs
95 # in C, and also incompatibility with C++ (where an empty struct is size 1).
96 if not base and not members:
97 ret += mcgen('''
98 char qapi_dummy_field_for_empty_struct;
99''')
100
fb3182ce
MR
101 if len(fieldname):
102 fieldname = " " + fieldname
103 ret += mcgen('''
104}%(field)s;
105''',
106 field=fieldname)
107
108 return ret
109
110def generate_enum_lookup(name, values):
111 ret = mcgen('''
112const char *%(name)s_lookup[] = {
113''',
fce384b8 114 name=c_name(name))
fb3182ce
MR
115 i = 0
116 for value in values:
7c81c61f 117 index = c_enum_const(name, value)
fb3182ce 118 ret += mcgen('''
912ae9c8 119 [%(index)s] = "%(value)s",
fb3182ce 120''',
912ae9c8 121 index = index, value = value)
fb3182ce 122
7c81c61f 123 max_index = c_enum_const(name, 'MAX')
fb3182ce 124 ret += mcgen('''
912ae9c8 125 [%(max_index)s] = NULL,
fb3182ce
MR
126};
127
912ae9c8
MT
128''',
129 max_index=max_index)
fb3182ce
MR
130 return ret
131
132def generate_enum(name, values):
fce384b8 133 name = c_name(name)
fb3182ce
MR
134 lookup_decl = mcgen('''
135extern const char *%(name)s_lookup[];
136''',
137 name=name)
138
139 enum_decl = mcgen('''
140typedef enum %(name)s
141{
142''',
143 name=name)
144
303b54b1
LC
145 # append automatically generated _MAX value
146 enum_values = values + [ 'MAX' ]
147
fb3182ce 148 i = 0
303b54b1 149 for value in enum_values:
7c81c61f 150 enum_full_value = c_enum_const(name, value)
fb3182ce 151 enum_decl += mcgen('''
b0b58195 152 %(enum_full_value)s = %(i)d,
fb3182ce 153''',
b0b58195 154 enum_full_value = enum_full_value,
fb3182ce
MR
155 i=i)
156 i += 1
157
158 enum_decl += mcgen('''
159} %(name)s;
160''',
161 name=name)
162
163 return lookup_decl + enum_decl
164
811d04fd 165def generate_alternate_qtypes(expr):
69dd62df 166
ab916fad 167 name = expr['alternate']
69dd62df
KW
168 members = expr['data']
169
170 ret = mcgen('''
171const int %(name)s_qtypes[QTYPE_MAX] = {
172''',
d1f07c86 173 name=c_name(name))
69dd62df
KW
174
175 for key in members:
811d04fd 176 qtype = find_alternate_member_qtype(members[key])
ab916fad 177 assert qtype, "Invalid alternate member"
69dd62df
KW
178
179 ret += mcgen('''
d1f07c86 180 [%(qtype)s] = %(enum_const)s,
69dd62df 181''',
d1f07c86
EB
182 qtype = qtype,
183 enum_const = c_enum_const(name + 'Kind', key))
69dd62df
KW
184
185 ret += mcgen('''
186};
187''')
188 return ret
189
190
ab916fad 191def generate_union(expr, meta):
e2503f5e 192
bb337290 193 name = c_name(expr[meta])
e2503f5e 194 typeinfo = expr['data']
50f2bdc7 195
e2503f5e 196 base = expr.get('base')
50f2bdc7 197 discriminator = expr.get('discriminator')
e2503f5e 198
bceae769
WX
199 enum_define = discriminator_find_enum_define(expr)
200 if enum_define:
201 discriminator_type_name = enum_define['enum_name']
202 else:
203 discriminator_type_name = '%sKind' % (name)
204
fb3182ce
MR
205 ret = mcgen('''
206struct %(name)s
207{
bceae769 208 %(discriminator_type_name)s kind;
fb3182ce 209 union {
dc8fb6df 210 void *data;
fb3182ce 211''',
bceae769 212 name=name,
857af5f0 213 discriminator_type_name=c_name(discriminator_type_name))
fb3182ce
MR
214
215 for key in typeinfo:
216 ret += mcgen('''
217 %(c_type)s %(c_name)s;
218''',
219 c_type=c_type(typeinfo[key]),
18df515e 220 c_name=c_name(key))
fb3182ce
MR
221
222 ret += mcgen('''
223 };
e2503f5e
KW
224''')
225
226 if base:
a8d4a2e4
EB
227 assert discriminator
228 base_fields = find_struct(base)['data'].copy()
229 del base_fields[discriminator]
50f2bdc7
KW
230 ret += generate_struct_fields(base_fields)
231 else:
232 assert not discriminator
e2503f5e
KW
233
234 ret += mcgen('''
fb3182ce
MR
235};
236''')
ab916fad 237 if meta == 'alternate':
69dd62df
KW
238 ret += mcgen('''
239extern const int %(name)s_qtypes[];
240''',
241 name=name)
242
fb3182ce
MR
243
244 return ret
245
246def generate_type_cleanup_decl(name):
247 ret = mcgen('''
fce384b8 248void qapi_free_%(name)s(%(c_type)s obj);
fb3182ce 249''',
fce384b8 250 c_type=c_type(name), name=c_name(name))
fb3182ce
MR
251 return ret
252
253def generate_type_cleanup(name):
254 ret = mcgen('''
c0afa9c5 255
fce384b8 256void qapi_free_%(name)s(%(c_type)s obj)
fb3182ce
MR
257{
258 QapiDeallocVisitor *md;
259 Visitor *v;
260
261 if (!obj) {
262 return;
263 }
264
265 md = qapi_dealloc_visitor_new();
266 v = qapi_dealloc_get_visitor(md);
fce384b8 267 visit_type_%(name)s(v, &obj, NULL, NULL);
fb3182ce
MR
268 qapi_dealloc_visitor_cleanup(md);
269}
270''',
fce384b8 271 c_type=c_type(name), name=c_name(name))
fb3182ce
MR
272 return ret
273
c0afa9c5 274do_builtins = False
8d3bc517 275
2114f5a9
MA
276(input_file, output_dir, do_c, do_h, prefix, opts) = \
277 parse_command_line("b", ["builtins"])
278
fb3182ce 279for o, a in opts:
2114f5a9 280 if o in ("-b", "--builtins"):
c0afa9c5 281 do_builtins = True
8d3bc517 282
12f8e1b9 283c_comment = '''
fb3182ce
MR
284/*
285 * deallocation functions for schema-defined QAPI types
286 *
287 * Copyright IBM, Corp. 2011
288 *
289 * Authors:
290 * Anthony Liguori <[email protected]>
291 * Michael Roth <[email protected]>
292 *
293 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
294 * See the COPYING.LIB file in the top-level directory.
295 *
296 */
12f8e1b9
MA
297'''
298h_comment = '''
fb3182ce
MR
299/*
300 * schema-defined QAPI types
301 *
302 * Copyright IBM, Corp. 2011
303 *
304 * Authors:
305 * Anthony Liguori <[email protected]>
306 *
307 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
308 * See the COPYING.LIB file in the top-level directory.
309 *
310 */
12f8e1b9 311'''
fb3182ce 312
12f8e1b9
MA
313(fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix,
314 'qapi-types.c', 'qapi-types.h',
315 c_comment, h_comment)
fb3182ce 316
12f8e1b9
MA
317fdef.write(mcgen('''
318#include "qapi/dealloc-visitor.h"
319#include "%(prefix)sqapi-types.h"
320#include "%(prefix)sqapi-visit.h"
321
322''',
323 prefix=prefix))
324
325fdecl.write(mcgen('''
da4fea06
IM
326#include <stdbool.h>
327#include <stdint.h>
b68a8472 328
12f8e1b9 329'''))
fb3182ce 330
33aaad52 331exprs = parse_schema(input_file)
5dbee474 332exprs = filter(lambda expr: not expr.has_key('gen'), exprs)
fb3182ce 333
c0afa9c5 334fdecl.write(guardstart("QAPI_TYPES_BUILTIN_STRUCT_DECL"))
b52c4b9c 335for typename in builtin_types.keys():
c0afa9c5
MR
336 fdecl.write(generate_fwd_struct(typename, None, builtin_type=True))
337fdecl.write(guardend("QAPI_TYPES_BUILTIN_STRUCT_DECL"))
338
fb3182ce
MR
339for expr in exprs:
340 ret = "\n"
fd41dd4e
EB
341 if expr.has_key('struct'):
342 ret += generate_fwd_struct(expr['struct'], expr['data'])
fb3182ce 343 elif expr.has_key('enum'):
b9c4b48d
AK
344 ret += generate_enum(expr['enum'], expr['data']) + "\n"
345 ret += generate_fwd_enum_struct(expr['enum'], expr['data'])
fb3182ce
MR
346 fdef.write(generate_enum_lookup(expr['enum'], expr['data']))
347 elif expr.has_key('union'):
348 ret += generate_fwd_struct(expr['union'], expr['data']) + "\n"
bceae769
WX
349 enum_define = discriminator_find_enum_define(expr)
350 if not enum_define:
351 ret += generate_enum('%sKind' % expr['union'], expr['data'].keys())
352 fdef.write(generate_enum_lookup('%sKind' % expr['union'],
353 expr['data'].keys()))
ab916fad
EB
354 elif expr.has_key('alternate'):
355 ret += generate_fwd_struct(expr['alternate'], expr['data']) + "\n"
356 ret += generate_enum('%sKind' % expr['alternate'], expr['data'].keys())
357 fdef.write(generate_enum_lookup('%sKind' % expr['alternate'],
358 expr['data'].keys()))
359 fdef.write(generate_alternate_qtypes(expr))
fb3182ce
MR
360 else:
361 continue
362 fdecl.write(ret)
363
c0afa9c5
MR
364# to avoid header dependency hell, we always generate declarations
365# for built-in types in our header files and simply guard them
366fdecl.write(guardstart("QAPI_TYPES_BUILTIN_CLEANUP_DECL"))
b52c4b9c 367for typename in builtin_types.keys():
c0afa9c5
MR
368 fdecl.write(generate_type_cleanup_decl(typename + "List"))
369fdecl.write(guardend("QAPI_TYPES_BUILTIN_CLEANUP_DECL"))
370
371# ...this doesn't work for cases where we link in multiple objects that
372# have the functions defined, so we use -b option to provide control
373# over these cases
374if do_builtins:
375 fdef.write(guardstart("QAPI_TYPES_BUILTIN_CLEANUP_DEF"))
b52c4b9c 376 for typename in builtin_types.keys():
c0afa9c5
MR
377 fdef.write(generate_type_cleanup(typename + "List"))
378 fdef.write(guardend("QAPI_TYPES_BUILTIN_CLEANUP_DEF"))
379
fb3182ce
MR
380for expr in exprs:
381 ret = "\n"
fd41dd4e 382 if expr.has_key('struct'):
14d36307 383 ret += generate_struct(expr) + "\n"
fd41dd4e
EB
384 ret += generate_type_cleanup_decl(expr['struct'] + "List")
385 fdef.write(generate_type_cleanup(expr['struct'] + "List") + "\n")
386 ret += generate_type_cleanup_decl(expr['struct'])
387 fdef.write(generate_type_cleanup(expr['struct']) + "\n")
fb3182ce 388 elif expr.has_key('union'):
ab916fad 389 ret += generate_union(expr, 'union')
dc8fb6df
PB
390 ret += generate_type_cleanup_decl(expr['union'] + "List")
391 fdef.write(generate_type_cleanup(expr['union'] + "List") + "\n")
392 ret += generate_type_cleanup_decl(expr['union'])
393 fdef.write(generate_type_cleanup(expr['union']) + "\n")
ab916fad
EB
394 elif expr.has_key('alternate'):
395 ret += generate_union(expr, 'alternate')
396 ret += generate_type_cleanup_decl(expr['alternate'] + "List")
397 fdef.write(generate_type_cleanup(expr['alternate'] + "List") + "\n")
398 ret += generate_type_cleanup_decl(expr['alternate'])
399 fdef.write(generate_type_cleanup(expr['alternate']) + "\n")
b9c4b48d
AK
400 elif expr.has_key('enum'):
401 ret += generate_type_cleanup_decl(expr['enum'] + "List")
402 fdef.write(generate_type_cleanup(expr['enum'] + "List") + "\n")
fb3182ce
MR
403 else:
404 continue
405 fdecl.write(ret)
406
12f8e1b9 407close_output(fdef, fdecl)
This page took 0.338541 seconds and 4 git commands to generate.