qdev: Don't assume existence of parent bus on unparenting
[qemu/opensuse.git] / scripts / qapi-types.py
blob9e19920970cc6e71190cc364d52bdc79c120fa3f
2 # QAPI types generator
4 # Copyright IBM, Corp. 2011
6 # Authors:
7 # Anthony Liguori <aliguori@us.ibm.com>
9 # This work is licensed under the terms of the GNU GPLv2.
10 # See the COPYING.LIB file in the top-level directory.
12 from ordereddict import OrderedDict
13 from qapi import *
14 import sys
15 import os
16 import getopt
17 import errno
19 def generate_fwd_struct(name, members):
20 return mcgen('''
21 typedef struct %(name)s %(name)s;
23 typedef struct %(name)sList
25 %(name)s *value;
26 struct %(name)sList *next;
27 } %(name)sList;
28 ''',
29 name=name)
31 def generate_fwd_enum_struct(name, members):
32 return mcgen('''
33 typedef struct %(name)sList
35 %(name)s value;
36 struct %(name)sList *next;
37 } %(name)sList;
38 ''',
39 name=name)
41 def generate_struct(structname, fieldname, members):
42 ret = mcgen('''
43 struct %(name)s
45 ''',
46 name=structname)
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))
64 if len(fieldname):
65 fieldname = " " + fieldname
66 ret += mcgen('''
67 }%(field)s;
68 ''',
69 field=fieldname)
71 return ret
73 def generate_enum_lookup(name, values):
74 ret = mcgen('''
75 const char *%(name)s_lookup[] = {
76 ''',
77 name=name)
78 i = 0
79 for value in values:
80 ret += mcgen('''
81 "%(value)s",
82 ''',
83 value=value)
85 ret += mcgen('''
86 NULL,
89 ''')
90 return ret
92 def generate_enum_name(name):
93 if name.isupper():
94 return c_fun(name, False)
95 new_name = ''
96 for c in c_fun(name, False):
97 if c.isupper():
98 new_name += '_'
99 new_name += c
100 return new_name.lstrip('_').upper()
102 def generate_enum(name, values):
103 lookup_decl = mcgen('''
104 extern const char *%(name)s_lookup[];
105 ''',
106 name=name)
108 enum_decl = mcgen('''
109 typedef enum %(name)s
111 ''',
112 name=name)
114 # append automatically generated _MAX value
115 enum_values = values + [ 'MAX' ]
117 i = 0
118 for value in enum_values:
119 enum_decl += mcgen('''
120 %(abbrev)s_%(value)s = %(i)d,
121 ''',
122 abbrev=de_camel_case(name).upper(),
123 value=generate_enum_name(value),
124 i=i)
125 i += 1
127 enum_decl += mcgen('''
128 } %(name)s;
129 ''',
130 name=name)
132 return lookup_decl + enum_decl
134 def generate_union(name, typeinfo):
135 ret = mcgen('''
136 struct %(name)s
138 %(name)sKind kind;
139 union {
140 void *data;
141 ''',
142 name=name)
144 for key in typeinfo:
145 ret += mcgen('''
146 %(c_type)s %(c_name)s;
147 ''',
148 c_type=c_type(typeinfo[key]),
149 c_name=c_fun(key))
151 ret += mcgen('''
154 ''')
156 return ret
158 def generate_type_cleanup_decl(name):
159 ret = mcgen('''
160 void qapi_free_%(type)s(%(c_type)s obj);
161 ''',
162 c_type=c_type(name),type=name)
163 return ret
165 def generate_type_cleanup(name):
166 ret = mcgen('''
167 void qapi_free_%(type)s(%(c_type)s obj)
169 QapiDeallocVisitor *md;
170 Visitor *v;
172 if (!obj) {
173 return;
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);
181 ''',
182 c_type=c_type(name),type=name)
183 return ret
186 try:
187 opts, args = getopt.gnu_getopt(sys.argv[1:], "chp:o:",
188 ["source", "header", "prefix=", "output-dir="])
189 except getopt.GetoptError, err:
190 print str(err)
191 sys.exit(1)
193 output_dir = ""
194 prefix = ""
195 c_file = 'qapi-types.c'
196 h_file = 'qapi-types.h'
198 do_c = False
199 do_h = False
201 for o, a in opts:
202 if o in ("-p", "--prefix"):
203 prefix = a
204 elif o in ("-o", "--output-dir"):
205 output_dir = a + "/"
206 elif o in ("-c", "--source"):
207 do_c = True
208 elif o in ("-h", "--header"):
209 do_h = True
211 if not do_c and not do_h:
212 do_c = True
213 do_h = True
215 c_file = output_dir + prefix + c_file
216 h_file = output_dir + prefix + h_file
218 try:
219 os.makedirs(output_dir)
220 except os.error, e:
221 if e.errno != errno.EEXIST:
222 raise
224 def maybe_open(really, name, opt):
225 if really:
226 return open(name, opt)
227 else:
228 import StringIO
229 return StringIO.StringIO()
231 fdef = maybe_open(do_c, c_file, 'w')
232 fdecl = maybe_open(do_h, h_file, 'w')
234 fdef.write(mcgen('''
235 /* AUTOMATICALLY GENERATED, DO NOT MODIFY */
238 * deallocation functions for schema-defined QAPI types
240 * Copyright IBM, Corp. 2011
242 * Authors:
243 * Anthony Liguori <aliguori@us.ibm.com>
244 * Michael Roth <mdroth@linux.vnet.ibm.com>
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.
251 #include "qapi/dealloc-visitor.h"
252 #include "%(prefix)sqapi-types.h"
253 #include "%(prefix)sqapi-visit.h"
255 ''', prefix=prefix))
257 fdecl.write(mcgen('''
258 /* AUTOMATICALLY GENERATED, DO NOT MODIFY */
261 * schema-defined QAPI types
263 * Copyright IBM, Corp. 2011
265 * Authors:
266 * Anthony Liguori <aliguori@us.ibm.com>
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.
273 #ifndef %(guard)s
274 #define %(guard)s
276 #include <stdbool.h>
277 #include <stdint.h>
279 ''',
280 guard=guardname(h_file)))
282 exprs = parse_schema(sys.stdin)
283 exprs = filter(lambda expr: not expr.has_key('gen'), exprs)
285 for expr in exprs:
286 ret = "\n"
287 if expr.has_key('type'):
288 ret += generate_fwd_struct(expr['type'], expr['data'])
289 elif expr.has_key('enum'):
290 ret += generate_enum(expr['enum'], expr['data']) + "\n"
291 ret += generate_fwd_enum_struct(expr['enum'], expr['data'])
292 fdef.write(generate_enum_lookup(expr['enum'], expr['data']))
293 elif expr.has_key('union'):
294 ret += generate_fwd_struct(expr['union'], expr['data']) + "\n"
295 ret += generate_enum('%sKind' % expr['union'], expr['data'].keys())
296 fdef.write(generate_enum_lookup('%sKind' % expr['union'], expr['data'].keys()))
297 else:
298 continue
299 fdecl.write(ret)
301 for expr in exprs:
302 ret = "\n"
303 if expr.has_key('type'):
304 ret += generate_struct(expr['type'], "", expr['data']) + "\n"
305 ret += generate_type_cleanup_decl(expr['type'] + "List")
306 fdef.write(generate_type_cleanup(expr['type'] + "List") + "\n")
307 ret += generate_type_cleanup_decl(expr['type'])
308 fdef.write(generate_type_cleanup(expr['type']) + "\n")
309 elif expr.has_key('union'):
310 ret += generate_union(expr['union'], expr['data'])
311 ret += generate_type_cleanup_decl(expr['union'] + "List")
312 fdef.write(generate_type_cleanup(expr['union'] + "List") + "\n")
313 ret += generate_type_cleanup_decl(expr['union'])
314 fdef.write(generate_type_cleanup(expr['union']) + "\n")
315 elif expr.has_key('enum'):
316 ret += generate_type_cleanup_decl(expr['enum'] + "List")
317 fdef.write(generate_type_cleanup(expr['enum'] + "List") + "\n")
318 else:
319 continue
320 fdecl.write(ret)
322 fdecl.write('''
323 #endif
324 ''')
326 fdecl.flush()
327 fdecl.close()
329 fdef.flush()
330 fdef.close()