Statistics
| Branch: | Revision:

root / scripts / qapi-types.py @ ee03398c

History | View | Annotate | Download (8.8 kB)

1 fb3182ce Michael Roth
#
2 fb3182ce Michael Roth
# QAPI types generator
3 fb3182ce Michael Roth
#
4 fb3182ce Michael Roth
# Copyright IBM, Corp. 2011
5 fb3182ce Michael Roth
#
6 fb3182ce Michael Roth
# Authors:
7 fb3182ce Michael Roth
#  Anthony Liguori <aliguori@us.ibm.com>
8 fb3182ce Michael Roth
#
9 fb3182ce Michael Roth
# This work is licensed under the terms of the GNU GPLv2.
10 fb3182ce Michael Roth
# See the COPYING.LIB file in the top-level directory.
11 fb3182ce Michael Roth
12 fb3182ce Michael Roth
from ordereddict import OrderedDict
13 fb3182ce Michael Roth
from qapi import *
14 fb3182ce Michael Roth
import sys
15 fb3182ce Michael Roth
import os
16 fb3182ce Michael Roth
import getopt
17 fb3182ce Michael Roth
import errno
18 fb3182ce Michael Roth
19 c0afa9c5 Michael Roth
def generate_fwd_struct(name, members, builtin_type=False):
20 c0afa9c5 Michael Roth
    if builtin_type:
21 c0afa9c5 Michael Roth
        return mcgen('''
22 c0afa9c5 Michael Roth

23 c0afa9c5 Michael Roth
typedef struct %(name)sList
24 c0afa9c5 Michael Roth
{
25 a678e26c Michael Roth
    union {
26 a678e26c Michael Roth
        %(type)s value;
27 a678e26c Michael Roth
        uint64_t padding;
28 a678e26c Michael Roth
    };
29 c0afa9c5 Michael Roth
    struct %(name)sList *next;
30 c0afa9c5 Michael Roth
} %(name)sList;
31 c0afa9c5 Michael Roth
''',
32 c0afa9c5 Michael Roth
                     type=c_type(name),
33 c0afa9c5 Michael Roth
                     name=name)
34 c0afa9c5 Michael Roth
35 fb3182ce Michael Roth
    return mcgen('''
36 c0afa9c5 Michael Roth

37 fb3182ce Michael Roth
typedef struct %(name)s %(name)s;
38 fb3182ce Michael Roth

39 fb3182ce Michael Roth
typedef struct %(name)sList
40 fb3182ce Michael Roth
{
41 a678e26c Michael Roth
    union {
42 a678e26c Michael Roth
        %(name)s *value;
43 a678e26c Michael Roth
        uint64_t padding;
44 a678e26c Michael Roth
    };
45 fb3182ce Michael Roth
    struct %(name)sList *next;
46 fb3182ce Michael Roth
} %(name)sList;
47 fb3182ce Michael Roth
''',
48 fb3182ce Michael Roth
                 name=name)
49 fb3182ce Michael Roth
50 b9c4b48d Amos Kong
def generate_fwd_enum_struct(name, members):
51 b9c4b48d Amos Kong
    return mcgen('''
52 b9c4b48d Amos Kong
typedef struct %(name)sList
53 b9c4b48d Amos Kong
{
54 b9c4b48d Amos Kong
    %(name)s value;
55 b9c4b48d Amos Kong
    struct %(name)sList *next;
56 b9c4b48d Amos Kong
} %(name)sList;
57 b9c4b48d Amos Kong
''',
58 b9c4b48d Amos Kong
                 name=name)
59 b9c4b48d Amos Kong
60 fb3182ce Michael Roth
def generate_struct(structname, fieldname, members):
61 fb3182ce Michael Roth
    ret = mcgen('''
62 fb3182ce Michael Roth
struct %(name)s
63 fb3182ce Michael Roth
{
64 fb3182ce Michael Roth
''',
65 fb3182ce Michael Roth
          name=structname)
66 fb3182ce Michael Roth
67 fb3182ce Michael Roth
    for argname, argentry, optional, structured in parse_args(members):
68 fb3182ce Michael Roth
        if optional:
