Statistics
| Branch: | Revision:

root / scripts / qapi-types.py @ ee03398c

History | View | Annotate | Download (8.8 kB)

1
#
2
# QAPI types generator
3
#
4
# Copyright IBM, Corp. 2011
5
#
6
# Authors:
7
#  Anthony Liguori <aliguori@us.ibm.com>
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(structname, fieldname, members):
61
    ret = mcgen('''
62
struct %(name)s
63
{
64
''',
65
          name=structname)
66

    
67
    for argname, argentry, optional, structured in parse_args(members):
68
        if optional:
69
            ret += mcgen('''
70
    bool has_%(c_name)s;
71
''',
72
                         c_name=c_var(argname))
73
        if structured:
74
            push_indent()
75
            ret += generate_struct("", argname, argentry)
76
            pop_indent()
77
        else:
78
            ret += mcgen('''
79
    %(c_type)s %(c_name)s;
80
''',
81
                     c_type=c_type(argentry), c_name=c_var(argname))
82

    
83
    if len(fieldname):
84
        fieldname = " " + fieldname
85
    ret += mcgen('''
86
}%(field)s;
87
''',
88
            field=fieldname)
89

    
90
    return ret
91

    
92
def generate_enum_lookup(name, values):
93
    ret = mcgen('''
94
const char *%(name)s_lookup[] = {
95
''',
96
                         name=name)
97
    i = 0
98
    for value in values:
99
        ret += mcgen('''
100
    "%(value)s",
101
''',
102
                     value=value)
103

    
104
    ret += mcgen('''
105
    NULL,
106
};
107

108
''')
109
    return ret
110

    
111
def generate_enum_name(name):
112
    if name.isupper():
113
        return c_fun(name, False)
114
    new_name = ''
115
    for c in c_fun(name, False):
116
        if c.isupper():
117
            new_name += '_'
118
        new_name += c
119
    return new_name.lstrip('_').upper()
120

    
121
def generate_enum(name, values):
122
    lookup_decl = mcgen('''
123
extern const char *%(name)s_lookup[];
124
''',
125
                name=name)
126

    
127
    enum_decl = mcgen('''
128
typedef enum %(name)s
129
{
130
''',
131
                name=name)
132

    
133
    # append automatically generated _MAX value
134
    enum_values = values + [ 'MAX' ]
135

    
136
    i = 0
137
    for value in enum_values:
138
        enum_decl += mcgen('''
139
    %(abbrev)s_%(value)s = %(i)d,
140
''',
141
                     abbrev=de_camel_case(name).upper(),
142
                     value=generate_enum_name(value),
143
                     i=i)
144
        i += 1
145

    
146
    enum_decl += mcgen('''
147
} %(name)s;
148
''',
149
                 name=name)
150

    
151
    return lookup_decl + enum_decl
152

    
153
def generate_union(name, typeinfo):
154
    ret = mcgen('''
155
struct %(name)s
156
{
157
    %(name)sKind kind;
158
    union {
159
        void *data;
160
''',
161
                name=name)
162

    
163
    for key in typeinfo:
164
        ret += mcgen('''
165
        %(c_type)s %(c_name)s;
166
''',
167
                     c_type=c_type(typeinfo[key]),
168
                     c_name=c_fun(key))
169

    
170
    ret += mcgen('''
171
    };
172
};
173
''')
174

    
175
    return ret
176

    
177
def generate_type_cleanup_decl(name):
178
    ret = mcgen('''
179
void qapi_free_%(type)s(%(c_type)s obj);
180
''',
181
                c_type=c_type(name),type=name)
182
    return ret
183

    
184
def generate_type_cleanup(name):
185
    ret = mcgen('''
186

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

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

196
    md = qapi_dealloc_visitor_new();
197
    v = qapi_dealloc_get_visitor(md);
198
    visit_type_%(type)s(v, &obj, NULL, NULL);
199
    qapi_dealloc_visitor_cleanup(md);
200
}
201
''',
202
                c_type=c_type(name),type=name)
203
    return ret
204

    
205

    
206
try:
207
    opts, args = getopt.gnu_getopt(sys.argv[1:], "chbp:o:",
208
                                   ["source", "header", "builtins",
209
                                    "prefix=", "output-dir="])
210
except getopt.GetoptError, err:
211
    print str(err)
212
    sys.exit(1)
213

    
214
output_dir = ""
215
prefix = ""
216
c_file = 'qapi-types.c'
217
h_file = 'qapi-types.h'
218

    
219
do_c = False
220
do_h = False
221
do_builtins = False
222

    
223
for o, a in opts:
224
    if o in ("-p", "--prefix"):
225
        prefix = a
226
    elif o in ("-o", "--output-dir"):
227
        output_dir = a + "/"
228
    elif o in ("-c", "--source"):
229
        do_c = True
230
    elif o in ("-h", "--header"):
231
        do_h = True
232
    elif o in ("-b", "--builtins"):
233
        do_builtins = True
