4 # Copyright IBM, Corp. 2011
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
19 def generate_fwd_struct(name
, members
, builtin_type
=False):
23 typedef struct %(name)sList
29 struct %(name)sList *next;
37 typedef struct %(name)s %(name)s;
39 typedef struct %(name)sList
45 struct %(name)sList *next;
50 def generate_fwd_enum_struct(name
, members
):
52 typedef struct %(name)sList
58 struct %(name)sList *next;
63 def generate_struct_fields(members
):
66 for argname
, argentry
, optional
in parse_args(members
):
71 c_name
=c_name(argname
))
73 %(c_type)s %(c_name)s;
75 c_type
=c_type(argentry
), c_name
=c_name(argname
))
79 def generate_struct(expr
):
81 structname
= expr
.get('struct', "")
82 fieldname
= expr
.get('field', "")
83 members
= expr
['data']
84 base
= expr
.get('base')
93 ret
+= generate_struct_fields({'base': base
})
95 ret
+= generate_struct_fields(members
)
97 # Make sure that all structs have at least one field; this avoids
98 # potential issues with attempting to malloc space for zero-length structs
99 # in C, and also incompatibility with C++ (where an empty struct is size 1).
100 if not base
and not members
:
102 char qapi_dummy_field_for_empty_struct;
106 fieldname
= " " + fieldname
114 def generate_enum_lookup(name
, values
):
116 const char *%(name)s_lookup[] = {
121 index
= generate_enum_full_value(name
, value
)
123 [%(index)s] = "%(value)s",
125 index
= index
, value
= value
)
127 max_index
= generate_enum_full_value(name
, 'MAX')
129 [%(max_index)s] = NULL,
136 def generate_enum(name
, values
):
137 lookup_decl
= mcgen('''
138 extern const char *%(name)s_lookup[];
142 enum_decl
= mcgen('''
143 typedef enum %(name)s
148 # append automatically generated _MAX value
149 enum_values
= values
+ [ 'MAX' ]
152 for value
in enum_values
:
153 enum_full_value
= generate_enum_full_value(name
, value
)
154 enum_decl
+= mcgen('''
155 %(enum_full_value)s = %(i)d,
157 enum_full_value
= enum_full_value
,
161 enum_decl
+= mcgen('''
166 return lookup_decl
+ enum_decl
168 def generate_alternate_qtypes(expr
):
170 name
= expr
['alternate']
171 members
= expr
['data']
174 const int %(name)s_qtypes[QTYPE_MAX] = {
179 qtype
= find_alternate_member_qtype(members
[key
])
180 assert qtype
, "Invalid alternate member"
183 [ %(qtype)s ] = %(abbrev)s_KIND_%(enum)s,
186 abbrev
= de_camel_case(name
).upper(),
187 enum
= c_name(de_camel_case(key
),False).upper())
195 def generate_union(expr
, meta
):
198 typeinfo
= expr
['data']
200 base
= expr
.get('base')
201 discriminator
= expr
.get('discriminator')
203 enum_define
= discriminator_find_enum_define(expr
)
205 discriminator_type_name
= enum_define
['enum_name']
207 discriminator_type_name
= '%sKind' % (name
)
212 %(discriminator_type_name)s kind;
217 discriminator_type_name
=discriminator_type_name
)
221 %(c_type)s %(c_name)s;
223 c_type
=c_type(typeinfo
[key
]),
232 base_fields
= find_struct(base
)['data'].copy()
233 del base_fields
[discriminator
]
234 ret
+= generate_struct_fields(base_fields
)
236 assert not discriminator
241 if meta
== 'alternate':
243 extern const int %(name)s_qtypes[];
250 def generate_type_cleanup_decl(name
):
252 void qapi_free_%(type)s(%(c_type)s obj);
254 c_type
=c_type(name
),type=name
)
257 def generate_type_cleanup(name
):
260 void qapi_free_%(type)s(%(c_type)s obj)
262 QapiDeallocVisitor *md;
269 md = qapi_dealloc_visitor_new();
270 v = qapi_dealloc_get_visitor(md);
271 visit_type_%(type)s(v, &obj, NULL, NULL);
272 qapi_dealloc_visitor_cleanup(md);
275 c_type
=c_type(name
),type=name
)
280 opts
, args
= getopt
.gnu_getopt(sys
.argv
[1:], "chbp:i:o:",
281 ["source", "header", "builtins",
282 "prefix=", "input-file=", "output-dir="])
283 except getopt
.GetoptError
, err
:
290 c_file
= 'qapi-types.c'
291 h_file
= 'qapi-types.h'
298 if o
in ("-p", "--prefix"):
300 elif o
in ("-i", "--input-file"):
302 elif o
in ("-o", "--output-dir"):
304 elif o
in ("-c", "--source"):
306 elif o
in ("-h", "--header"):
308 elif o
in ("-b", "--builtins"):
311 if not do_c
and not do_h
:
315 c_file
= output_dir
+ prefix
+ c_file
316 h_file
= output_dir
+ prefix
+ h_file
319 os
.makedirs(output_dir
)
321 if e
.errno
!= errno
.EEXIST
:
324 def maybe_open(really
, name
, opt
):
326 return open(name
, opt
)
329 return StringIO
.StringIO()
331 fdef
= maybe_open(do_c
, c_file
, 'w')
332 fdecl
= maybe_open(do_h
, h_file
, 'w')
335 /* AUTOMATICALLY GENERATED, DO NOT MODIFY */
338 * deallocation functions for schema-defined QAPI types
340 * Copyright IBM, Corp. 2011
343 * Anthony Liguori <aliguori@us.ibm.com>
344 * Michael Roth <mdroth@linux.vnet.ibm.com>
346 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
347 * See the COPYING.LIB file in the top-level directory.
351 #include "qapi/dealloc-visitor.h"
352 #include "%(prefix)sqapi-types.h"
353 #include "%(prefix)sqapi-visit.h"
357 fdecl
.write(mcgen('''
358 /* AUTOMATICALLY GENERATED, DO NOT MODIFY */
361 * schema-defined QAPI types
363 * Copyright IBM, Corp. 2011
366 * Anthony Liguori <aliguori@us.ibm.com>
368 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
369 * See the COPYING.LIB file in the top-level directory.
380 guard
=guardname(h_file
)))
382 exprs
= parse_schema(input_file
)
383 exprs
= filter(lambda expr
: not expr
.has_key('gen'), exprs
)
385 fdecl
.write(guardstart("QAPI_TYPES_BUILTIN_STRUCT_DECL"))
386 for typename
in builtin_types
.keys():
387 fdecl
.write(generate_fwd_struct(typename
, None, builtin_type
=True))
388 fdecl
.write(guardend("QAPI_TYPES_BUILTIN_STRUCT_DECL"))
392 if expr
.has_key('struct'):
393 ret
+= generate_fwd_struct(expr
['struct'], expr
['data'])
394 elif expr
.has_key('enum'):
395 ret
+= generate_enum(expr
['enum'], expr
['data']) + "\n"
396 ret
+= generate_fwd_enum_struct(expr
['enum'], expr
['data'])
397 fdef
.write(generate_enum_lookup(expr
['enum'], expr
['data']))
398 elif expr
.has_key('union'):
399 ret
+= generate_fwd_struct(expr
['union'], expr
['data']) + "\n"
400 enum_define
= discriminator_find_enum_define(expr
)
402 ret
+= generate_enum('%sKind' % expr
['union'], expr
['data'].keys())
403 fdef
.write(generate_enum_lookup('%sKind' % expr
['union'],
404 expr
['data'].keys()))
405 elif expr
.has_key('alternate'):
406 ret
+= generate_fwd_struct(expr
['alternate'], expr
['data']) + "\n"
407 ret
+= generate_enum('%sKind' % expr
['alternate'], expr
['data'].keys())
408 fdef
.write(generate_enum_lookup('%sKind' % expr
['alternate'],
409 expr
['data'].keys()))
410 fdef
.write(generate_alternate_qtypes(expr
))
415 # to avoid header dependency hell, we always generate declarations
416 # for built-in types in our header files and simply guard them
417 fdecl
.write(guardstart("QAPI_TYPES_BUILTIN_CLEANUP_DECL"))
418 for typename
in builtin_types
.keys():
419 fdecl
.write(generate_type_cleanup_decl(typename
+ "List"))
420 fdecl
.write(guardend("QAPI_TYPES_BUILTIN_CLEANUP_DECL"))
422 # ...this doesn't work for cases where we link in multiple objects that
423 # have the functions defined, so we use -b option to provide control
426 fdef
.write(guardstart("QAPI_TYPES_BUILTIN_CLEANUP_DEF"))
427 for typename
in builtin_types
.keys():
428 fdef
.write(generate_type_cleanup(typename
+ "List"))
429 fdef
.write(guardend("QAPI_TYPES_BUILTIN_CLEANUP_DEF"))
433 if expr
.has_key('struct'):
434 ret
+= generate_struct(expr
) + "\n"
435 ret
+= generate_type_cleanup_decl(expr
['struct'] + "List")
436 fdef
.write(generate_type_cleanup(expr
['struct'] + "List") + "\n")
437 ret
+= generate_type_cleanup_decl(expr
['struct'])
438 fdef
.write(generate_type_cleanup(expr
['struct']) + "\n")
439 elif expr
.has_key('union'):
440 ret
+= generate_union(expr
, 'union')
441 ret
+= generate_type_cleanup_decl(expr
['union'] + "List")
442 fdef
.write(generate_type_cleanup(expr
['union'] + "List") + "\n")
443 ret
+= generate_type_cleanup_decl(expr
['union'])
444 fdef
.write(generate_type_cleanup(expr
['union']) + "\n")
445 elif expr
.has_key('alternate'):
446 ret
+= generate_union(expr
, 'alternate')
447 ret
+= generate_type_cleanup_decl(expr
['alternate'] + "List")
448 fdef
.write(generate_type_cleanup(expr
['alternate'] + "List") + "\n")
449 ret
+= generate_type_cleanup_decl(expr
['alternate'])
450 fdef
.write(generate_type_cleanup(expr
['alternate']) + "\n")
451 elif expr
.has_key('enum'):
452 ret
+= generate_type_cleanup_decl(expr
['enum'] + "List")
453 fdef
.write(generate_type_cleanup(expr
['enum'] + "List") + "\n")