69 fb3182ce Michael Roth
            ret += mcgen('''
70 fb3182ce Michael Roth
    bool has_%(c_name)s;
71 fb3182ce Michael Roth
''',
72 fb3182ce Michael Roth
                         c_name=c_var(argname))
73 fb3182ce Michael Roth
        if structured:
74 fb3182ce Michael Roth
            push_indent()
75 fb3182ce Michael Roth
            ret += generate_struct("", argname, argentry)
76 fb3182ce Michael Roth
            pop_indent()
77 fb3182ce Michael Roth
        else:
78 fb3182ce Michael Roth
            ret += mcgen('''
79 fb3182ce Michael Roth
    %(c_type)s %(c_name)s;
80 fb3182ce Michael Roth
''',
81 fb3182ce Michael Roth
                     c_type=c_type(argentry), c_name=c_var(argname))
82 fb3182ce Michael Roth
83 fb3182ce Michael Roth
    if len(fieldname):
84 fb3182ce Michael Roth
        fieldname = " " + fieldname
85 fb3182ce Michael Roth
    ret += mcgen('''
86 fb3182ce Michael Roth
}%(field)s;
87 fb3182ce Michael Roth
''',
88 fb3182ce Michael Roth
            field=fieldname)
89 fb3182ce Michael Roth
90 fb3182ce Michael Roth
    return ret
91 fb3182ce Michael Roth
92 fb3182ce Michael Roth
def generate_enum_lookup(name, values):
93 fb3182ce Michael Roth
    ret = mcgen('''
94 fb3182ce Michael Roth
const char *%(name)s_lookup[] = {
95 fb3182ce Michael Roth
''',
96 fb3182ce Michael Roth
                         name=name)
97 fb3182ce Michael Roth
    i = 0
98 fb3182ce Michael Roth
    for value in values:
99 fb3182ce Michael Roth
        ret += mcgen('''
100 fb3182ce Michael Roth
    "%(value)s",
101 fb3182ce Michael Roth
''',
102 ac4ff701 Luiz Capitulino
                     value=value)
103 fb3182ce Michael Roth
104 fb3182ce Michael Roth
    ret += mcgen('''
105 fb3182ce Michael Roth
    NULL,
106 fb3182ce Michael Roth
};
107 fb3182ce Michael Roth

108 fb3182ce Michael Roth
''')
109 fb3182ce Michael Roth
    return ret
110 fb3182ce Michael Roth
111 f01f594b Luiz Capitulino
def generate_enum_name(name):
112 f01f594b Luiz Capitulino
    if name.isupper():
113 eda50a65 Paolo Bonzini
        return c_fun(name, False)
114 f01f594b Luiz Capitulino
    new_name = ''
115 eda50a65 Paolo Bonzini
    for c in c_fun(name, False):
116 f01f594b Luiz Capitulino
        if c.isupper():
117 f01f594b Luiz Capitulino
            new_name += '_'
118 f01f594b Luiz Capitulino
        new_name += c
119 f01f594b Luiz Capitulino
    return new_name.lstrip('_').upper()
120 f01f594b Luiz Capitulino
121 fb3182ce Michael Roth
def generate_enum(name, values):
122 fb3182ce Michael Roth
    lookup_decl = mcgen('''
123 fb3182ce Michael Roth
extern const char *%(name)s_lookup[];
124 fb3182ce Michael Roth
''',
125 fb3182ce Michael Roth
                name=name)
126 fb3182ce Michael Roth
127 fb3182ce Michael Roth
    enum_decl = mcgen('''
128 fb3182ce Michael Roth
typedef enum %(name)s
129 fb3182ce Michael Roth
{
130 fb3182ce Michael Roth
''',
131 fb3182ce Michael Roth
                name=name)
132 fb3182ce Michael Roth
133 303b54b1 Luiz Capitulino
    # append automatically generated _MAX value
134 303b54b1 Luiz Capitulino
    enum_values = values + [ 'MAX' ]
135 303b54b1 Luiz Capitulino
136 fb3182ce Michael Roth
    i = 0
137 303b54b1 Luiz Capitulino
    for value in enum_values:
