218e99
From e8b11ccb96a0a6ddbb039631511c91652e4d0efc Mon Sep 17 00:00:00 2001
218e99
From: Kevin Wolf <kwolf@redhat.com>
218e99
Date: Tue, 5 Nov 2013 14:08:58 +0100
218e99
Subject: [PATCH 45/87] qapi-types/visit.py: Inheritance for structs
218e99
218e99
RH-Author: Kevin Wolf <kwolf@redhat.com>
218e99
Message-id: <1383660558-32096-5-git-send-email-kwolf@redhat.com>
218e99
Patchwork-id: 55383
218e99
O-Subject: [RHEL-7.0 qemu-kvm PATCH 04/24] qapi-types/visit.py: Inheritance for structs
218e99
Bugzilla: 978402
218e99
RH-Acked-by: Fam Zheng <famz@redhat.com>
218e99
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
218e99
RH-Acked-by: Max Reitz <mreitz@redhat.com>
218e99
218e99
This introduces a new 'base' key for struct definitions that refers to
218e99
another struct type. On the JSON level, the fields of the base type are
218e99
included directly into the same namespace as the fields of the defined
218e99
type, like with unions. On the C level, a pointer to a struct of the
218e99
base type is included.
218e99
218e99
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
218e99
Reviewed-by: Eric Blake <eblake@redhat.com>
218e99
(cherry picked from commit 622f557f5aaea1326c94ca4cddfa4eafeade3723)
218e99
218e99
Signed-off-by: Kevin Wolf <kwolf@redhat.com>
218e99
---
218e99
 docs/qapi-code-gen.txt | 17 +++++++++++++++++
218e99
 scripts/qapi-types.py  |  4 ++++
218e99
 scripts/qapi-visit.py  | 18 ++++++++++++++++--
218e99
 3 files changed, 37 insertions(+), 2 deletions(-)
218e99
218e99
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
218e99
---
218e99
 docs/qapi-code-gen.txt |   17 +++++++++++++++++
218e99
 scripts/qapi-types.py  |    4 ++++
218e99
 scripts/qapi-visit.py  |   18 ++++++++++++++++--
218e99
 3 files changed, 37 insertions(+), 2 deletions(-)
218e99
218e99
diff --git a/docs/qapi-code-gen.txt b/docs/qapi-code-gen.txt
218e99
index 0ce045c..91f44d0 100644
218e99
--- a/docs/qapi-code-gen.txt
218e99
+++ b/docs/qapi-code-gen.txt
218e99
@@ -53,6 +53,23 @@ The use of '*' as a prefix to the name means the member is optional.  Optional
218e99
 members should always be added to the end of the dictionary to preserve
218e99
 backwards compatibility.
218e99
 
218e99
+
218e99
+A complex type definition can specify another complex type as its base.
218e99
+In this case, the fields of the base type are included as top-level fields
218e99
+of the new complex type's dictionary in the QMP wire format. An example
218e99
+definition is:
218e99
+
218e99
+ { 'type': 'BlockdevOptionsGenericFormat', 'data': { 'file': 'str' } }
218e99
+ { 'type': 'BlockdevOptionsGenericCOWFormat',
218e99
+   'base': 'BlockdevOptionsGenericFormat',
218e99
+   'data': { '*backing': 'str' } }
218e99
+
218e99
+An example BlockdevOptionsGenericCOWFormat object on the wire could use
218e99
+both fields like this:
218e99
+
218e99
+ { "file": "/some/place/my-image",
218e99
+   "backing": "/some/place/my-backing-file" }
218e99
+
218e99
 === Enumeration types ===
218e99
 
218e99
 An enumeration type is a dictionary containing a single key whose value is a
218e99
diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py
218e99
index ff60dfb..a0737a6 100644
218e99
--- a/scripts/qapi-types.py
218e99
+++ b/scripts/qapi-types.py
218e99
@@ -80,6 +80,7 @@ def generate_struct(expr):
218e99
     structname = expr.get('type', "")
218e99
     fieldname = expr.get('field', "")
218e99
     members = expr['data']
218e99
+    base = expr.get('base')
218e99
 
218e99
     ret = mcgen('''
218e99
 struct %(name)s
218e99
@@ -87,6 +88,9 @@ struct %(name)s
218e99
 ''',
218e99
           name=structname)
218e99
 
218e99
+    if base:
218e99
+        ret += generate_struct_fields({'base': base})
218e99
+
218e99
     ret += generate_struct_fields(members)
218e99
 
218e99
     if len(fieldname):
218e99
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
218e99
index 43d902c..71004ae 100644
218e99
--- a/scripts/qapi-visit.py
218e99
+++ b/scripts/qapi-visit.py
218e99
@@ -17,7 +17,7 @@ import os
218e99
 import getopt
218e99
 import errno
218e99
 
218e99
-def generate_visit_struct_fields(name, field_prefix, fn_prefix, members):
218e99
+def generate_visit_struct_fields(name, field_prefix, fn_prefix, members, base = None):
218e99
     substructs = []
218e99
     ret = ''
218e99
     full_name = name if not fn_prefix else "%s_%s" % (name, fn_prefix)
218e99
@@ -42,6 +42,19 @@ static void visit_type_%(full_name)s_fields(Visitor *m, %(name)s ** obj, Error *
218e99
         name=name, full_name=full_name)
218e99
     push_indent()
218e99
 
218e99
+    if base:
218e99
+        ret += mcgen('''
218e99
+visit_start_implicit_struct(m, obj ? (void**) &(*obj)->%(c_name)s : NULL, sizeof(%(type)s), &err;;
218e99
+if (!err) {
218e99
+    visit_type_%(type)s_fields(m, obj ? &(*obj)->%(c_prefix)s%(c_name)s : NULL, &err;;
218e99
+    error_propagate(errp, err);
218e99
+    err = NULL;
218e99
+    visit_end_implicit_struct(m, &err;;
218e99
+}
218e99
+''',
218e99
+                     c_prefix=c_var(field_prefix),
218e99
+                     type=type_name(base), c_name=c_var('base'))
218e99
+
218e99
     for argname, argentry, optional, structured in parse_args(members):
218e99
         if optional:
218e99
             ret += mcgen('''
218e99
@@ -124,8 +137,9 @@ def generate_visit_struct(expr):
218e99
 
218e99
     name = expr['type']
218e99
     members = expr['data']
218e99
+    base = expr.get('base')
218e99
 
218e99
-    ret = generate_visit_struct_fields(name, "", "", members)
218e99
+    ret = generate_visit_struct_fields(name, "", "", members, base)
218e99
 
218e99
     ret += mcgen('''
218e99
 
218e99
-- 
218e99
1.7.1
218e99