~ubuntu-branches/ubuntu/precise/qemu-kvm/precise

« back to all changes in this revision

Viewing changes to scripts/qapi-commands.py

  • Committer: Serge Hallyn
  • Date: 2011-10-19 07:37:43 UTC
  • mfrom: (1.2.7)
  • Revision ID: serge.hallyn@ubuntu.com-20111019073743-7i7n9irsxlm38wic
Tags: 0.15.0+noroms-0ubuntu1
* New upstream release
* Remaining changes from upstream:
  - removed all binary roms and tests/pi_10.com
* Removed Detect-and-use-GCC-atomic-builtins-for-locking.patch - non-NPTL
  implementations were removed with commit
  02615337ef295443daa03233e492194e289a807e
* Drop spice-qxl-locking-fix-for-qemu-kvm.patch - should be unnecessary
  as of commit 196a778428989217b82de042725dc8eb29c8f8d8
* drop patches applied upstream:
  - CVE-2011-1751.diff
  - virtio-guard-against-negative-vq-notifies-CVE-2011-2512.diff
  - CVE-2011-2527.patch
  - fix-pa-configure.patch
* Refreshed the remaining patches:
  - larger_default_ram_size.patch
  - CVE-2011-2212-virtqueue-indirect-overflow.patch
  - qemuifup-fix-paths.patch
  - vpc.patch
* e1000-Dont-set-the-Capabilities-List-bit.patch - switched to the
  cherrypicked upstream patch (as the source file changed quite a bit,
  and the hand-ported patch backported to 0.14.1 does not apply).
