aboutsummaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rw-r--r--scripts/qapi-commands.py57
-rw-r--r--scripts/qapi-visit.py171
2 files changed, 128 insertions, 100 deletions
diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
index 341dba27a8..386f17ef44 100644
--- a/scripts/qapi-commands.py
+++ b/scripts/qapi-commands.py
@@ -2,16 +2,19 @@
# QAPI command marshaller generator
#
# Copyright IBM, Corp. 2011
+# Copyright (C) 2014 Red Hat, Inc.
#
# Authors:
# Anthony Liguori <aliguori@us.ibm.com>
# Michael Roth <mdroth@linux.vnet.ibm.com>
+# Markus Armbruster <armbru@redhat.com>
#
# This work is licensed under the terms of the GNU GPL, version 2.
# See the COPYING file in the top-level directory.
from ordereddict import OrderedDict
from qapi import *
+import re
import sys
import os
import getopt
@@ -37,6 +40,15 @@ def generate_command_decl(name, args, ret_type):
''',
ret_type=c_type(ret_type), name=c_fun(name), args=arglist).strip()
+def gen_err_check(errvar):
+ if errvar:
+ return mcgen('''
+if (local_err) {
+ goto out;
+}
+''')
+ return ''
+
def gen_sync_call(name, args, ret_type, indent=0):
ret = ""
arglist=""
@@ -49,15 +61,14 @@ def gen_sync_call(name, args, ret_type, indent=0):
arglist += "%s, " % (c_var(argname))
push_indent(indent)
ret = mcgen('''
-%(retval)sqmp_%(name)s(%(args)serrp);
+%(retval)sqmp_%(name)s(%(args)s&local_err);
''',
name=c_fun(name), args=arglist, retval=retval).rstrip()
if ret_type:
+ ret += "\n" + gen_err_check('local_err')
ret += "\n" + mcgen(''''
-if (!error_is_set(errp)) {
- %(marshal_output_call)s
-}
+%(marshal_output_call)s
''',
marshal_output_call=gen_marshal_output_call(name, ret_type)).rstrip()
pop_indent(indent)
@@ -67,7 +78,7 @@ if (!error_is_set(errp)) {
def gen_marshal_output_call(name, ret_type):
if not ret_type:
return ""
- return "qmp_marshal_output_%s(retval, ret, errp);" % c_fun(name)
+ return "qmp_marshal_output_%s(retval, ret, &local_err);" % c_fun(name)
def gen_visitor_input_containers_decl(args, obj):
ret = ""
@@ -109,7 +120,8 @@ bool has_%(argname)s = false;
def gen_visitor_input_block(args, dealloc=False):
ret = ""
- errparg = 'errp'
+ errparg = '&local_err'
+ errarg = 'local_err'
if len(args) == 0:
return ret
@@ -118,6 +130,7 @@ def gen_visitor_input_block(args, dealloc=False):
if dealloc:
errparg = 'NULL'
+ errarg = None;
ret += mcgen('''
qmp_input_visitor_cleanup(mi);
md = qapi_dealloc_visitor_new();
@@ -132,15 +145,20 @@ v = qmp_input_get_visitor(mi);
if optional:
ret += mcgen('''
visit_optional(v, &has_%(c_name)s, "%(name)s", %(errp)s);
-if (has_%(c_name)s) {
''',
c_name=c_var(argname), name=argname, errp=errparg)
+ ret += gen_err_check(errarg)
+ ret += mcgen('''
+if (has_%(c_name)s) {
+''',
+ c_name=c_var(argname))
push_indent()
ret += mcgen('''
%(visitor)s(v, &%(c_name)s, "%(name)s", %(errp)s);
''',
c_name=c_var(argname), name=argname, argtype=argtype,
visitor=type_visitor(argtype), errp=errparg)
+ ret += gen_err_check(errarg)
if optional:
pop_indent()
ret += mcgen('''
@@ -161,15 +179,20 @@ def gen_marshal_output(name, args, ret_type, middle_mode):
ret = mcgen('''
static void qmp_marshal_output_%(c_name)s(%(c_ret_type)s ret_in, QObject **ret_out, Error **errp)
{
+ Error *local_err = NULL;
QmpOutputVisitor *mo = qmp_output_visitor_new();
QapiDeallocVisitor *md;
Visitor *v;
v = qmp_output_get_visitor(mo);
- %(visitor)s(v, &ret_in, "unused", errp);
- if (!error_is_set(errp)) {
- *ret_out = qmp_output_get_qobject(mo);
+ %(visitor)s(v, &ret_in, "unused", &local_err);
+ if (local_err) {
+ goto out;
}
+ *ret_out = qmp_output_get_qobject(mo);
+
+out:
+ error_propagate(errp, local_err);
qmp_output_visitor_cleanup(mo);
md = qapi_dealloc_visitor_new();
v = qapi_dealloc_get_visitor(md);
@@ -196,13 +219,12 @@ def gen_marshal_input(name, args, ret_type, middle_mode):
ret = mcgen('''
%(header)s
{
+ Error *local_err = NULL;
''',
header=hdr)
if middle_mode:
ret += mcgen('''
- Error *local_err = NULL;
- Error **errp = &local_err;
QDict *args = (QDict *)qdict;
''')
@@ -229,20 +251,23 @@ def gen_marshal_input(name, args, ret_type, middle_mode):
visitor_input_block=gen_visitor_input_block(args))
else:
ret += mcgen('''
+
(void)args;
''')
ret += mcgen('''
- if (error_is_set(errp)) {
- goto out;
- }
%(sync_call)s
''',
sync_call=gen_sync_call(name, args, ret_type, indent=4))
- ret += mcgen('''
+ if re.search('^ *goto out\\;', ret, re.MULTILINE):
+ ret += mcgen('''
out:
''')
+ if not middle_mode:
+ ret += mcgen('''
+ error_propagate(errp, local_err);
+''')
ret += mcgen('''
%(visitor_input_block_cleanup)s
''',
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index 1ef753a9b9..06a79f1631 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -2,16 +2,19 @@
# QAPI visitor generator
#
# Copyright IBM, Corp. 2011
+# Copyright (C) 2014 Red Hat, Inc.
#
# Authors:
# Anthony Liguori <aliguori@us.ibm.com>
# Michael Roth <mdroth@linux.vnet.ibm.com>
+# Markus Armbruster <armbru@redhat.com>
#
# This work is licensed under the terms of the GNU GPL, version 2.
# See the COPYING file in the top-level directory.
from ordereddict import OrderedDict
from qapi import *
+import re
import sys
import os
import getopt
@@ -32,9 +35,7 @@ static void visit_type_implicit_%(c_type)s(Visitor *m, %(c_type)s **obj, Error *
visit_start_implicit_struct(m, (void **)obj, sizeof(%(c_type)s), &err);
if (!err) {
- visit_type_%(c_type)s_fields(m, obj, &err);
- error_propagate(errp, err);
- err = NULL;
+ visit_type_%(c_type)s_fields(m, obj, errp);
visit_end_implicit_struct(m, &err);
}
error_propagate(errp, err);
@@ -64,12 +65,9 @@ def generate_visit_struct_fields(name, field_prefix, fn_prefix, members, base =
static void visit_type_%(full_name)s_field_%(c_name)s(Visitor *m, %(name)s **obj, Error **errp)
{
- Error *err = NULL;
''',
name=name, full_name=full_name, c_name=c_var(argname))
- push_indent()
ret += generate_visit_struct_body(full_name, argname, argentry)
- pop_indent()
ret += mcgen('''
}
''')
@@ -89,6 +87,9 @@ static void visit_type_%(full_name)s_fields(Visitor *m, %(name)s ** obj, Error *
if base:
ret += mcgen('''
visit_type_implicit_%(type)s(m, &(*obj)->%(c_prefix)s%(c_name)s, &err);
+if (err) {
+ goto out;
+}
''',
c_prefix=c_var(field_prefix),
type=type_name(base), c_name=c_var('base'))
@@ -97,7 +98,7 @@ visit_type_implicit_%(type)s(m, &(*obj)->%(c_prefix)s%(c_name)s, &err);
if optional:
ret += mcgen('''
visit_optional(m, &(*obj)->%(c_prefix)shas_%(c_name)s, "%(name)s", &err);
-if ((*obj)->%(prefix)shas_%(c_name)s) {
+if (!err && (*obj)->%(prefix)shas_%(c_name)s) {
''',
c_prefix=c_var(field_prefix), prefix=field_prefix,
c_name=c_var(argname), name=argname)
@@ -121,10 +122,19 @@ visit_type_%(type)s(m, &(*obj)->%(c_prefix)s%(c_name)s, "%(name)s", &err);
ret += mcgen('''
}
''')
+ ret += mcgen('''
+if (err) {
+ goto out;
+}
+''')
pop_indent()
- ret += mcgen('''
+ if re.search('^ *goto out\\;', ret, re.MULTILINE):
+ ret += mcgen('''
+out:
+''')
+ ret += mcgen('''
error_propagate(errp, err);
}
''')
@@ -133,9 +143,9 @@ visit_type_%(type)s(m, &(*obj)->%(c_prefix)s%(c_name)s, "%(name)s", &err);
def generate_visit_struct_body(field_prefix, name, members):
ret = mcgen('''
-if (!error_is_set(errp)) {
+ Error *err = NULL;
+
''')
- push_indent()
if not field_prefix:
full_name = name
@@ -144,36 +154,26 @@ if (!error_is_set(errp)) {
if len(field_prefix):
ret += mcgen('''
-visit_start_struct(m, NULL, "", "%(name)s", 0, &err);
+ visit_start_struct(m, NULL, "", "%(name)s", 0, &err);
''',
name=name)
else:
ret += mcgen('''
-Error *err = NULL;
-visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(name)s), &err);
+ visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(name)s), &err);
''',
name=name)
ret += mcgen('''
-if (!err) {
- if (*obj) {
- visit_type_%(name)s_fields(m, obj, &err);
- error_propagate(errp, err);
- err = NULL;
+ if (!err) {
+ if (*obj) {
+ visit_type_%(name)s_fields(m, obj, errp);
+ }
+ visit_end_struct(m, &err);
}
+ error_propagate(errp, err);
''',
name=full_name)
- ret += mcgen('''
- /* Always call end_struct if start_struct succeeded. */
- visit_end_struct(m, &err);
-}
-error_propagate(errp, err);
-''')
- pop_indent()
- ret += mcgen('''
-}
-''')
return ret
def generate_visit_struct(expr):
@@ -191,9 +191,7 @@ void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **
''',
name=name)
- push_indent()
ret += generate_visit_struct_body("", name, members)
- pop_indent()
ret += mcgen('''
}
@@ -205,24 +203,26 @@ def generate_visit_list(name, members):
void visit_type_%(name)sList(Visitor *m, %(name)sList ** obj, const char *name, Error **errp)
{
- GenericList *i, **prev = (GenericList **)obj;
Error *err = NULL;
+ GenericList *i, **prev;
- if (!error_is_set(errp)) {
- visit_start_list(m, name, &err);
- if (!err) {
- for (; (i = visit_next_list(m, prev, &err)) != NULL; prev = &i) {
- %(name)sList *native_i = (%(name)sList *)i;
- visit_type_%(name)s(m, &native_i->value, NULL, &err);
- }
- error_propagate(errp, err);
- err = NULL;
-
- /* Always call end_list if start_list succeeded. */
- visit_end_list(m, &err);
- }
- error_propagate(errp, err);
+ visit_start_list(m, name, &err);
+ if (err) {
+ goto out;
+ }
+
+ for (prev = (GenericList **)obj;
+ !err && (i = visit_next_list(m, prev, &err)) != NULL;
+ prev = &i) {
+ %(name)sList *native_i = (%(name)sList *)i;
+ visit_type_%(name)s(m, &native_i->value, NULL, &err);
}
+
+ error_propagate(errp, err);
+ err = NULL;
+ visit_end_list(m, &err);
+out:
+ error_propagate(errp, err);
}
''',
name=name)
@@ -244,10 +244,15 @@ void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **
{
Error *err = NULL;
- if (!error_is_set(errp)) {
- visit_start_implicit_struct(m, (void**) obj, sizeof(%(name)s), &err);
- visit_get_next_type(m, (int*) &(*obj)->kind, %(name)s_qtypes, name, &err);
- switch ((*obj)->kind) {
+ visit_start_implicit_struct(m, (void**) obj, sizeof(%(name)s), &err);
+ if (err) {
+ goto out;
+ }
+ visit_get_next_type(m, (int*) &(*obj)->kind, %(name)s_qtypes, name, &err);
+ if (err) {
+ goto out_end;
+ }
+ switch ((*obj)->kind) {
''',
name=name)
@@ -262,22 +267,24 @@ void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **
enum_full_value = generate_enum_full_value(disc_type, key)
ret += mcgen('''
- case %(enum_full_value)s:
- visit_type_%(c_type)s(m, &(*obj)->%(c_name)s, name, &err);
- break;
+ case %(enum_full_value)s:
+ visit_type_%(c_type)s(m, &(*obj)->%(c_name)s, name, &err);
+ break;
''',
enum_full_value = enum_full_value,
c_type = type_name(members[key]),
c_name = c_fun(key))
ret += mcgen('''
- default:
- abort();
- }
- error_propagate(errp, err);
- err = NULL;
- visit_end_implicit_struct(m, &err);
+ default:
+ abort();
}
+out_end:
+ error_propagate(errp, err);
+ err = NULL;
+ visit_end_implicit_struct(m, &err);
+out:
+ error_propagate(errp, err);
}
''')
@@ -324,19 +331,20 @@ void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **
{
Error *err = NULL;
- if (!error_is_set(errp)) {
- visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(name)s), &err);
- if (!err) {
- if (*obj) {
+ visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(name)s), &err);
+ if (err) {
+ goto out;
+ }
+ if (*obj) {
''',
name=name)
- push_indent()
- push_indent()
-
if base:
ret += mcgen('''
visit_type_%(name)s_fields(m, obj, &err);
+ if (err) {
+ goto out_obj;
+ }
''',
name=name)
@@ -346,8 +354,10 @@ void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **
disc_key = discriminator
ret += mcgen('''
visit_type_%(disc_type)s(m, &(*obj)->kind, "%(disc_key)s", &err);
- if (!err) {
- switch ((*obj)->kind) {
+ if (err) {
+ goto out_obj;
+ }
+ switch ((*obj)->kind) {
''',
disc_type = disc_type,
disc_key = disc_key)
@@ -360,32 +370,25 @@ void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **
enum_full_value = generate_enum_full_value(disc_type, key)
ret += mcgen('''
- case %(enum_full_value)s:
- ''' + fmt + '''
- break;
+ case %(enum_full_value)s:
+ ''' + fmt + '''
+ break;
''',
enum_full_value = enum_full_value,
c_type=type_name(members[key]),
c_name=c_fun(key))
ret += mcgen('''
- default:
- abort();
- }
+ default:
+ abort();
}
+out_obj:
error_propagate(errp, err);
err = NULL;
-''')
- pop_indent()
- pop_indent()
-
- ret += mcgen('''
- }
- /* Always call end_struct if start_struct succeeded. */
- visit_end_struct(m, &err);
- }
- error_propagate(errp, err);
}
+ visit_end_struct(m, &err);
+out:
+ error_propagate(errp, err);
}
''')
@@ -505,7 +508,7 @@ fdecl.write(mcgen('''
/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
/*
- * schema-defined QAPI visitor function
+ * schema-defined QAPI visitor functions
*
* Copyright IBM, Corp. 2011
*