qapi: dealloc visitor, support freeing of nested lists
[qemu.git] / scripts / qapi-types.py
blob4797a708132bb953d7df07b3fd0ace2a562db5c2
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_struct(structname, fieldname, members):
32 ret = mcgen('''
33 struct %(name)s
35 ''',
36 name=structname)
38 for argname, argentry, optional, structured in parse_args(members):
39 if optional:
40 ret += mcgen('''
41 bool has_%(c_name)s;
42 ''',
43 c_name=c_var(argname))
44 if structured:
45 push_indent()
46 ret += generate_struct("", argname, argentry)
47 pop_indent()
48 else:
49 ret += mcgen('''
50 %(c_type)s %(c_name)s;
51 ''',
52 c_type=c_type(argentry), c_name=c_var(argname))
54 if len(fieldname):
55 fieldname = " " + fieldname
56 ret += mcgen('''
57 }%(field)s;
58 ''',
59 field=fieldname)
61 return ret
63 def generate_enum_lookup(name, values):
64 ret = mcgen('''
65 const char *%(name)s_lookup[] = {
66 ''',
67 name=name)
68 i = 0
69 for value in values:
70 ret += mcgen('''
71 "%(value)s",
72 ''',
73 value=c_var(value).lower())
75 ret += mcgen('''
76 NULL,
79 ''')
80 return ret
82 def generate_enum(name, values):
83 lookup_decl = mcgen('''
84 extern const char *%(name)s_lookup[];
85 ''',
86 name=name)
88 enum_decl = mcgen('''
89 typedef enum %(name)s
91 ''',
92 name=name)
94 i = 0
95 for value in values:
96 enum_decl += mcgen('''
97 %(abbrev)s_%(value)s = %(i)d,
98 ''',
99 abbrev=de_camel_case(name).upper(),
100 value=c_var(value).upper(),
101 i=i)
102 i += 1
104 enum_decl += mcgen('''
105 } %(name)s;
106 ''',
107 name=name)
109 return lookup_decl + enum_decl
111 def generate_union(name, typeinfo):
112 ret = mcgen('''
113 struct %(name)s
115 %(name)sKind kind;
116 union {
117 ''',
118 name=name)
120 for key in typeinfo:
121 ret += mcgen('''
122 %(c_type)s %(c_name)s;
123 ''',
124 c_type=c_type(typeinfo[key]),
125 c_name=c_var(key))
127 ret += mcgen('''
130 ''')
132 return ret
134 def generate_type_cleanup_decl(name):
135 ret = mcgen('''
136 void qapi_free_%(type)s(%(c_type)s obj);
137 ''',
138 c_type=c_type(name),type=name)
139 return ret
141 def generate_type_cleanup(name):
142 ret = mcgen('''
143 void qapi_free_%(type)s(%(c_type)s obj)
145 QapiDeallocVisitor *md;
146 Visitor *v;
148 if (!obj) {
149 return;
152 md = qapi_dealloc_visitor_new();
153 v = qapi_dealloc_get_visitor(md);
154 visit_type_%(type)s(v, &obj, NULL, NULL);
155 qapi_dealloc_visitor_cleanup(md);
157 ''',
158 c_type=c_type(name),type=name)
159 return ret
162 try:
163 opts, args = getopt.gnu_getopt(sys.argv[1:], "p:o:", ["prefix=", "output-dir="])
164 except getopt.GetoptError, err:
165 print str(err)
166 sys.exit(1)
168 output_dir = ""
169 prefix = ""
170 c_file = 'qapi-types.c'
171 h_file = 'qapi-types.h'
173 for o, a in opts:
174 if o in ("-p", "--prefix"):
175 prefix = a
176 elif o in ("-o", "--output-dir"):
177 output_dir = a + "/"
179 c_file = output_dir + prefix + c_file
180 h_file = output_dir + prefix + h_file
182 try:
183 os.makedirs(output_dir)
184 except os.error, e:
185 if e.errno != errno.EEXIST:
186 raise
188 fdef = open(c_file, 'w')
189 fdecl = open(h_file, 'w')
191 fdef.write(mcgen('''
192 /* AUTOMATICALLY GENERATED, DO NOT MODIFY */
195 * deallocation functions for schema-defined QAPI types
197 * Copyright IBM, Corp. 2011
199 * Authors:
200 * Anthony Liguori <aliguori@us.ibm.com>
201 * Michael Roth <mdroth@linux.vnet.ibm.com>
203 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
204 * See the COPYING.LIB file in the top-level directory.
208 #include "qapi/qapi-dealloc-visitor.h"
209 #include "%(prefix)sqapi-types.h"
210 #include "%(prefix)sqapi-visit.h"
212 ''', prefix=prefix))
214 fdecl.write(mcgen('''
215 /* AUTOMATICALLY GENERATED, DO NOT MODIFY */
218 * schema-defined QAPI types
220 * Copyright IBM, Corp. 2011
222 * Authors:
223 * Anthony Liguori <aliguori@us.ibm.com>
225 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
226 * See the COPYING.LIB file in the top-level directory.
230 #ifndef %(guard)s
231 #define %(guard)s
233 #include "qapi/qapi-types-core.h"
234 ''',
235 guard=guardname(h_file)))
237 exprs = parse_schema(sys.stdin)
239 for expr in exprs:
240 ret = "\n"
241 if expr.has_key('type'):
242 ret += generate_fwd_struct(expr['type'], expr['data'])
243 elif expr.has_key('enum'):
244 ret += generate_enum(expr['enum'], expr['data'])
245 fdef.write(generate_enum_lookup(expr['enum'], expr['data']))
246 elif expr.has_key('union'):
247 ret += generate_fwd_struct(expr['union'], expr['data']) + "\n"
248 ret += generate_enum('%sKind' % expr['union'], expr['data'].keys())
249 else:
250 continue
251 fdecl.write(ret)
253 for expr in exprs:
254 ret = "\n"
255 if expr.has_key('type'):
256 ret += generate_struct(expr['type'], "", expr['data']) + "\n"
257 ret += generate_type_cleanup_decl(expr['type'] + "List")
258 fdef.write(generate_type_cleanup(expr['type'] + "List") + "\n")
259 ret += generate_type_cleanup_decl(expr['type'])
260 fdef.write(generate_type_cleanup(expr['type']) + "\n")
261 elif expr.has_key('union'):
262 ret += generate_union(expr['union'], expr['data'])
263 else:
264 continue
265 fdecl.write(ret)
267 fdecl.write('''
268 #endif
269 ''')
271 fdecl.flush()
272 fdecl.close()
274 fdef.flush()
275 fdef.close()