Statistics
| Branch: | Revision:

root / scripts / qapi-visit.py @ 0b944384

History | View | Annotate | Download (7.5 kB)

1
#
2
# QAPI visitor generator
3
#
4
# Copyright IBM, Corp. 2011
5
#
6
# Authors:
7
#  Anthony Liguori <aliguori@us.ibm.com>
8
#  Michael Roth    <mdroth@linux.vnet.ibm.com>
9
#
10
# This work is licensed under the terms of the GNU GPLv2.
11
# See the COPYING.LIB file in the top-level directory.
12

    
13
from ordereddict import OrderedDict
14
from qapi import *
15
import sys
16
import os
17
import getopt
18
import errno
19

    
20
def generate_visit_struct_body(field_prefix, members):
21
    ret = ""
22
    if len(field_prefix):
23
        field_prefix = field_prefix + "."
24
    for argname, argentry, optional, structured in parse_args(members):
25
        if optional:
26
            ret += mcgen('''
27
visit_start_optional(m, (obj && *obj) ? &(*obj)->%(c_prefix)shas_%(c_name)s : NULL, "%(name)s", errp);
28
if ((*obj)->%(prefix)shas_%(c_name)s) {
29
''',
30
                         c_prefix=c_var(field_prefix), prefix=field_prefix,
31
                         c_name=c_var(argname), name=argname)
32
            push_indent()
33

    
34
        if structured:
35
            ret += mcgen('''
36
visit_start_struct(m, NULL, "", "%(name)s", 0, errp);
37
''',
38
                         name=argname)
39
            ret += generate_visit_struct_body(field_prefix + argname, argentry)
40
            ret += mcgen('''
41
visit_end_struct(m, errp);
42
''')
43
        else:
44
            ret += mcgen('''
45
visit_type_%(type)s(m, (obj && *obj) ? &(*obj)->%(c_prefix)s%(c_name)s : NULL, "%(name)s", errp);
46
''',
47
                         c_prefix=c_var(field_prefix), prefix=field_prefix,
48
                         type=type_name(argentry), c_name=c_var(argname),
49
                         name=argname)
50

    
51
        if optional:
52
            pop_indent()
53
            ret += mcgen('''
54
}
55
visit_end_optional(m, errp);
56
''')
57
    return ret
58

    
59
def generate_visit_struct(name, members):
60
    ret = mcgen('''
61

62
void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **errp)
63
{
64
    if (error_is_set(errp)) {
65
        return;
66
    }
67
    visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(name)s), errp);
68
    if (obj && !*obj) {
69
        goto end;
70
    }
71
''',
72
                name=name)
73
    push_indent()
74
    ret += generate_visit_struct_body("", members)
75
    pop_indent()
76

    
77
    ret += mcgen('''
78
end:
79
    visit_end_struct(m, errp);
80
}
81
''')
82
    return ret
83

    
84
def generate_visit_list(name, members):
85
    return mcgen('''
86

87
void visit_type_%(name)sList(Visitor *m, %(name)sList ** obj, const char *name, Error **errp)
88
{
89
    GenericList *i, **prev = (GenericList **)obj;
90

91
    if (error_is_set(errp)) {
92
        return;
93
    }
94
    visit_start_list(m, name, errp);
95

96
    for (; (i = visit_next_list(m, prev, errp)) != NULL; prev = &i) {
97
        %(name)sList *native_i = (%(name)sList *)i;
98
        visit_type_%(name)s(m, &native_i->value, NULL, errp);
99
    }
100

101
    visit_end_list(m, errp);
102
}
103
''',
104
                name=name)
105

    
106
def generate_visit_enum(name, members):
107
    return mcgen('''
108

109
void visit_type_%(name)s(Visitor *m, %(name)s * obj, const char *name, Error **errp)
110
{
111
    visit_type_enum(m, (int *)obj, %(name)s_lookup, "%(name)s", name, errp);
112
}
113
''',
114
                 name=name)
115

    
116
def generate_visit_union(name, members):
117
    ret = generate_visit_enum('%sKind' % name, members.keys())
118

    
119
    ret += mcgen('''
120

121
void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **errp)
122
{
123
    Error *err = NULL;
124

125
    if (error_is_set(errp)) {
126
        return;
127
    }
128
    visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(name)s), &err);
129
    if (obj && !*obj) {
130
        goto end;
131
    }
132
    visit_type_%(name)sKind(m, &(*obj)->kind, "type", &err);
133
    if (err) {
134
        error_propagate(errp, err);
135
        goto end;
136
    }
137
    switch ((*obj)->kind) {
138
''',
139
                 name=name)
140

    
141
    for key in members:
142
        ret += mcgen('''
143
    case %(abbrev)s_KIND_%(enum)s:
144
        visit_type_%(c_type)s(m, &(*obj)->%(c_name)s, "data", errp);
145
        break;
146
''',
147
                abbrev = de_camel_case(name).upper(),
148
                enum = c_fun(de_camel_case(key)).upper(),
149
                c_type=members[key],
150
                c_name=c_fun(key))
