From 756457a10778dbe76435c3385871e34e15cdbb5e Mon Sep 17 00:00:00 2001
From: Michael Roth <mdroth@linux.vnet.ibm.com>
Date: Mon, 5 Mar 2012 17:44:19 -0500
Subject: [PATCH 52/98] qapi: dealloc visitor, support freeing of nested lists

Previously our logic for keeping track of when we're visiting the head
of a list was done via a global bool. This can be overwritten if dealing
with nested lists, so use stack entries to track this instead.

Reviewed-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
(cherry picked from commit 0b9d854230737b214c01e89f0b679ea36fd59e5e)

Conflicts:

	qapi/qapi-dealloc-visitor.c
Signed-off-by: Jeff Cody <jcody@redhat.com>
Signed-off-by: Michal Novotny <minovotn@redhat.com>
---
 qapi/qapi-dealloc-visitor.c |   28 +++++++++++++++++++++-------
 1 files changed, 21 insertions(+), 7 deletions(-)

diff --git a/qapi/qapi-dealloc-visitor.c b/qapi/qapi-dealloc-visitor.c
index 28b23c1..f280837 100644
--- a/qapi/qapi-dealloc-visitor.c
+++ b/qapi/qapi-dealloc-visitor.c
@@ -19,6 +19,7 @@
 typedef struct StackEntry
 {
     void *value;
+    bool is_list_head;
     QTAILQ_ENTRY(StackEntry) node;
 } StackEntry;
 
@@ -39,6 +40,11 @@ static void qapi_dealloc_push(QapiDeallocVisitor *qov, void *value)
     StackEntry *e = qemu_mallocz(sizeof(*e));
 
     e->value = value;
+
+    /* see if we're just pushing a list head tracker */
+    if (value == NULL) {
+        e->is_list_head = true;
+    }
     QTAILQ_INSERT_HEAD(&qov->stack, e, node);
 }
 
@@ -72,7 +78,7 @@ static void qapi_dealloc_end_struct(Visitor *v, Error **errp)
 static void qapi_dealloc_start_list(Visitor *v, const char *name, Error **errp)
 {
     QapiDeallocVisitor *qov = to_qov(v);
-    qov->is_list_head = true;
+    qapi_dealloc_push(qov, NULL);
 }
 
 static GenericList *qapi_dealloc_next_list(Visitor *v, GenericList **listp,
@@ -80,19 +86,27 @@ static GenericList *qapi_dealloc_next_list(Visitor *v, GenericList **listp,
 {
     GenericList *list = *listp;
     QapiDeallocVisitor *qov = to_qov(v);
+    StackEntry *e = QTAILQ_FIRST(&qov->stack);
 
-    if (!qov->is_list_head) {
-        *listp = list->next;
-        qemu_free(list);
-        return *listp;
+    if (e && e->is_list_head) {
+        e->is_list_head = false;
+        return list;
     }
 
-    qov->is_list_head = false;
-    return list;
+    if (list) {
+        list = list->next;
+        qemu_free(*listp);
+        return list;
+    }
+
+    return NULL;
 }
 
 static void qapi_dealloc_end_list(Visitor *v, Error **errp)
 {
+    QapiDeallocVisitor *qov = to_qov(v);
+    void *obj = qapi_dealloc_pop(qov);
+    assert(obj == NULL); /* should've been list head tracker with no payload */
 }
 
 static void qapi_dealloc_type_str(Visitor *v, char **obj, const char *name,
-- 
1.7.7.6

