]> Git Repo - qemu.git/blob - scripts/qapi-types.py
qapi: Automatically generate a _MAX value for enums
[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):
20     return mcgen('''
21 typedef struct %(name)s %(name)s;
22
23 typedef struct %(name)sList
24 {
25     %(name)s *value;
26     struct %(name)sList *next;
27 } %(name)sList;
28 ''',
29                  name=name)
30
31 def generate_struct(structname, fieldname, members):
32     ret = mcgen('''
33 struct %(name)s
34 {
35 ''',
36           name=structname)
37
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))
53
54     if len(fieldname):
55         fieldname = " " + fieldname
56     ret += mcgen('''
57 }%(field)s;
58 ''',
59             field=fieldname)
60
61     return ret
62
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=value.lower())
74
75     ret += mcgen('''
76     NULL,
77 };
78
79 ''')
80     return ret
81
82 def generate_enum(name, values):
83     lookup_decl = mcgen('''
84 extern const char *%(name)s_lookup[];
85 ''',
86                 name=name)
87
88     enum_decl = mcgen('''
89 typedef enum %(name)s
90 {
91 ''',
92                 name=name)
93
94     # append automatically generated _MAX value
95     enum_values = values + [ 'MAX' ]
96
97     i = 0
98     for value in enum_values:
99         enum_decl += mcgen('''
100     %(abbrev)s_%(value)s = %(i)d,
101 ''',
102                      abbrev=de_camel_case(name).upper(),
103                      value=c_var(value).upper(),
104                      i=i)
105         i += 1
106
107     enum_decl += mcgen('''
108 } %(name)s;
109 ''',
110                  name=name)
111
112     return lookup_decl + enum_decl
113
114 def generate_union(name, typeinfo):
115     ret = mcgen('''
116 struct %(name)s
117 {
118     %(name)sKind kind;
119     union {
120 ''',
121                 name=name)
122
123     for key in typeinfo:
124         ret += mcgen('''
125         %(c_type)s %(c_name)s;
126 ''',
127                      c_type=c_type(typeinfo[key]),
128                      c_name=c_var(key))
129
130     ret += mcgen('''
131     };
132 };
133 ''')
134
135     return ret
136
137 def generate_type_cleanup_decl(name):
138     ret = mcgen('''
139 void qapi_free_%(type)s(%(c_type)s obj);
140 ''',
141                 c_type=c_type(name),type=name)
142     return ret
143
144 def generate_type_cleanup(name):
145     ret = mcgen('''
146 void qapi_free_%(type)s(%(c_type)s obj)
147 {
148     QapiDeallocVisitor *md;
149     Visitor *v;
150
151     if (!obj) {
152         return;
153     }
154
155     md = qapi_dealloc_visitor_new();
156     v = qapi_dealloc_get_visitor(md);
157     visit_type_%(type)s(v, &obj, NULL, NULL);
158     qapi_dealloc_visitor_cleanup(md);
159 }
160 ''',
161                 c_type=c_type(name),type=name)
162     return ret
163
164
165 try:
166     opts, args = getopt.gnu_getopt(sys.argv[1:], "p:o:", ["prefix=", "output-dir="])
167 except getopt.GetoptError, err:
168     print str(err)
169     sys.exit(1)
170
171 output_dir = ""
172 prefix = ""
173 c_file = 'qapi-types.c'
174 h_file = 'qapi-types.h'
175
176 for o, a in opts:
177     if o in ("-p", "--prefix"):
178         prefix = a
179     elif o in ("-o", "--output-dir"):
180         output_dir = a + "/"
181
182 c_file = output_dir + prefix + c_file
183 h_file = output_dir + prefix + h_file
184
185 try:
186     os.makedirs(output_dir)
187 except os.error, e:
188     if e.errno != errno.EEXIST:
189         raise
190
191 fdef = open(c_file, 'w')
192 fdecl = open(h_file, 'w')
193
194 fdef.write(mcgen('''
195 /* AUTOMATICALLY GENERATED, DO NOT MODIFY */
196
197 /*
198  * deallocation functions for schema-defined QAPI types
199  *
200  * Copyright IBM, Corp. 2011
201  *
202  * Authors:
203  *  Anthony Liguori   <[email protected]>
204  *  Michael Roth      <[email protected]>
205  *
206  * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
207  * See the COPYING.LIB file in the top-level directory.
208  *
209  */
210
211 #include "qapi/qapi-dealloc-visitor.h"
212 #include "%(prefix)sqapi-types.h"
213 #include "%(prefix)sqapi-visit.h"
214
215 ''',             prefix=prefix))
216
217 fdecl.write(mcgen('''
218 /* AUTOMATICALLY GENERATED, DO NOT MODIFY */
219
220 /*
221  * schema-defined QAPI types
222  *
223  * Copyright IBM, Corp. 2011
224  *
225  * Authors:
226  *  Anthony Liguori   <[email protected]>
227  *
228  * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
229  * See the COPYING.LIB file in the top-level directory.
230  *
231  */
232
233 #ifndef %(guard)s
234 #define %(guard)s
235
236 #include "qapi/qapi-types-core.h"
237 ''',
238                   guard=guardname(h_file)))
239
240 exprs = parse_schema(sys.stdin)
241
242 for expr in exprs:
243     ret = "\n"
244     if expr.has_key('type'):
245         ret += generate_fwd_struct(expr['type'], expr['data'])
246     elif expr.has_key('enum'):
247         ret += generate_enum(expr['enum'], expr['data'])
248         fdef.write(generate_enum_lookup(expr['enum'], expr['data']))
249     elif expr.has_key('union'):
250         ret += generate_fwd_struct(expr['union'], expr['data']) + "\n"
251         ret += generate_enum('%sKind' % expr['union'], expr['data'].keys())
252     else:
253         continue
254     fdecl.write(ret)
255
256 for expr in exprs:
257     ret = "\n"
258     if expr.has_key('type'):
259         ret += generate_struct(expr['type'], "", expr['data']) + "\n"
260         ret += generate_type_cleanup_decl(expr['type'] + "List")
261         fdef.write(generate_type_cleanup(expr['type'] + "List") + "\n")
262         ret += generate_type_cleanup_decl(expr['type'])
263         fdef.write(generate_type_cleanup(expr['type']) + "\n")
264     elif expr.has_key('union'):
265         ret += generate_union(expr['union'], expr['data'])
266     else:
267         continue
268     fdecl.write(ret)
269
270 fdecl.write('''
271 #endif
272 ''')
273
274 fdecl.flush()
275 fdecl.close()
276
277 fdef.flush()
278 fdef.close()
This page took 0.040357 seconds and 4 git commands to generate.