138 fb3182ce Michael Roth
        enum_decl += mcgen('''
139 fb3182ce Michael Roth
    %(abbrev)s_%(value)s = %(i)d,
140 fb3182ce Michael Roth
''',
141 fb3182ce Michael Roth
                     abbrev=de_camel_case(name).upper(),
142 f01f594b Luiz Capitulino
                     value=generate_enum_name(value),
143 fb3182ce Michael Roth
                     i=i)
144 fb3182ce Michael Roth
        i += 1
145 fb3182ce Michael Roth
146 fb3182ce Michael Roth
    enum_decl += mcgen('''
147 fb3182ce Michael Roth
} %(name)s;
148 fb3182ce Michael Roth
''',
149 fb3182ce Michael Roth
                 name=name)
150 fb3182ce Michael Roth
151 fb3182ce Michael Roth
    return lookup_decl + enum_decl
152 fb3182ce Michael Roth
153 fb3182ce Michael Roth
def generate_union(name, typeinfo):
154 fb3182ce Michael Roth
    ret = mcgen('''
155 fb3182ce Michael Roth
struct %(name)s
156 fb3182ce Michael Roth
{
157 fb3182ce Michael Roth
    %(name)sKind kind;
158 fb3182ce Michael Roth
    union {
159 dc8fb6df Paolo Bonzini
        void *data;
160 fb3182ce Michael Roth
''',
161 fb3182ce Michael Roth
                name=name)
162 fb3182ce Michael Roth
163 fb3182ce Michael Roth
    for key in typeinfo:
164 fb3182ce Michael Roth
        ret += mcgen('''
165 fb3182ce Michael Roth
        %(c_type)s %(c_name)s;
166 fb3182ce Michael Roth
''',
167 fb3182ce Michael Roth
                     c_type=c_type(typeinfo[key]),
168 c9da228b Federico Simoncelli
                     c_name=c_fun(key))
169 fb3182ce Michael Roth
170 fb3182ce Michael Roth
    ret += mcgen('''
171 fb3182ce Michael Roth
    };
172 fb3182ce Michael Roth
};
173 fb3182ce Michael Roth
''')
174 fb3182ce Michael Roth
175 fb3182ce Michael Roth
    return ret
176 fb3182ce Michael Roth
177 fb3182ce Michael Roth
def generate_type_cleanup_decl(name):
178 fb3182ce Michael Roth
    ret = mcgen('''
179 fb3182ce Michael Roth
void qapi_free_%(type)s(%(c_type)s obj);
180 fb3182ce Michael Roth
''',
181 fb3182ce Michael Roth
                c_type=c_type(name),type=name)
182 fb3182ce Michael Roth
    return ret
183 fb3182ce Michael Roth
184 fb3182ce Michael Roth
def generate_type_cleanup(name):
185 fb3182ce Michael Roth
    ret = mcgen('''
186 c0afa9c5 Michael Roth

187 fb3182ce Michael Roth
void qapi_free_%(type)s(%(c_type)s obj)
188 fb3182ce Michael Roth
{
189 fb3182ce Michael Roth
    QapiDeallocVisitor *md;
190 fb3182ce Michael Roth
    Visitor *v;
191 fb3182ce Michael Roth

192 fb3182ce Michael Roth
    if (!obj) {
193 fb3182ce Michael Roth
        return;
194 fb3182ce Michael Roth
    }
195 fb3182ce Michael Roth

196 fb3182ce Michael Roth
    md = qapi_dealloc_visitor_new();
197 fb3182ce Michael Roth
    v = qapi_dealloc_get_visitor(md);
198 fb3182ce Michael Roth
    visit_type_%(type)s(v, &obj, NULL, NULL);
199 fb3182ce Michael Roth
    qapi_dealloc_visitor_cleanup(md);
200 fb3182ce Michael Roth
}
201 fb3182ce Michael Roth
''',
202 fb3182ce Michael Roth
                c_type=c_type(name),type=name)
203 fb3182ce Michael Roth
    return ret
