ui/vnc: optimize full scanline updates
[qemu/ar7.git] / scripts / qapi-types.py
blob1eb272dd2644a51669752bcae9cb84bb2ea3440f
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 GPL, version 2.
10 # See the COPYING 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, builtin_type=False):
20 if builtin_type:
21 return mcgen('''
23 typedef struct %(name)sList
25 union {
26 %(type)s value;
27 uint64_t padding;
29 struct %(name)sList *next;
30 } %(name)sList;
31 ''',
32 type=c_type(name),
33 name=name)
35 return mcgen('''
37 typedef struct %(name)s %(name)s;
39 typedef struct %(name)sList
41 union {
42 %(name)s *value;
43 uint64_t padding;
45 struct %(name)sList *next;
46 } %(name)sList;
47 ''',
48 name=name)
50 def generate_fwd_enum_struct(name, members):
51 return mcgen('''
52 typedef struct %(name)sList
54 union {
55 %(name)s value;
56 uint64_t padding;
58 struct %(name)sList *next;
59 } %(name)sList;
60 ''',
61 name=name)
63 def generate_struct_fields(members):
64 ret = ''
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()
74 ret += generate_struct({ "field": argname, "data": argentry})
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))
82 return ret
84 def generate_struct(expr):
86 structname = expr.get('type', "")
87 fieldname = expr.get('field', "")
88 members = expr['data']
89 base = expr.get('base')
91 ret = mcgen('''
92 struct %(name)s
94 ''',
95 name=structname)
97 if base:
98 ret += generate_struct_fields({'base': base})
100 ret += generate_struct_fields(members)
102 # Make sure that all structs have at least one field; this avoids
103 # potential issues with attempting to malloc space for zero-length structs
104 # in C, and also incompatibility with C++ (where an empty struct is size 1).
105 if not base and not members:
106 ret += mcgen('''
107 char qapi_dummy_field_for_empty_struct;
108 ''')
110 if len(fieldname):
111 fieldname = " " + fieldname
112 ret += mcgen('''
113 }%(field)s;
114 ''',
115 field=fieldname)
117 return ret
119 def generate_enum_lookup(name, values):
120 ret = mcgen('''
121 const char *%(name)s_lookup[] = {
122 ''',
123 name=name)
124 i = 0
125 for value in values:
126 ret += mcgen('''
127 "%(value)s",
128 ''',
129 value=value)
131 ret += mcgen('''
132 NULL,
135 ''')
136 return ret
138 def generate_enum(name, values):
139 lookup_decl = mcgen('''
140 extern const char *%(name)s_lookup[];
141 ''',
142 name=name)
144 enum_decl = mcgen('''
145 typedef enum %(name)s
147 ''',
148 name=name)
150 # append automatically generated _MAX value
151 enum_values = values + [ 'MAX' ]
153 i = 0
154 for value in enum_values:
155 enum_full_value = generate_enum_full_value(name, value)
156 enum_decl += mcgen('''
157 %(enum_full_value)s = %(i)d,
158 ''',
159 enum_full_value = enum_full_value,
160 i=i)
161 i += 1
163 enum_decl += mcgen('''
164 } %(name)s;
165 ''',
166 name=name)
168 return lookup_decl + enum_decl
170 def generate_anon_union_qtypes(expr):
172 name = expr['union']
173 members = expr['data']
175 ret = mcgen('''
176 const int %(name)s_qtypes[QTYPE_MAX] = {
177 ''',
178 name=name)
180 for key in members:
181 qapi_type = members[key]
182 if builtin_type_qtypes.has_key(qapi_type):
183 qtype = builtin_type_qtypes[qapi_type]
184 elif find_struct(qapi_type):
185 qtype = "QTYPE_QDICT"
186 elif find_union(qapi_type):
187 qtype = "QTYPE_QDICT"
188 elif find_enum(qapi_type):
189 qtype = "QTYPE_QSTRING"
190 else:
191 assert False, "Invalid anonymous union member"
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())
200 ret += mcgen('''
202 ''')
203 return ret
206 def generate_union(expr):
208 name = expr['union']
209 typeinfo = expr['data']
211 base = expr.get('base')
212 discriminator = expr.get('discriminator')
214 enum_define = discriminator_find_enum_define(expr)
215 if enum_define:
216 discriminator_type_name = enum_define['enum_name']
217 else:
218 discriminator_type_name = '%sKind' % (name)
220 ret = mcgen('''
221 struct %(name)s
223 %(discriminator_type_name)s kind;
224 union {
225 void *data;
226 ''',
227 name=name,
228 discriminator_type_name=discriminator_type_name)
230 for key in typeinfo:
231 ret += mcgen('''
232 %(c_type)s %(c_name)s;
233 ''',
234 c_type=c_type(typeinfo[key]),
235 c_name=c_fun(key))
237 ret += mcgen('''
239 ''')
241 if base:
242 base_fields = find_struct(base)['data']
243 if discriminator:
244 base_fields = base_fields.copy()
245 del base_fields[discriminator]
246 ret += generate_struct_fields(base_fields)
247 else:
248 assert not discriminator
250 ret += mcgen('''
252 ''')
253 if discriminator == {}:
254 ret += mcgen('''
255 extern const int %(name)s_qtypes[];
256 ''',
257 name=name)
260 return ret
262 def generate_type_cleanup_decl(name):
263 ret = mcgen('''
264 void qapi_free_%(type)s(%(c_type)s obj);
265 ''',
266 c_type=c_type(name),type=name)
267 return ret
269 def generate_type_cleanup(name):
270 ret = mcgen('''
272 void qapi_free_%(type)s(%(c_type)s obj)
274 QapiDeallocVisitor *md;
275 Visitor *v;
277 if (!obj) {
278 return;
281 md = qapi_dealloc_visitor_new();
282 v = qapi_dealloc_get_visitor(md);
283 visit_type_%(type)s(v, &obj, NULL, NULL);
284 qapi_dealloc_visitor_cleanup(md);
286 ''',
287 c_type=c_type(name),type=name)
288 return ret
291 try:
292 opts, args = getopt.gnu_getopt(sys.argv[1:], "chbp:i:o:",
293 ["source", "header", "builtins",
294 "prefix=", "input-file=", "output-dir="])
295 except getopt.GetoptError, err:
296 print str(err)
297 sys.exit(1)
299 output_dir = ""
300 input_file = ""
301 prefix = ""
302 c_file = 'qapi-types.c'
303 h_file = 'qapi-types.h'
305 do_c = False
306 do_h = False
307 do_builtins = False
309 for o, a in opts:
310 if o in ("-p", "--prefix"):
311 prefix = a
312 elif o in ("-i", "--input-file"):
313 input_file = a
314 elif o in ("-o", "--output-dir"):
315 output_dir = a + "/"
316 elif o in ("-c", "--source"):
317 do_c = True
318 elif o in ("-h", "--header"):
319 do_h = True
320 elif o in ("-b", "--builtins"):
321 do_builtins = True
323 if not do_c and not do_h:
324 do_c = True
325 do_h = True
327 c_file = output_dir + prefix + c_file
328 h_file = output_dir + prefix + h_file
330 try:
331 os.makedirs(output_dir)
332 except os.error, e:
333 if e.errno != errno.EEXIST:
334 raise
336 def maybe_open(really, name, opt):
337 if really:
338 return open(name, opt)
339 else:
340 import StringIO
341 return StringIO.StringIO()
343 fdef = maybe_open(do_c, c_file, 'w')
344 fdecl = maybe_open(do_h, h_file, 'w')
346 fdef.write(mcgen('''
347 /* AUTOMATICALLY GENERATED, DO NOT MODIFY */
350 * deallocation functions for schema-defined QAPI types
352 * Copyright IBM, Corp. 2011
354 * Authors:
355 * Anthony Liguori <aliguori@us.ibm.com>
356 * Michael Roth <mdroth@linux.vnet.ibm.com>
358 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
359 * See the COPYING.LIB file in the top-level directory.
363 #include "qapi/dealloc-visitor.h"
364 #include "%(prefix)sqapi-types.h"
365 #include "%(prefix)sqapi-visit.h"
367 ''', prefix=prefix))
369 fdecl.write(mcgen('''
370 /* AUTOMATICALLY GENERATED, DO NOT MODIFY */
373 * schema-defined QAPI types
375 * Copyright IBM, Corp. 2011
377 * Authors:
378 * Anthony Liguori <aliguori@us.ibm.com>
380 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
381 * See the COPYING.LIB file in the top-level directory.
385 #ifndef %(guard)s
386 #define %(guard)s
388 #include <stdbool.h>
389 #include <stdint.h>
391 ''',
392 guard=guardname(h_file)))
394 exprs = parse_schema(input_file)
395 exprs = filter(lambda expr: not expr.has_key('gen'), exprs)
397 fdecl.write(guardstart("QAPI_TYPES_BUILTIN_STRUCT_DECL"))
398 for typename in builtin_types:
399 fdecl.write(generate_fwd_struct(typename, None, builtin_type=True))
400 fdecl.write(guardend("QAPI_TYPES_BUILTIN_STRUCT_DECL"))
402 for expr in exprs:
403 ret = "\n"
404 if expr.has_key('type'):
405 ret += generate_fwd_struct(expr['type'], expr['data'])
406 elif expr.has_key('enum'):
407 ret += generate_enum(expr['enum'], expr['data']) + "\n"
408 ret += generate_fwd_enum_struct(expr['enum'], expr['data'])
409 fdef.write(generate_enum_lookup(expr['enum'], expr['data']))
410 elif expr.has_key('union'):
411 ret += generate_fwd_struct(expr['union'], expr['data']) + "\n"
412 enum_define = discriminator_find_enum_define(expr)
413 if not enum_define:
414 ret += generate_enum('%sKind' % expr['union'], expr['data'].keys())
415 fdef.write(generate_enum_lookup('%sKind' % expr['union'],
416 expr['data'].keys()))
417 if expr.get('discriminator') == {}:
418 fdef.write(generate_anon_union_qtypes(expr))
419 else:
420 continue
421 fdecl.write(ret)
423 # to avoid header dependency hell, we always generate declarations
424 # for built-in types in our header files and simply guard them
425 fdecl.write(guardstart("QAPI_TYPES_BUILTIN_CLEANUP_DECL"))
426 for typename in builtin_types:
427 fdecl.write(generate_type_cleanup_decl(typename + "List"))
428 fdecl.write(guardend("QAPI_TYPES_BUILTIN_CLEANUP_DECL"))
430 # ...this doesn't work for cases where we link in multiple objects that
431 # have the functions defined, so we use -b option to provide control
432 # over these cases
433 if do_builtins:
434 fdef.write(guardstart("QAPI_TYPES_BUILTIN_CLEANUP_DEF"))
435 for typename in builtin_types:
436 fdef.write(generate_type_cleanup(typename + "List"))
437 fdef.write(guardend("QAPI_TYPES_BUILTIN_CLEANUP_DEF"))
439 for expr in exprs:
440 ret = "\n"
441 if expr.has_key('type'):
442 ret += generate_struct(expr) + "\n"
443 ret += generate_type_cleanup_decl(expr['type'] + "List")
444 fdef.write(generate_type_cleanup(expr['type'] + "List") + "\n")
445 ret += generate_type_cleanup_decl(expr['type'])
446 fdef.write(generate_type_cleanup(expr['type']) + "\n")
447 elif expr.has_key('union'):
448 ret += generate_union(expr)
449 ret += generate_type_cleanup_decl(expr['union'] + "List")
450 fdef.write(generate_type_cleanup(expr['union'] + "List") + "\n")
451 ret += generate_type_cleanup_decl(expr['union'])
452 fdef.write(generate_type_cleanup(expr['union']) + "\n")
453 elif expr.has_key('enum'):
454 ret += generate_type_cleanup_decl(expr['enum'] + "List")
455 fdef.write(generate_type_cleanup(expr['enum'] + "List") + "\n")
456 else:
457 continue
458 fdecl.write(ret)
460 fdecl.write('''
461 #endif
462 ''')
464 fdecl.flush()
465 fdecl.close()
467 fdef.flush()
468 fdef.close()