* Drop qemu-kvm-spice (all changes from 0.14.1+noroms-0ubuntu7), it will
  need its own source package (LP: #878162)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#
 
2
# QAPI command marshaller 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_decl_enum(name, members, genlist=True):
 
21
    return mcgen('''
 
22
 
 
23
void visit_type_%(name)s(Visitor *m, %(name)s * obj, const char *name, Error **errp);
 
24
''',
 
25
                name=name)
 
26
 
 
27
def generate_command_decl(name, args, ret_type):
 
28
    arglist=""
 
29
    for argname, argtype, optional, structured in parse_args(args):
 
30
        argtype = c_type(argtype)
 
31
        if argtype == "char *":
 
32
            argtype = "const char *"
 
33
        if optional:
 
34
            arglist += "bool has_%s, " % c_var(argname)
 
35
        arglist += "%s %s, " % (argtype, c_var(argname))
 
36
    return mcgen('''
 
37
%(ret_type)s qmp_%(name)s(%(args)sError **errp);
 
38
''',
 
39
                 ret_type=c_type(ret_type), name=c_var(name), args=arglist).strip()
 
40
 
 
41
def gen_sync_call(name, args, ret_type, indent=0):
 
42
    ret = ""
 
43
    arglist=""
 
44
    retval=""
 
45
    if ret_type:
 
46
        retval = "retval = "
 
47
    for argname, argtype, optional, structured in parse_args(args):
 
48
        if optional:
 
49
            arglist += "has_%s, " % c_var(argname)
 
50
        arglist += "%s, " % (c_var(argname))
 
51
    push_indent(indent)
 
52
    ret = mcgen('''
 
53
%(retval)sqmp_%(name)s(%(args)serrp);
 
54
 
 
55
''',
 
56
                name=c_var(name), args=arglist, retval=retval).rstrip()
 
57
    if ret_type:
 
58
        ret += "\n" + mcgen(''''
 
59
%(marshal_output_call)s
 
60
''',
 
61
                            marshal_output_call=gen_marshal_output_call(name, ret_type)).rstrip()
 
62
    pop_indent(indent)
 
63
    return ret.rstrip()
 
64
 
 
65
 
 
66
def gen_marshal_output_call(name, ret_type):
 
67
    if not ret_type:
 
68
        return ""
 
69
    return "qmp_marshal_output_%s(retval, ret, errp);" % c_var(name)
 
70
 
 
71
def gen_visitor_output_containers_decl(ret_type):
 
72
    ret = ""
 
73
    push_indent()
 
74
    if ret_type:
 
75
        ret += mcgen('''
 
76
QmpOutputVisitor *mo;
 
77
QapiDeallocVisitor *md;
 
78
Visitor *v;
 
79
''')
 
80
    pop_indent()
 
81
 
 
82
    return ret
 
83
 
 
84
def gen_visitor_input_containers_decl(args):
 
85
    ret = ""
 
86
 
 
87
    push_indent()
 
88
    if len(args) > 0:
 
89
        ret += mcgen('''
 
90
QmpInputVisitor *mi;
 
91
QapiDeallocVisitor *md;
 
92
Visitor *v;
 
93
''')
 
94
    pop_indent()
 
95
 
 
96
    return ret.rstrip()
 
97
 
 
98
def gen_visitor_input_vars_decl(args):
 
99
    ret = ""
 
100
    push_indent()
 
101
    for argname, argtype, optional, structured in parse_args(args):
 
102
        if optional:
 
103
            ret += mcgen('''
 
104
bool has_%(argname)s = false;
 
105
''',
 
106
                         argname=c_var(argname))
 
107
        if c_type(argtype).endswith("*"):
 
108
            ret += mcgen('''
 
109
%(argtype)s %(argname)s = NULL;
 
110
''',
 
111
                         argname=c_var(argname), argtype=c_type(argtype))
 
112
        else:
 
113
            ret += mcgen('''
 
114
%(argtype)s %(argname)s;
 
115
''',
 
116
                         argname=c_var(argname), argtype=c_type(argtype))
 
117
 
 
118
    pop_indent()
 
119
    return ret.rstrip()
 
120
 
 
121
def gen_visitor_input_block(args, obj, dealloc=False):
 
122
    ret = ""
 
123
    if len(args) == 0:
 
124
        return ret
 
125
 
 
126
    push_indent()
 
127
 
 
128
    if dealloc:
 
129
        ret += mcgen('''
 
130
md = qapi_dealloc_visitor_new();
 
131
v = qapi_dealloc_get_visitor(md);
 
132
''')
 
133
    else:
 
134
        ret += mcgen('''
 
135
mi = qmp_input_visitor_new(%(obj)s);
 
136
v = qmp_input_get_visitor(mi);
 
137
''',
 
138
                     obj=obj)
 
139
 
 
140
    for argname, argtype, optional, structured in parse_args(args):
 
141
        if optional:
 
142
            ret += mcgen('''
 
143
visit_start_optional(v, &has_%(c_name)s, "%(name)s", errp);
 
144
if (has_%(c_name)s) {
 
145
''',
 
146
                         c_name=c_var(argname), name=argname)
 
147
            push_indent()
 
148
        ret += mcgen('''
 
149
visit_type_%(argtype)s(v, &%(c_name)s, "%(name)s", errp);
 
150
''',
 
151
                      c_name=c_var(argname), name=argname, argtype=argtype)
 
152
        if optional:
 
153
            pop_indent()
 
154
            ret += mcgen('''
 
155
}
 
156
visit_end_optional(v, errp);
 
157
''')
 
158
 
 
159
    if dealloc:
 
160
        ret += mcgen('''
 
161
qapi_dealloc_visitor_cleanup(md);
 
162
''')
 
163
    else:
 
164
        ret += mcgen('''
 
165
qmp_input_visitor_cleanup(mi);
 
166
''')
 
167
    pop_indent()
 
168
    return ret.rstrip()
 
169
 
 
170
def gen_marshal_output(name, args, ret_type):
 
171
    if not ret_type:
 
172
        return ""
 
173
    ret = mcgen('''
 
174
static void qmp_marshal_output_%(c_name)s(%(c_ret_type)s ret_in, QObject **ret_out, Error **errp)
 
175
{
 
176
    QapiDeallocVisitor *md = qapi_dealloc_visitor_new();
 
177
    QmpOutputVisitor *mo = qmp_output_visitor_new();
 
178
    Visitor *v;
 
179
 
 
180
    v = qmp_output_get_visitor(mo);
 
181
    visit_type_%(ret_type)s(v, &ret_in, "unused", errp);
 
182
    if (!error_is_set(errp)) {
 
183
        *ret_out = qmp_output_get_qobject(mo);
 
184
    }
 
185
    qmp_output_visitor_cleanup(mo);
 
186
    v = qapi_dealloc_get_visitor(md);
 
187
    visit_type_%(ret_type)s(v, &ret_in, "unused", errp);
 
188
    qapi_dealloc_visitor_cleanup(md);
 
189
}
 
190
''',
 
191
            c_ret_type=c_type(ret_type), c_name=c_var(name), ret_type=ret_type)
 
192
 
 
193
    return ret
 
194
 
 
195
def gen_marshal_input(name, args, ret_type):
 
196
    ret = mcgen('''
 
197
static void qmp_marshal_input_%(c_name)s(QDict *args, QObject **ret, Error **errp)
 
198
{
 
199
''',
 
200
                c_name=c_var(name))
 
201
 
 
202
    if ret_type:
 
203
        if c_type(ret_type).endswith("*"):
 
204
            retval = "    %s retval = NULL;" % c_type(ret_type)
 
205
        else:
 
206
            retval = "    %s retval;" % c_type(ret_type)
 
207
        ret += mcgen('''
 
208
%(retval)s
 
209
''',
 
210
                     retval=retval)
 
211
 
 
212
    if len(args) > 0:
 
213
        ret += mcgen('''
 
214
%(visitor_input_containers_decl)s
 
215
%(visitor_input_vars_decl)s
 
216
 
 
217
%(visitor_input_block)s
 
218
 
 
219
''',
 
220
                     visitor_input_containers_decl=gen_visitor_input_containers_decl(args),
 
221
                     visitor_input_vars_decl=gen_visitor_input_vars_decl(args),
 
222
                     visitor_input_block=gen_visitor_input_block(args, "QOBJECT(args)"))
 
223
 
 
224
    ret += mcgen('''
 
225
    if (error_is_set(errp)) {
 
226
        goto out;
 
227
    }
 
228
%(sync_call)s
 
229
''',
 
230
                 sync_call=gen_sync_call(name, args, ret_type, indent=4))
 
231
    ret += mcgen('''
 
232
 
 
233
out:
 
234
''')
 
235
    ret += mcgen('''
 
236
%(visitor_input_block_cleanup)s
 
237
    return;
 
238
}
 
239
''',
 
240
                 visitor_input_block_cleanup=gen_visitor_input_block(args, None, dealloc=True))
 
241
    return ret
 
242
 
 
243
def gen_registry(commands):
 
244
    registry=""
 
245
    push_indent()
 
246
    for cmd in commands:
 
247
        registry += mcgen('''
 
248
qmp_register_command("%(name)s", qmp_marshal_input_%(c_name)s);
 
249
''',
 
250
                     name=cmd['command'], c_name=c_var(cmd['command']))
 
251
    pop_indent()
 
252
    ret = mcgen('''
 
253
static void qmp_init_marshal(void)
 
254
{
 
255
%(registry)s
 
256
}
 
257
 
 
258
qapi_init(qmp_init_marshal);
 
259
''',
 
260
                registry=registry.rstrip())
 
261
    return ret
 
262
 
 
263
def gen_command_decl_prologue(header, guard, prefix=""):
 
264
    ret = mcgen('''
 
265
/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
 
266
 
 
267
/*
 
268
 * schema-defined QAPI function prototypes
 
269
 *
 
270
 * Copyright IBM, Corp. 2011
 
271
 *
 
272
 * Authors:
 
273
 *  Anthony Liguori   <aliguori@us.ibm.com>
 
274
 *
 
275
 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
 
276
 * See the COPYING.LIB file in the top-level directory.
 
277
 *
 
278
 */
 
279
 
 
280
#ifndef %(guard)s
 
281
#define %(guard)s
 
282
 
 
283
#include "%(prefix)sqapi-types.h"
 
284
#include "error.h"
 
285
 
 
286
''',
 
287
                 header=basename(h_file), guard=guardname(h_file), prefix=prefix)
 
288
    return ret
 
289
 
 
290
def gen_command_def_prologue(prefix="", proxy=False):
 
291
    ret = mcgen('''
 
292
/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
 
293
 
 
294
/*
 
295
 * schema-defined QMP->QAPI command dispatch
 
296
 *
 
297
 * Copyright IBM, Corp. 2011
 
298
 *
 
299
 * Authors:
 
300
 *  Anthony Liguori   <aliguori@us.ibm.com>
 
301
 *
 
302
 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
 
303
 * See the COPYING.LIB file in the top-level directory.
 
304
 *
 
305
 */
 
306
 
 
307
#include "qemu-objects.h"
 
308
#include "qapi/qmp-core.h"
 
309
#include "qapi/qapi-visit-core.h"
 
310
#include "qapi/qmp-output-visitor.h"
 
311
#include "qapi/qmp-input-visitor.h"
 
312
#include "qapi/qapi-dealloc-visitor.h"
 
313
#include "%(prefix)sqapi-types.h"
 
314
#include "%(prefix)sqapi-visit.h"
 
315
 
 
316
''',
 
317
                prefix=prefix)
 
318
    if not proxy:
 
319
        ret += '#include "%sqmp-commands.h"' % prefix
 
320
    return ret + "\n"
 
321
 
 
322
 
 
323
try:
 
324
    opts, args = getopt.gnu_getopt(sys.argv[1:], "p:o:", ["prefix=", "output-dir=", "type="])
 
325
except getopt.GetoptError, err:
 
326
    print str(err)
 
327
    sys.exit(1)
 
328
 
 
329
output_dir = ""
 
330
prefix = ""
 
331
dispatch_type = "sync"
 
332
c_file = 'qmp-marshal.c'
 
333
h_file = 'qmp-commands.h'
 
334
 
 
335
for o, a in opts:
 
336
    if o in ("-p", "--prefix"):
 
337
        prefix = a
 
338
    elif o in ("-o", "--output-dir"):
 
339
        output_dir = a + "/"
 
340
    elif o in ("-t", "--type"):
 
341
        dispatch_type = a
 
342
 
 
343
c_file = output_dir + prefix + c_file
 
344
h_file = output_dir + prefix + h_file
 
345
 
 
346
try:
 
347
    os.makedirs(output_dir)
 
348
except os.error, e:
 
349
    if e.errno != errno.EEXIST:
 
350
        raise
 
351
 
 
352
exprs = parse_schema(sys.stdin)
 
353
commands = filter(lambda expr: expr.has_key('command'), exprs)
 
354
 
 
355
if dispatch_type == "sync":
 
356
    fdecl = open(h_file, 'w')
 
357
    fdef = open(c_file, 'w')
 
358
    ret = gen_command_decl_prologue(header=basename(h_file), guard=guardname(h_file), prefix=prefix)
 
359
    fdecl.write(ret)
 
360
    ret = gen_command_def_prologue(prefix=prefix)
 
361
    fdef.write(ret)
 
362
 
 
363
    for cmd in commands:
 
364
        arglist = []
 
365
        ret_type = None
 
366
        if cmd.has_key('data'):
 
367
            arglist = cmd['data']
 
368
        if cmd.has_key('returns'):
 
369
            ret_type = cmd['returns']
 
370
        ret = generate_command_decl(cmd['command'], arglist, ret_type) + "\n"
 
371
        fdecl.write(ret)
 
372
        if ret_type:
 
373
            ret = gen_marshal_output(cmd['command'], arglist, ret_type) + "\n"
 
374
            fdef.write(ret)
 
375
        ret = gen_marshal_input(cmd['command'], arglist, ret_type) + "\n"
 
376
        fdef.write(ret)
 
377
 
 
378
    fdecl.write("\n#endif");
 
379
    ret = gen_registry(commands)
 
380
    fdef.write(ret)
 
381
 
 
382
    fdef.flush()
 
383
    fdef.close()
 
384
    fdecl.flush()
 
385
    fdecl.close()