204 fb3182ce Michael Roth
205 fb3182ce Michael Roth
206 fb3182ce Michael Roth
try:
207 c0afa9c5 Michael Roth
    opts, args = getopt.gnu_getopt(sys.argv[1:], "chbp:o:",
208 c0afa9c5 Michael Roth
                                   ["source", "header", "builtins",
209 c0afa9c5 Michael Roth
                                    "prefix=", "output-dir="])
210 fb3182ce Michael Roth
except getopt.GetoptError, err:
211 fb3182ce Michael Roth
    print str(err)
212 fb3182ce Michael Roth
    sys.exit(1)
213 fb3182ce Michael Roth
214 fb3182ce Michael Roth
output_dir = ""
215 fb3182ce Michael Roth
prefix = ""
216 fb3182ce Michael Roth
c_file = 'qapi-types.c'
217 fb3182ce Michael Roth
h_file = 'qapi-types.h'
218 fb3182ce Michael Roth
219 8d3bc517 Avi Kivity
do_c = False
220 8d3bc517 Avi Kivity
do_h = False
221 c0afa9c5 Michael Roth
do_builtins = False
222 8d3bc517 Avi Kivity
223 fb3182ce Michael Roth
for o, a in opts:
224 fb3182ce Michael Roth
    if o in ("-p", "--prefix"):
225 fb3182ce Michael Roth
        prefix = a
226 fb3182ce Michael Roth
    elif o in ("-o", "--output-dir"):
227 fb3182ce Michael Roth
        output_dir = a + "/"
228 8d3bc517 Avi Kivity
    elif o in ("-c", "--source"):
229 8d3bc517 Avi Kivity
        do_c = True
230 19bf7c87 Avi Kivity
    elif o in ("-h", "--header"):
231 19bf7c87 Avi Kivity
        do_h = True
232 c0afa9c5 Michael Roth
    elif o in ("-b", "--builtins"):
233 c0afa9c5 Michael Roth
        do_builtins = True
234 8d3bc517 Avi Kivity
235 8d3bc517 Avi Kivity
if not do_c and not do_h:
236 8d3bc517 Avi Kivity
    do_c = True
237 8d3bc517 Avi Kivity
    do_h = True
238 fb3182ce Michael Roth
239 fb3182ce Michael Roth
c_file = output_dir + prefix + c_file
240 fb3182ce Michael Roth
h_file = output_dir + prefix + h_file
241 fb3182ce Michael Roth
242 fb3182ce Michael Roth
try:
243 fb3182ce Michael Roth
    os.makedirs(output_dir)
244 fb3182ce Michael Roth
except os.error, e:
245 fb3182ce Michael Roth
    if e.errno != errno.EEXIST:
246 fb3182ce Michael Roth
        raise
247 fb3182ce Michael Roth
248 8d3bc517 Avi Kivity
def maybe_open(really, name, opt):
249 8d3bc517 Avi Kivity
    if really:
250 8d3bc517 Avi Kivity
        return open(name, opt)
251 19bf7c87 Avi Kivity
    else:
252 19bf7c87 Avi Kivity
        import StringIO
253 19bf7c87 Avi Kivity
        return StringIO.StringIO()
