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