]> Git Repo - qemu.git/blob - scripts/qapi-types.py
Merge remote-tracking branch 'afaerber/tags/qom-cpu-for-anthony' into staging
[qemu.git] / scripts / qapi-types.py
1 #
2 # QAPI types generator
3 #
4 # Copyright IBM, Corp. 2011
5 #
6 # Authors:
7 #  Anthony Liguori <[email protected]>
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
12 from ordereddict import OrderedDict
13 from qapi import *
14 import sys
15 import os
16 import getopt
17 import errno
18
19 def generate_fwd_struct(name, members, builtin_type=False):
20     if builtin_type:
21         return mcgen('''
22
23 typedef struct %(name)sList
24 {
25     union {
26         %(type)s value;
27         uint64_t padding;
28     };
29     struct %(name)sList *next;
30 } %(name)sList;
31 ''',
32                      type=c_type(name),
33                      name=name)
34
35     return mcgen('''
36
37 typedef struct %(name)s %(name)s;
38
39 typedef struct %(name)sList
40 {
41     union {
42         %(name)s *value;
43         uint64_t padding;
44     };
45     struct %(name)sList *next;
46 } %(name)sList;
47 ''',
48                  name=name)
49
50 def generate_fwd_enum_struct(name, members):
51     return mcgen('''
52 typedef struct %(name)sList
53 {
54     %(name)s value;
55     struct %(name)sList *next;
56 } %(name)sList;
57 ''',
58                  name=name)
59
60 def generate_struct_fields(members):
61     ret = ''
62
63     for argname, argentry, optional, structured in parse_args(members):
64         if optional:
65             ret += mcgen('''
66     bool has_%(c_name)s;
67 ''',
68                          c_name=c_var(argname))
69         if structured:
70             push_indent()
71             ret += generate_struct("", argname, argentry)
72             pop_indent()
73         else:
74             ret += mcgen('''
75     %(c_type)s %(c_name)s;
76 ''',
77                      c_type=c_type(argentry), c_name=c_var(argname))
78
79     return ret
80
81 def generate_struct(structname, fieldname, members):
82     ret = mcgen('''
83 struct %(name)s
84 {
85 ''',
86           name=structname)
87
88     ret += generate_struct_fields(members)
89
90     if len(fieldname):
91         fieldname = " " + fieldname
92     ret += mcgen('''
93 }%(field)s;
94 ''',
95             field=fieldname)
96
97     return ret
98
99 def generate_enum_lookup(name, values):
100     ret = mcgen('''
101 const char *%(name)s_lookup[] = {
102 ''',
103                          name=name)
104     i = 0
105     for value in values:
106         ret += mcgen('''
107     "%(value)s",
108 ''',
109                      value=value)
110
111     ret += mcgen('''
112     NULL,
113 };
114
115 ''')
116     return ret
117
118 def generate_enum_name(name):
119     if name.isupper():
120         return c_fun(name, False)
121     new_name = ''
122     for c in c_fun(name, False):
123         if c.isupper():
124             new_name += '_'
125         new_name += c
126     return new_name.lstrip('_').upper()
127
128 def generate_enum(name, values):
129     lookup_decl = mcgen('''
130 extern const char *%(name)s_lookup[];
131 ''',
132                 name=name)
133
134     enum_decl = mcgen('''
135 typedef enum %(name)s
136 {
137 ''',
138                 name=name)
139
140     # append automatically generated _MAX value
141     enum_values = values + [ 'MAX' ]
142
143     i = 0
144     for value in enum_values:
145         enum_decl += mcgen('''
146     %(abbrev)s_%(value)s = %(i)d,
147 ''',
148                      abbrev=de_camel_case(name).upper(),
149                      value=generate_enum_name(value),
150                      i=i)
151         i += 1
152
153     enum_decl += mcgen('''
154 } %(name)s;
155 ''',
156                  name=name)
157
158     return lookup_decl + enum_decl
159
160 def generate_anon_union_qtypes(expr):
161
162     name = expr['union']
163     members = expr['data']
164
165     ret = mcgen('''
166 const int %(name)s_qtypes[QTYPE_MAX] = {
167 ''',
168     name=name)
169
170     for key in members:
171         qapi_type = members[key]
172         if builtin_type_qtypes.has_key(qapi_type):
173             qtype = builtin_type_qtypes[qapi_type]
174         elif find_struct(qapi_type):
175             qtype = "QTYPE_QDICT"
176         elif find_union(qapi_type):
177             qtype = "QTYPE_QDICT"
178         else:
179             assert False, "Invalid anonymous union member"
180
181         ret += mcgen('''
182     [ %(qtype)s ] = %(abbrev)s_KIND_%(enum)s,
183 ''',
184         qtype = qtype,
185         abbrev = de_camel_case(name).upper(),
186         enum = c_fun(de_camel_case(key),False).upper())
187
188     ret += mcgen('''
189 };
190 ''')
191     return ret
192
193
194 def generate_union(expr):
195
196     name = expr['union']
197     typeinfo = expr['data']
198
199     base = expr.get('base')
200     discriminator = expr.get('discriminator')
201
202     ret = mcgen('''
203 struct %(name)s
204 {
205     %(name)sKind kind;
206     union {
207         void *data;
208 ''',
209                 name=name)
210
211     for key in typeinfo:
212         ret += mcgen('''
213         %(c_type)s %(c_name)s;
214 ''',
215                      c_type=c_type(typeinfo[key]),
216                      c_name=c_fun(key))
217
218     ret += mcgen('''
219     };
220 ''')
221
222     if base:
223         base_fields = find_struct(base)['data']
224         if discriminator:
225             base_fields = base_fields.copy()
226             del base_fields[discriminator]
227         ret += generate_struct_fields(base_fields)
228     else:
229         assert not discriminator
230
231     ret += mcgen('''
232 };
233 ''')
234     if discriminator == {}:
235         ret += mcgen('''
236 extern const int %(name)s_qtypes[];
237 ''',
238             name=name)
239
240
241     return ret
242
243 def generate_type_cleanup_decl(name):
244     ret = mcgen('''
245 void qapi_free_%(type)s(%(c_type)s obj);
246 ''',
247                 c_type=c_type(name),type=name)
248     return ret
249
250 def generate_type_cleanup(name):
251     ret = mcgen('''
252
253 void qapi_free_%(type)s(%(c_type)s obj)
254 {
255     QapiDeallocVisitor *md;
256     Visitor *v;
257
258     if (!obj) {
259         return;
260     }
261
262     md = qapi_dealloc_visitor_new();
263     v = qapi_dealloc_get_visitor(md);
264     visit_type_%(type)s(v, &obj, NULL, NULL);
265     qapi_dealloc_visitor_cleanup(md);
266 }
267 ''',
268                 c_type=c_type(name),type=name)
269     return ret
270
271
272 try:
273     opts, args = getopt.gnu_getopt(sys.argv[1:], "chbp:o:",
274                                    ["source", "header", "builtins",
275                                     "prefix=", "output-dir="])
276 except getopt.GetoptError, err:
277     print str(err)
278     sys.exit(1)
279
280 output_dir = ""
281 prefix = ""
282 c_file = 'qapi-types.c'
283 h_file = 'qapi-types.h'
284
285 do_c = False
286 do_h = False
287 do_builtins = False
288
289 for o, a in opts:
290     if o in ("-p", "--prefix"):
291         prefix = a
292     elif o in ("-o", "--output-dir"):
293         output_dir = a + "/"
294     elif o in ("-c", "--source"):
295         do_c = True
296     elif o in ("-h", "--header"):
297         do_h = True
298     elif o in ("-b", "--builtins"):
299         do_builtins = True
300
301 if not do_c and not do_h:
302     do_c = True
303     do_h = True
304
305 c_file = output_dir + prefix + c_file
306 h_file = output_dir + prefix + h_file
307
308 try:
309     os.makedirs(output_dir)
310 except os.error, e:
311     if e.errno != errno.EEXIST:
312         raise
313
314 def maybe_open(really, name, opt):
315     if really:
316         return open(name, opt)
317     else:
318         import StringIO
319         return StringIO.StringIO()
320
321 fdef = maybe_open(do_c, c_file, 'w')
322 fdecl = maybe_open(do_h, h_file, 'w')
323
324 fdef.write(mcgen('''
325 /* AUTOMATICALLY GENERATED, DO NOT MODIFY */
326
327 /*
328  * deallocation functions for schema-defined QAPI types
329  *
330  * Copyright IBM, Corp. 2011
331  *
332  * Authors:
333  *  Anthony Liguori   <[email protected]>
334  *  Michael Roth      <[email protected]>
335  *
336  * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
337  * See the COPYING.LIB file in the top-level directory.
338  *
339  */
340
341 #include "qapi/dealloc-visitor.h"
342 #include "%(prefix)sqapi-types.h"
343 #include "%(prefix)sqapi-visit.h"
344
345 ''',             prefix=prefix))
346
347 fdecl.write(mcgen('''
348 /* AUTOMATICALLY GENERATED, DO NOT MODIFY */
349
350 /*
351  * schema-defined QAPI types
352  *
353  * Copyright IBM, Corp. 2011
354  *
355  * Authors:
356  *  Anthony Liguori   <[email protected]>
357  *
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.
360  *
361  */
362
363 #ifndef %(guard)s
364 #define %(guard)s
365
366 #include <stdbool.h>
367 #include <stdint.h>
368
369 ''',
370                   guard=guardname(h_file)))
371
372 exprs = parse_schema(sys.stdin)
373 exprs = filter(lambda expr: not expr.has_key('gen'), exprs)
374
375 fdecl.write(guardstart("QAPI_TYPES_BUILTIN_STRUCT_DECL"))
376 for typename in builtin_types:
377     fdecl.write(generate_fwd_struct(typename, None, builtin_type=True))
378 fdecl.write(guardend("QAPI_TYPES_BUILTIN_STRUCT_DECL"))
379
380 for expr in exprs:
381     ret = "\n"
382     if expr.has_key('type'):
383         ret += generate_fwd_struct(expr['type'], expr['data'])
384     elif expr.has_key('enum'):
385         ret += generate_enum(expr['enum'], expr['data']) + "\n"
386         ret += generate_fwd_enum_struct(expr['enum'], expr['data'])
387         fdef.write(generate_enum_lookup(expr['enum'], expr['data']))
388     elif expr.has_key('union'):
389         ret += generate_fwd_struct(expr['union'], expr['data']) + "\n"
390         ret += generate_enum('%sKind' % expr['union'], expr['data'].keys())
391         fdef.write(generate_enum_lookup('%sKind' % expr['union'], expr['data'].keys()))
392         if expr.get('discriminator') == {}:
393             fdef.write(generate_anon_union_qtypes(expr))
394     else:
395         continue
396     fdecl.write(ret)
397
398 # to avoid header dependency hell, we always generate declarations
399 # for built-in types in our header files and simply guard them
400 fdecl.write(guardstart("QAPI_TYPES_BUILTIN_CLEANUP_DECL"))
401 for typename in builtin_types:
402     fdecl.write(generate_type_cleanup_decl(typename + "List"))
403 fdecl.write(guardend("QAPI_TYPES_BUILTIN_CLEANUP_DECL"))
404
405 # ...this doesn't work for cases where we link in multiple objects that
406 # have the functions defined, so we use -b option to provide control
407 # over these cases
408 if do_builtins:
409     fdef.write(guardstart("QAPI_TYPES_BUILTIN_CLEANUP_DEF"))
410     for typename in builtin_types:
411         fdef.write(generate_type_cleanup(typename + "List"))
412     fdef.write(guardend("QAPI_TYPES_BUILTIN_CLEANUP_DEF"))
413
414 for expr in exprs:
415     ret = "\n"
416     if expr.has_key('type'):
417         ret += generate_struct(expr['type'], "", expr['data']) + "\n"
418         ret += generate_type_cleanup_decl(expr['type'] + "List")
419         fdef.write(generate_type_cleanup(expr['type'] + "List") + "\n")
420         ret += generate_type_cleanup_decl(expr['type'])
421         fdef.write(generate_type_cleanup(expr['type']) + "\n")
422     elif expr.has_key('union'):
423         ret += generate_union(expr)
424         ret += generate_type_cleanup_decl(expr['union'] + "List")
425         fdef.write(generate_type_cleanup(expr['union'] + "List") + "\n")
426         ret += generate_type_cleanup_decl(expr['union'])
427         fdef.write(generate_type_cleanup(expr['union']) + "\n")
428     elif expr.has_key('enum'):
429         ret += generate_type_cleanup_decl(expr['enum'] + "List")
430         fdef.write(generate_type_cleanup(expr['enum'] + "List") + "\n")
431     else:
432         continue
433     fdecl.write(ret)
434
435 fdecl.write('''
436 #endif
437 ''')
438
439 fdecl.flush()
440 fdecl.close()
441
442 fdef.flush()
443 fdef.close()
This page took 0.049175 seconds and 4 git commands to generate.