254 8d3bc517 Avi Kivity
255 8d3bc517 Avi Kivity
fdef = maybe_open(do_c, c_file, 'w')
256 8d3bc517 Avi Kivity
fdecl = maybe_open(do_h, h_file, 'w')
257 fb3182ce Michael Roth
258 fb3182ce Michael Roth
fdef.write(mcgen('''
259 fb3182ce Michael Roth
/* AUTOMATICALLY GENERATED, DO NOT MODIFY */
260 fb3182ce Michael Roth

261 fb3182ce Michael Roth
/*
262 fb3182ce Michael Roth
 * deallocation functions for schema-defined QAPI types
263 fb3182ce Michael Roth
 *
264 fb3182ce Michael Roth
 * Copyright IBM, Corp. 2011
265 fb3182ce Michael Roth
 *
266 fb3182ce Michael Roth
 * Authors:
267 fb3182ce Michael Roth
 *  Anthony Liguori   <aliguori@us.ibm.com>
268 fb3182ce Michael Roth
 *  Michael Roth      <mdroth@linux.vnet.ibm.com>
269 fb3182ce Michael Roth
 *
270 fb3182ce Michael Roth
 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
271 fb3182ce Michael Roth
 * See the COPYING.LIB file in the top-level directory.
272 fb3182ce Michael Roth
 *
273 fb3182ce Michael Roth
 */
274 fb3182ce Michael Roth

275 7b1b5d19 Paolo Bonzini
#include "qapi/dealloc-visitor.h"
276 fb3182ce Michael Roth
#include "%(prefix)sqapi-types.h"
277 fb3182ce Michael Roth
#include "%(prefix)sqapi-visit.h"
278 fb3182ce Michael Roth

279 fb3182ce Michael Roth
''',             prefix=prefix))
280 fb3182ce Michael Roth
281 fb3182ce Michael Roth
fdecl.write(mcgen('''
282 fb3182ce Michael Roth
/* AUTOMATICALLY GENERATED, DO NOT MODIFY */
283 fb3182ce Michael Roth

284 fb3182ce Michael Roth
/*
285 fb3182ce Michael Roth
 * schema-defined QAPI types
286 fb3182ce Michael Roth
 *
287 fb3182ce Michael Roth
 * Copyright IBM, Corp. 2011
288 fb3182ce Michael Roth
 *
289 fb3182ce Michael Roth
 * Authors:
290 fb3182ce Michael Roth
 *  Anthony Liguori   <aliguori@us.ibm.com>
291 fb3182ce Michael Roth
 *
292 fb3182ce Michael Roth
 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
293 fb3182ce Michael Roth
 * See the COPYING.LIB file in the top-level directory.
294 fb3182ce Michael Roth
 *
295 fb3182ce Michael Roth
 */
296 fb3182ce Michael Roth

297 fb3182ce Michael Roth
#ifndef %(guard)s
298 fb3182ce Michael Roth
#define %(guard)s
299 fb3182ce Michael Roth

300 da4fea06 Igor Mammedov
#include <stdbool.h>
301 da4fea06 Igor Mammedov
#include <stdint.h>
302 b68a8472 Luiz Capitulino

303 fb3182ce Michael Roth
''',
304 fb3182ce Michael Roth
                  guard=guardname(h_file)))
305 fb3182ce Michael Roth
306 fb3182ce Michael Roth
exprs = parse_schema(sys.stdin)
307 5dbee474 Anthony Liguori
exprs = filter(lambda expr: not expr.has_key('gen'), exprs)
308 fb3182ce Michael Roth
309 c0afa9c5 Michael Roth
fdecl.write(guardstart("QAPI_TYPES_BUILTIN_STRUCT_DECL"))
310 c0afa9c5 Michael Roth
for typename in builtin_types:
311 c0afa9c5 Michael Roth
    fdecl.write(generate_fwd_struct(typename, None, builtin_type=True))
312 c0afa9c5 Michael Roth
fdecl.write(guardend("QAPI_TYPES_BUILTIN_STRUCT_DECL"))
313 c0afa9c5 Michael Roth
314 fb3182ce Michael Roth
for expr in exprs:
315 fb3182ce Michael Roth
    ret = "\n"
316 fb3182ce Michael Roth
    if expr.has_key('type'):
317 fb3182ce Michael Roth
        ret += generate_fwd_struct(expr['type'], expr['data'])
318 fb3182ce Michael Roth
    elif expr.has_key('enum'):
319 b9c4b48d Amos Kong
        ret += generate_enum(expr['enum'], expr['data']) + "\n"
320 b9c4b48d Amos Kong
        ret += generate_fwd_enum_struct(expr['enum'], expr['data'])
321 fb3182ce Michael Roth
        fdef.write(generate_enum_lookup(expr['enum'], expr['data']))
322 fb3182ce Michael Roth
    elif expr.has_key('union'):
323 fb3182ce Michael Roth
        ret += generate_fwd_struct(expr['union'], expr['data']) + "\n"
324 fb3182ce Michael Roth
        ret += generate_enum('%sKind' % expr['union'], expr['data'].keys())
325 dc8fb6df Paolo Bonzini
        fdef.write(generate_enum_lookup('%sKind' % expr['union'], expr['data'].keys()))