234

    
235
if not do_c and not do_h:
236
    do_c = True
237
    do_h = True
238

    
239
c_file = output_dir + prefix + c_file
240
h_file = output_dir + prefix + h_file
241

    
242
try:
243
    os.makedirs(output_dir)
244
except os.error, e:
245
    if e.errno != errno.EEXIST:
246
        raise
247

    
248
def maybe_open(really, name, opt):
249
    if really:
250
        return open(name, opt)
251
    else:
252
        import StringIO
253
        return StringIO.StringIO()
254

    
255
fdef = maybe_open(do_c, c_file, 'w')
256
fdecl = maybe_open(do_h, h_file, 'w')
257

    
258
fdef.write(mcgen('''
259
/* AUTOMATICALLY GENERATED, DO NOT MODIFY */
260

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

275
#include "qapi/dealloc-visitor.h"
276
#include "%(prefix)sqapi-types.h"
277
#include "%(prefix)sqapi-visit.h"
278

279
''',             prefix=prefix))
280

    
281
fdecl.write(mcgen('''
282
/* AUTOMATICALLY GENERATED, DO NOT MODIFY */
283

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

297
#ifndef %(guard)s
298
#define %(guard)s
299

300
#include <stdbool.h>
301
#include <stdint.h>
302

303
''',
304
                  guard=guardname(h_file)))
305

    
306
exprs = parse_schema(sys.stdin)
307
exprs = filter(lambda expr: not expr.has_key('gen'), exprs)
308

    
309
fdecl.write(guardstart("QAPI_TYPES_BUILTIN_STRUCT_DECL"))
310
for typename in builtin_types:
311
    fdecl.write(generate_fwd_struct(typename, None, builtin_type=True))
312
fdecl.write(guardend("QAPI_TYPES_BUILTIN_STRUCT_DECL"))
313

    
314
for expr in exprs:
315
    ret = "\n"
316
    if expr.has_key('type'):
317
        ret += generate_fwd_struct(expr['type'], expr['data'])
318
    elif expr.has_key('enum'):
319
        ret += generate_enum(expr['enum'], expr['data']) + "\n"
320
        ret += generate_fwd_enum_struct(expr['enum'], expr['data'])
321
        fdef.write(generate_enum_lookup(expr['enum'], expr['data']))
322
    elif expr.has_key('union'):
323
        ret += generate_fwd_struct(expr['union'], expr['data']) + "\n"
324
        ret += generate_enum('%sKind' % expr['union'], expr['data'].keys())
325
        fdef.write(generate_enum_lookup('%sKind' % expr['union'], expr['data'].keys()))
326
    else:
327
        continue
328
    fdecl.write(ret)
329

    
330
# to avoid header dependency hell, we always generate declarations
331
# for built-in types in our header files and simply guard them
332
fdecl.write(guardstart("QAPI_TYPES_BUILTIN_CLEANUP_DECL"))
333
for typename in builtin_types:
334
    fdecl.write(generate_type_cleanup_decl(typename + "List"))
335
fdecl.write(guardend("QAPI_TYPES_BUILTIN_CLEANUP_DECL"))
336

    
337
# ...this doesn't work for cases where we link in multiple objects that
338
# have the functions defined, so we use -b option to provide control
339
# over these cases
340
if do_builtins:
341
    fdef.write(guardstart("QAPI_TYPES_BUILTIN_CLEANUP_DEF"))
342
    for typename in builtin_types:
343
        fdef.write(generate_type_cleanup(typename + "List"))
344
    fdef.write(guardend("QAPI_TYPES_BUILTIN_CLEANUP_DEF"))
345

    
346
for expr in exprs:
347
    ret = "\n"
348
    if expr.has_key('type'):
349
        ret += generate_struct(expr['type'], "", expr['data']) + "\n"
350
        ret += generate_type_cleanup_decl(expr['type'] + "List")
351
        fdef.write(generate_type_cleanup(expr['type'] + "List") + "\n")
352
        ret += generate_type_cleanup_decl(expr['type'])
353
        fdef.write(generate_type_cleanup(expr['type']) + "\n")
354
    elif expr.has_key('union'):
355
        ret += generate_union(expr['union'], expr['data'])
356
        ret += generate_type_cleanup_decl(expr['union'] + "List")
357
        fdef.write(generate_type_cleanup(expr['union'] + "List") + "\n")
358
        ret += generate_type_cleanup_decl(expr['union'])
359
        fdef.write(generate_type_cleanup(expr['union']) + "\n")
360
    elif expr.has_key('enum'):
361
        ret += generate_type_cleanup_decl(expr['enum'] + "List")
362
        fdef.write(generate_type_cleanup(expr['enum'] + "List") + "\n")
363
    else:
364
        continue
365
    fdecl.write(ret)
366

    
367
fdecl.write('''
368
#endif
369
''')
370

    
371
fdecl.flush()
372
fdecl.close()
373

    
374
fdef.flush()
375
fdef.close()