aboutsummaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2016-05-12 15:06:38 +0100
committerPeter Maydell <peter.maydell@linaro.org>2016-05-12 15:06:38 +0100
commit6ddeeffffecf1f78acf6c93cbf267a8abe755836 (patch)
treea3cba08b27f87adb9c0ed2badaa9945856c39144 /scripts
parentf83b70f701923964aaf89e1203ddcef0dd48ed08 (diff)
parent68ab47e4b4ecc1c4649362b8cc1e49794d1a6537 (diff)
downloadqemu-6ddeeffffecf1f78acf6c93cbf267a8abe755836.zip
qemu-6ddeeffffecf1f78acf6c93cbf267a8abe755836.tar.gz
qemu-6ddeeffffecf1f78acf6c93cbf267a8abe755836.tar.bz2
Merge remote-tracking branch 'remotes/armbru/tags/pull-qapi-2016-05-12' into staging
QAPI patches for 2016-05-12 # gpg: Signature made Thu 12 May 2016 08:49:04 BST using RSA key ID EB918653 # gpg: Good signature from "Markus Armbruster <armbru@redhat.com>" # gpg: aka "Markus Armbruster <armbru@pond.sub.org>" * remotes/armbru/tags/pull-qapi-2016-05-12: (23 commits) qapi: Change visit_type_FOO() to no longer return partial objects qapi: Simplify semantics of visit_next_list() qapi: Fix string input visitor handling of invalid list tests/string-input-visitor: Add negative integer tests qapi: Split visit_end_struct() into pieces qmp: Tighten output visitor rules qmp: Don't reuse qmp visitor after grabbing output spapr_drc: Expose 'null' in qom-get when there is no fdt qmp: Support explicit null during visits qapi: Add visit_type_null() visitor tests: Add check-qnull qapi: Document visitor interfaces, add assertions qmp-input: Refactor when list is advanced qmp-input: Require struct push to visit members of top dict qom: Wrap prop visit in visit_start_struct qapi-commands: Wrap argument visit in visit_start_struct qmp-input: Don't consume input when checking has_member qapi: Use strict QMP input visitor in more places qapi: Consolidate QMP input visitor creation qmp-input: Clean up stack handling ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'scripts')
-rw-r--r--scripts/qapi-commands.py12
-rw-r--r--scripts/qapi-event.py5
-rw-r--r--scripts/qapi-visit.py53
3 files changed, 46 insertions, 24 deletions
diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
index b570069..8c6acb3 100644
--- a/scripts/qapi-commands.py
+++ b/scripts/qapi-commands.py
@@ -115,13 +115,21 @@ def gen_marshal(name, arg_type, ret_type):
if arg_type and arg_type.members:
ret += mcgen('''
- QmpInputVisitor *qiv = qmp_input_visitor_new_strict(QOBJECT(args));
+ QmpInputVisitor *qiv = qmp_input_visitor_new(QOBJECT(args), true);
QapiDeallocVisitor *qdv;
Visitor *v;
%(c_name)s arg = {0};
v = qmp_input_get_visitor(qiv);
+ visit_start_struct(v, NULL, NULL, 0, &err);
+ if (err) {
+ goto out;
+ }
visit_type_%(c_name)s_members(v, &arg, &err);
+ if (!err) {
+ visit_check_struct(v, &err);
+ }
+ visit_end_struct(v);
if (err) {
goto out;
}
@@ -150,7 +158,9 @@ out:
qmp_input_visitor_cleanup(qiv);
qdv = qapi_dealloc_visitor_new();
v = qapi_dealloc_get_visitor(qdv);
+ visit_start_struct(v, NULL, NULL, 0, NULL);
visit_type_%(c_name)s_members(v, &arg, NULL);
+ visit_end_struct(v);
qapi_dealloc_visitor_cleanup(qdv);
''',
c_name=arg_type.c_name())
diff --git a/scripts/qapi-event.py b/scripts/qapi-event.py
index 9b5c5b5..21fb167 100644
--- a/scripts/qapi-event.py
+++ b/scripts/qapi-event.py
@@ -98,7 +98,10 @@ def gen_event_send(name, arg_type):
goto out;
}
visit_type_%(c_name)s_members(v, &param, &err);
- visit_end_struct(v, err ? NULL : &err);
+ if (!err) {
+ visit_check_struct(v, &err);
+ }
+ visit_end_struct(v);
if (err) {
goto out;
}
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index 31d2330..70ea8ca 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -108,30 +108,32 @@ out:
def gen_visit_list(name, element_type):
- # FIXME: if *obj is NULL on entry, and the first visit_next_list()
- # assigns to *obj, while a later one fails, we should clean up *obj
- # rather than leaving it non-NULL. As currently written, the caller must
- # call qapi_free_FOOList() to avoid a memory leak of the partial FOOList.
return mcgen('''
void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s **obj, Error **errp)
{
Error *err = NULL;
- GenericList *i, **prev;
+ %(c_name)s *tail;
+ size_t size = sizeof(**obj);
- visit_start_list(v, name, &err);
+ visit_start_list(v, name, (GenericList **)obj, size, &err);
if (err) {
goto out;
}
- for (prev = (GenericList **)obj;
- !err && (i = visit_next_list(v, prev, sizeof(**obj))) != NULL;
- prev = &i) {
- %(c_name)s *native_i = (%(c_name)s *)i;
- visit_type_%(c_elt_type)s(v, NULL, &native_i->value, &err);
+ for (tail = *obj; tail;
+ tail = (%(c_name)s *)visit_next_list(v, (GenericList *)tail, size)) {
+ visit_type_%(c_elt_type)s(v, NULL, &tail->value, &err);
+ if (err) {
+ break;
+ }
}
visit_end_list(v);
+ if (err && visit_is_input(v)) {
+ qapi_free_%(c_name)s(*obj);
+ *obj = NULL;
+ }
out:
error_propagate(errp, err);
}
@@ -186,9 +188,10 @@ void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s **obj, Error
break;
}
visit_type_%(c_type)s_members(v, &(*obj)->u.%(c_name)s, &err);
- error_propagate(errp, err);
- err = NULL;
- visit_end_struct(v, &err);
+ if (!err) {
+ visit_check_struct(v, &err);
+ }
+ visit_end_struct(v);
''',
c_type=var.type.c_name(),
c_name=c_name(var.name))
@@ -208,20 +211,20 @@ void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s **obj, Error
"%(name)s");
}
visit_end_alternate(v);
+ if (err && visit_is_input(v)) {
+ qapi_free_%(c_name)s(*obj);
+ *obj = NULL;
+ }
out:
error_propagate(errp, err);
}
''',
- name=name)
+ name=name, c_name=c_name(name))
return ret
def gen_visit_object(name, base, members, variants):
- # FIXME: if *obj is NULL on entry, and visit_start_struct() assigns to
- # *obj, but then visit_type_FOO_members() fails, we should clean up *obj
- # rather than leaving it non-NULL. As currently written, the caller must
- # call qapi_free_FOO() to avoid a memory leak of the partial FOO.
return mcgen('''
void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s **obj, Error **errp)
@@ -236,10 +239,16 @@ void visit_type_%(c_name)s(Visitor *v, const char *name, %(c_name)s **obj, Error
goto out_obj;
}
visit_type_%(c_name)s_members(v, *obj, &err);
- error_propagate(errp, err);
- err = NULL;
+ if (err) {
+ goto out_obj;
+ }
+ visit_check_struct(v, &err);
out_obj:
- visit_end_struct(v, &err);
+ visit_end_struct(v);
+ if (err && visit_is_input(v)) {
+ qapi_free_%(c_name)s(*obj);
+ *obj = NULL;
+ }
out:
error_propagate(errp, err);
}