326 fb3182ce Michael Roth
    else:
327 fb3182ce Michael Roth
        continue
328 fb3182ce Michael Roth
    fdecl.write(ret)
329 fb3182ce Michael Roth
330 c0afa9c5 Michael Roth
# to avoid header dependency hell, we always generate declarations
331 c0afa9c5 Michael Roth
# for built-in types in our header files and simply guard them
332 c0afa9c5 Michael Roth
fdecl.write(guardstart("QAPI_TYPES_BUILTIN_CLEANUP_DECL"))
333 c0afa9c5 Michael Roth
for typename in builtin_types:
334 c0afa9c5 Michael Roth
    fdecl.write(generate_type_cleanup_decl(typename + "List"))
335 c0afa9c5 Michael Roth
fdecl.write(guardend("QAPI_TYPES_BUILTIN_CLEANUP_DECL"))
336 c0afa9c5 Michael Roth
337 c0afa9c5 Michael Roth
# ...this doesn't work for cases where we link in multiple objects that
338 c0afa9c5 Michael Roth
# have the functions defined, so we use -b option to provide control
339 c0afa9c5 Michael Roth
# over these cases
340 c0afa9c5 Michael Roth
if do_builtins:
341 c0afa9c5 Michael Roth
    fdef.write(guardstart("QAPI_TYPES_BUILTIN_CLEANUP_DEF"))
342 c0afa9c5 Michael Roth
    for typename in builtin_types:
343 c0afa9c5 Michael Roth
        fdef.write(generate_type_cleanup(typename + "List"))
344 c0afa9c5 Michael Roth
    fdef.write(guardend("QAPI_TYPES_BUILTIN_CLEANUP_DEF"))
345 c0afa9c5 Michael Roth
346 fb3182ce Michael Roth
for expr in exprs:
347 fb3182ce Michael Roth
    ret = "\n"
348 fb3182ce Michael Roth
    if expr.has_key('type'):
349 fb3182ce Michael Roth
        ret += generate_struct(expr['type'], "", expr['data']) + "\n"
350 75b96aca Michael Roth
        ret += generate_type_cleanup_decl(expr['type'] + "List")
351 75b96aca Michael Roth
        fdef.write(generate_type_cleanup(expr['type'] + "List") + "\n")
352 fb3182ce Michael Roth
        ret += generate_type_cleanup_decl(expr['type'])
353 fb3182ce Michael Roth
        fdef.write(generate_type_cleanup(expr['type']) + "\n")
354 fb3182ce Michael Roth
    elif expr.has_key('union'):
355 fb3182ce Michael Roth
        ret += generate_union(expr['union'], expr['data'])
356 dc8fb6df Paolo Bonzini
        ret += generate_type_cleanup_decl(expr['union'] + "List")
357 dc8fb6df Paolo Bonzini
        fdef.write(generate_type_cleanup(expr['union'] + "List") + "\n")
358 dc8fb6df Paolo Bonzini
        ret += generate_type_cleanup_decl(expr['union'])
359 dc8fb6df Paolo Bonzini
        fdef.write(generate_type_cleanup(expr['union']) + "\n")
360 b9c4b48d Amos Kong
    elif expr.has_key('enum'):
361 b9c4b48d Amos Kong
        ret += generate_type_cleanup_decl(expr['enum'] + "List")
362 b9c4b48d Amos Kong
        fdef.write(generate_type_cleanup(expr['enum'] + "List") + "\n")
363 fb3182ce Michael Roth
    else:
364 fb3182ce Michael Roth
        continue
365 fb3182ce Michael Roth
    fdecl.write(ret)
366 fb3182ce Michael Roth
367 fb3182ce Michael Roth
fdecl.write('''
368 fb3182ce Michael Roth
#endif
369 fb3182ce Michael Roth
''')
370 fb3182ce Michael Roth
371 fb3182ce Michael Roth
fdecl.flush()
372 fb3182ce Michael Roth
fdecl.close()
373 776574d6 Anthony Liguori
374 776574d6 Anthony Liguori
fdef.flush()
375 776574d6 Anthony Liguori
fdef.close()