151

    
152
    ret += mcgen('''
153
    default:
154
        abort();
155
    }
156
end:
157
    visit_end_struct(m, errp);
158
}
159
''')
160

    
161
    return ret
162

    
163
def generate_declaration(name, members, genlist=True):
164
    ret = mcgen('''
165

166
void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **errp);
167
''',
168
                name=name)
169

    
170
    if genlist:
171
        ret += mcgen('''
172
void visit_type_%(name)sList(Visitor *m, %(name)sList ** obj, const char *name, Error **errp);
173
''',
174
                 name=name)
175

    
176
    return ret
177

    
178
def generate_decl_enum(name, members, genlist=True):
179
    return mcgen('''
180

181
void visit_type_%(name)s(Visitor *m, %(name)s * obj, const char *name, Error **errp);
182
''',
183
                name=name)
184

    
185
try:
186
    opts, args = getopt.gnu_getopt(sys.argv[1:], "chp:o:",
187
                                   ["source", "header", "prefix=", "output-dir="])
188
except getopt.GetoptError, err:
189
    print str(err)
190
    sys.exit(1)
191

    
192
output_dir = ""
193
prefix = ""
194
c_file = 'qapi-visit.c'
195
h_file = 'qapi-visit.h'
196

    
197
do_c = False
198
do_h = False
199

    
200
for o, a in opts:
201
    if o in ("-p", "--prefix"):
202
        prefix = a
203
    elif o in ("-o", "--output-dir"):
204
        output_dir = a + "/"
205
    elif o in ("-c", "--source"):
206
        do_c = True
207
    elif o in ("-h", "--header"):
208
        do_h = True
209

    
210
if not do_c and not do_h:
211
    do_c = True
212
    do_h = True
213

    
214
c_file = output_dir + prefix + c_file
215
h_file = output_dir + prefix + h_file
216

    
217
try:
218
    os.makedirs(output_dir)
219
except os.error, e:
220
    if e.errno != errno.EEXIST:
221
        raise
222

    
223
def maybe_open(really, name, opt):
224
    if really:
225
        return open(name, opt)
226
    else:
227
        import StringIO
228
        return StringIO.StringIO()
229

    
230
fdef = maybe_open(do_c, c_file, 'w')
231
fdecl = maybe_open(do_h, h_file, 'w')
232

    
233
fdef.write(mcgen('''
234
/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
235

236
/*
237
 * schema-defined QAPI visitor functions
238
 *
239
 * Copyright IBM, Corp. 2011
240
 *
241
 * Authors:
242
 *  Anthony Liguori   <aliguori@us.ibm.com>
243
 *
244
 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
245
 * See the COPYING.LIB file in the top-level directory.
246
 *
247
 */
248

249
#include "%(header)s"
250
''',
251
                 header=basename(h_file)))
252

    
253
fdecl.write(mcgen('''
254
/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
255

256
/*
257
 * schema-defined QAPI visitor function
258
 *
259
 * Copyright IBM, Corp. 2011
260
 *
261
 * Authors:
262
 *  Anthony Liguori   <aliguori@us.ibm.com>
263
 *
264
 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
265
 * See the COPYING.LIB file in the top-level directory.
266
 *
267
 */
268

269
#ifndef %(guard)s
270
#define %(guard)s
271

272
#include "qapi/qapi-visit-core.h"
273
#include "%(prefix)sqapi-types.h"
274
''',
275
                  prefix=prefix, guard=guardname(h_file)))
276

    
277
exprs = parse_schema(sys.stdin)
278

    
279
for expr in exprs:
280
    if expr.has_key('type'):
281
        ret = generate_visit_struct(expr['type'], expr['data'])
282
        ret += generate_visit_list(expr['type'], expr['data'])
283
        fdef.write(ret)
284

    
285
        ret = generate_declaration(expr['type'], expr['data'])
286
        fdecl.write(ret)
287
    elif expr.has_key('union'):
288
        ret = generate_visit_union(expr['union'], expr['data'])
289
        ret += generate_visit_list(expr['union'], expr['data'])
290
        fdef.write(ret)
291

    
292
        ret = generate_decl_enum('%sKind' % expr['union'], expr['data'].keys())
293
        ret += generate_declaration(expr['union'], expr['data'])
294
        fdecl.write(ret)
295
    elif expr.has_key('enum'):
296
        ret = generate_visit_enum(expr['enum'], expr['data'])
297
        fdef.write(ret)
298

    
299
        ret = generate_decl_enum(expr['enum'], expr['data'])
300
        fdecl.write(ret)
301

    
302
fdecl.write('''
303
#endif
304
''')
305

    
306
fdecl.flush()
307
fdecl.close()
308

    
309
fdef.flush()
310
fdef.close()