]> git.proxmox.com Git - qemu.git/blame - scripts/qapi-types.py
Merge remote-tracking branch 'origin/master' into staging
[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
19def generate_fwd_struct(name, members):
20 return mcgen('''
21typedef struct %(name)s %(name)s;
22
23typedef struct %(name)sList
24{
25 %(name)s *value;
26 struct %(name)sList *next;
27} %(name)sList;
28''',
29 name=name)
30
b9c4b48d
AK
31def generate_fwd_enum_struct(name, members):
32 return mcgen('''
33typedef struct %(name)sList
34{
35 %(name)s value;
36 struct %(name)sList *next;
37} %(name)sList;
38''',
39 name=name)
40
fb3182ce
MR
41def generate_struct(structname, fieldname, members):
42 ret = mcgen('''
43struct %(name)s
44{
45''',
46 name=structname)
47
48 for argname, argentry, optional, structured in parse_args(members):
49 if optional:
50 ret += mcgen('''
51 bool has_%(c_name)s;
52''',
53 c_name=c_var(argname))
54 if structured:
55 push_indent()
56 ret += generate_struct("", argname, argentry)
57 pop_indent()
58 else:
59 ret += mcgen('''
60 %(c_type)s %(c_name)s;
61''',
62 c_type=c_type(argentry), c_name=c_var(argname))
63
64 if len(fieldname):
65 fieldname = " " + fieldname
66 ret += mcgen('''
67}%(field)s;
68''',
69 field=fieldname)
70
71 return ret
72
73def generate_enum_lookup(name, values):
74 ret = mcgen('''
75const char *%(name)s_lookup[] = {
76''',
77 name=name)
78 i = 0
79 for value in values:
80 ret += mcgen('''
81 "%(value)s",
82''',
ac4ff701 83 value=value)
fb3182ce
MR
84
85 ret += mcgen('''
86 NULL,
87};
88
89''')
90 return ret
91
f01f594b
LC
92def generate_enum_name(name):
93 if name.isupper():
94 return c_fun(name)
95 new_name = ''
96 for c in c_fun(name):
97 if c.isupper():
98 new_name += '_'
99 new_name += c
100 return new_name.lstrip('_').upper()
101
fb3182ce
MR
102def generate_enum(name, values):
103 lookup_decl = mcgen('''
104extern const char *%(name)s_lookup[];
105''',
106 name=name)
107
108 enum_decl = mcgen('''
109typedef enum %(name)s
110{
111''',
112 name=name)
113
303b54b1
LC
114 # append automatically generated _MAX value
115 enum_values = values + [ 'MAX' ]
116
fb3182ce 117 i = 0
303b54b1 118 for value in enum_values:
fb3182ce
MR
119 enum_decl += mcgen('''
120 %(abbrev)s_%(value)s = %(i)d,
121''',
122 abbrev=de_camel_case(name).upper(),
f01f594b 123 value=generate_enum_name(value),
fb3182ce
MR
124 i=i)
125 i += 1
126
127 enum_decl += mcgen('''
128} %(name)s;
129''',
130 name=name)
131
132 return lookup_decl + enum_decl
133
134def generate_union(name, typeinfo):
135 ret = mcgen('''
136struct %(name)s
137{
138 %(name)sKind kind;
139 union {
dc8fb6df 140 void *data;
fb3182ce
MR
141''',
142 name=name)
143
144 for key in typeinfo:
145 ret += mcgen('''
146 %(c_type)s %(c_name)s;
147''',
148 c_type=c_type(typeinfo[key]),
c9da228b 149 c_name=c_fun(key))
fb3182ce
MR
150
151 ret += mcgen('''
152 };
153};
154''')
155
156 return ret
157
158def generate_type_cleanup_decl(name):
159 ret = mcgen('''
160void qapi_free_%(type)s(%(c_type)s obj);
161''',
162 c_type=c_type(name),type=name)
163 return ret
164
165def generate_type_cleanup(name):
166 ret = mcgen('''
167void qapi_free_%(type)s(%(c_type)s obj)
168{
169 QapiDeallocVisitor *md;
170 Visitor *v;
171
172 if (!obj) {
173 return;
174 }
175
176 md = qapi_dealloc_visitor_new();
177 v = qapi_dealloc_get_visitor(md);
178 visit_type_%(type)s(v, &obj, NULL, NULL);
179 qapi_dealloc_visitor_cleanup(md);
180}
181''',
182 c_type=c_type(name),type=name)
183 return ret
184
185
186try:
8d3bc517
AK
187 opts, args = getopt.gnu_getopt(sys.argv[1:], "chp:o:",
188 ["source", "header", "prefix=", "output-dir="])
fb3182ce
MR
189except getopt.GetoptError, err:
190 print str(err)
191 sys.exit(1)
192
193output_dir = ""
194prefix = ""
195c_file = 'qapi-types.c'
196h_file = 'qapi-types.h'
197
8d3bc517
AK
198do_c = False
199do_h = False
200
fb3182ce
MR
201for o, a in opts:
202 if o in ("-p", "--prefix"):
203 prefix = a
204 elif o in ("-o", "--output-dir"):
205 output_dir = a + "/"
8d3bc517 206 elif o in ("-c", "--source"):
8d3bc517 207 do_c = True
19bf7c87
AK
208 elif o in ("-h", "--header"):
209 do_h = True
8d3bc517
AK
210
211if not do_c and not do_h:
212 do_c = True
213 do_h = True
fb3182ce
MR
214
215c_file = output_dir + prefix + c_file
216h_file = output_dir + prefix + h_file
217
218try:
219 os.makedirs(output_dir)
220except os.error, e:
221 if e.errno != errno.EEXIST:
222 raise
223
8d3bc517 224def maybe_open(really, name, opt):
8d3bc517
AK
225 if really:
226 return open(name, opt)
19bf7c87
AK
227 else:
228 import StringIO
229 return StringIO.StringIO()
8d3bc517
AK
230
231fdef = maybe_open(do_c, c_file, 'w')
232fdecl = maybe_open(do_h, h_file, 'w')
fb3182ce
MR
233
234fdef.write(mcgen('''
235/* AUTOMATICALLY GENERATED, DO NOT MODIFY */
236
237/*
238 * deallocation functions for schema-defined QAPI types
239 *
240 * Copyright IBM, Corp. 2011
241 *
242 * Authors:
243 * Anthony Liguori <aliguori@us.ibm.com>
244 * Michael Roth <mdroth@linux.vnet.ibm.com>
245 *
246 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
247 * See the COPYING.LIB file in the top-level directory.
248 *
249 */
250
251#include "qapi/qapi-dealloc-visitor.h"
252#include "%(prefix)sqapi-types.h"
253#include "%(prefix)sqapi-visit.h"
254
255''', prefix=prefix))
256
257fdecl.write(mcgen('''
258/* AUTOMATICALLY GENERATED, DO NOT MODIFY */
259
260/*
261 * schema-defined QAPI types
262 *
263 * Copyright IBM, Corp. 2011
264 *
265 * Authors:
266 * Anthony Liguori <aliguori@us.ibm.com>
267 *
268 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
269 * See the COPYING.LIB file in the top-level directory.
270 *
271 */
272
273#ifndef %(guard)s
274#define %(guard)s
275
b68a8472
LC
276#include "qemu-common.h"
277
fb3182ce
MR
278''',
279 guard=guardname(h_file)))
280
281exprs = parse_schema(sys.stdin)
5dbee474 282exprs = filter(lambda expr: not expr.has_key('gen'), exprs)
fb3182ce
MR
283
284for expr in exprs:
285 ret = "\n"
286 if expr.has_key('type'):
287 ret += generate_fwd_struct(expr['type'], expr['data'])
288 elif expr.has_key('enum'):
b9c4b48d
AK
289 ret += generate_enum(expr['enum'], expr['data']) + "\n"
290 ret += generate_fwd_enum_struct(expr['enum'], expr['data'])
fb3182ce
MR
291 fdef.write(generate_enum_lookup(expr['enum'], expr['data']))
292 elif expr.has_key('union'):
293 ret += generate_fwd_struct(expr['union'], expr['data']) + "\n"
294 ret += generate_enum('%sKind' % expr['union'], expr['data'].keys())
dc8fb6df 295 fdef.write(generate_enum_lookup('%sKind' % expr['union'], expr['data'].keys()))
fb3182ce
MR
296 else:
297 continue
298 fdecl.write(ret)
299
300for expr in exprs:
301 ret = "\n"
302 if expr.has_key('type'):
303 ret += generate_struct(expr['type'], "", expr['data']) + "\n"
75b96aca
MR
304 ret += generate_type_cleanup_decl(expr['type'] + "List")
305 fdef.write(generate_type_cleanup(expr['type'] + "List") + "\n")
fb3182ce
MR
306 ret += generate_type_cleanup_decl(expr['type'])
307 fdef.write(generate_type_cleanup(expr['type']) + "\n")
308 elif expr.has_key('union'):
309 ret += generate_union(expr['union'], expr['data'])
dc8fb6df
PB
310 ret += generate_type_cleanup_decl(expr['union'] + "List")
311 fdef.write(generate_type_cleanup(expr['union'] + "List") + "\n")
312 ret += generate_type_cleanup_decl(expr['union'])
313 fdef.write(generate_type_cleanup(expr['union']) + "\n")
b9c4b48d
AK
314 elif expr.has_key('enum'):
315 ret += generate_type_cleanup_decl(expr['enum'] + "List")
316 fdef.write(generate_type_cleanup(expr['enum'] + "List") + "\n")
fb3182ce
MR
317 else:
318 continue
319 fdecl.write(ret)
320
321fdecl.write('''
322#endif
323''')
324
325fdecl.flush()
326fdecl.close()
776574d6
AL
327
328fdef.flush()
329fdef.close()