]> xenbits.xensource.com Git - people/liuw/qemu.git/commitdiff
qapi: Convert QType into QAPI built-in enum type
authorEric Blake <eblake@redhat.com>
Wed, 2 Dec 2015 05:20:47 +0000 (22:20 -0700)
committerMarkus Armbruster <armbru@redhat.com>
Thu, 17 Dec 2015 07:21:28 +0000 (08:21 +0100)
What's more meta than using qapi to define qapi? :)

Convert QType into a full-fledged[*] builtin qapi enum type, so
that a subsequent patch can then use it as the discriminator
type of qapi alternate types.  Fortunately, the judicious use of
'prefix' in the qapi definition avoids churn to the spelling of
the enum constants.

To avoid circular definitions, we have to flip the order of
inclusion between "qobject.h" vs. "qapi-types.h".  Back in commit
28770e0, we had the latter include the former, so that we could
use 'QObject *' for our implementation of 'any'.  But that usage
also works with only a forward declaration, whereas the
definition of QObject requires QType to be a complete type.

[*] The type has to be builtin, rather than declared in
qapi/common.json, because we want to use it for alternates even
when common.json is not included. But since it is the first
builtin enum type, we have to add special cases to qapi-types
and qapi-visit to only emit definitions once, even when two
qapi files are being compiled into the same binary (the way we
already handled builtin list types like 'intList').  We may
need to revisit how multiple qapi files share common types,
but that's a project for another day.

Signed-off-by: Eric Blake <eblake@redhat.com>
Message-Id: <1449033659-25497-4-git-send-email-eblake@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
20 files changed:
docs/qapi-code-gen.txt
include/qapi/qmp/qobject.h
include/qemu/typedefs.h
qobject/qobject.c
scripts/qapi-types.py
scripts/qapi-visit.py
scripts/qapi.py
tests/qapi-schema/alternate-empty.out
tests/qapi-schema/comments.out
tests/qapi-schema/empty.out
tests/qapi-schema/event-case.out
tests/qapi-schema/flat-union-empty.out
tests/qapi-schema/ident-with-escape.out
tests/qapi-schema/include-relpath.out
tests/qapi-schema/include-repetition.out
tests/qapi-schema/include-simple.out
tests/qapi-schema/indented-expr.out
tests/qapi-schema/qapi-schema-test.out
tests/qapi-schema/union-clash-data.out
tests/qapi-schema/union-empty.out

index 2becba95b96541c55d1b0a6ab8dec9247bbc7c03..79bf0726951350351de60b6331dedf342e5e3052 100644 (file)
@@ -160,6 +160,7 @@ The following types are predefined, and map to C as follows:
                        accepts size suffixes
   bool      bool       JSON true or false
   any       QObject *  any JSON value
+  QType     QType      JSON string matching enum QType values
 
 
 === Includes ===
index c0f1e99bca16570bf1e724139eb8f23823d2048f..74459ae14b7c4c170ad131f183c986309126a33a 100644 (file)
 
 #include <stddef.h>
 #include <assert.h>
+#include "qapi-types.h"
 
-typedef enum {
-    QTYPE_NONE,    /* sentinel value, no QObject has this type code */
-    QTYPE_QNULL,
-    QTYPE_QINT,
-    QTYPE_QSTRING,
-    QTYPE_QDICT,
-    QTYPE_QLIST,
-    QTYPE_QFLOAT,
-    QTYPE_QBOOL,
-    QTYPE_MAX,
-} QType;
-
-typedef struct QObject {
+struct QObject {
     QType type;
     size_t refcnt;
-} QObject;
+};
 
 /* Get the 'base' part of an object */
 #define QOBJECT(obj) (&(obj)->base)
@@ -66,7 +55,7 @@ typedef struct QObject {
 /* Initialize an object to default values */
 static inline void qobject_init(QObject *obj, QType type)
 {
-    assert(QTYPE_NONE < type && type < QTYPE_MAX);
+    assert(QTYPE_NONE < type && type < QTYPE__MAX);
     obj->refcnt = 1;
     obj->type = type;
 }
@@ -102,7 +91,7 @@ static inline void qobject_decref(QObject *obj)
  */
 static inline QType qobject_type(const QObject *obj)
 {
-    assert(QTYPE_NONE < obj->type && obj->type < QTYPE_MAX);
+    assert(QTYPE_NONE < obj->type && obj->type < QTYPE__MAX);
     return obj->type;
 }
 
index 3eedcf4c8fe9c9d5cf27ff7c8a0cfbb1fe26d335..78fe6e86e3031a34b28f8a7f6df6195f6ed4647c 100644 (file)
@@ -80,6 +80,7 @@ typedef struct QEMUSGList QEMUSGList;
 typedef struct QEMUSizedBuffer QEMUSizedBuffer;
 typedef struct QEMUTimer QEMUTimer;
 typedef struct QEMUTimerListGroup QEMUTimerListGroup;
+typedef struct QObject QObject;
 typedef struct RAMBlock RAMBlock;
 typedef struct Range Range;
 typedef struct SerialState SerialState;
index 1df315ab013dac5fb4513a519881a0e4899ed932..a3ef14eb55a158083e95d87a3f24eb4f50e574b4 100644 (file)
@@ -15,7 +15,7 @@
 #include "qapi/qmp/qlist.h"
 #include "qapi/qmp/qstring.h"
 
-static void (*qdestroy[QTYPE_MAX])(QObject *) = {
+static void (*qdestroy[QTYPE__MAX])(QObject *) = {
     [QTYPE_NONE] = NULL,               /* No such object exists */
     [QTYPE_QNULL] = NULL,              /* qnull_ is indestructible */
     [QTYPE_QINT] = qint_destroy_obj,
@@ -29,6 +29,6 @@ static void (*qdestroy[QTYPE_MAX])(QObject *) = {
 void qobject_destroy(QObject *obj)
 {
     assert(!obj->refcnt);
-    assert(QTYPE_QNULL < obj->type && obj->type < QTYPE_MAX);
+    assert(QTYPE_QNULL < obj->type && obj->type < QTYPE__MAX);
     qdestroy[obj->type](obj);
 }
index 2f2f7dfd80a2a206afba391776cc4bc3a408d1e7..20718462506e3f1f40ddcbb646c8512133b3322c 100644 (file)
@@ -112,7 +112,7 @@ extern const int %(c_name)s_qtypes[];
 def gen_alternate_qtypes(name, variants):
     ret = mcgen('''
 
-const int %(c_name)s_qtypes[QTYPE_MAX] = {
+const int %(c_name)s_qtypes[QTYPE__MAX] = {
 ''',
                 c_name=c_name(name))
 
@@ -233,8 +233,15 @@ class QAPISchemaGenTypeVisitor(QAPISchemaVisitor):
         self.defn += gen_type_cleanup(name)
 
     def visit_enum_type(self, name, info, values, prefix):
-        self._fwdecl += gen_enum(name, values, prefix)
-        self._fwdefn += gen_enum_lookup(name, values, prefix)
+        # Special case for our lone builtin enum type
+        # TODO use something cleaner than existence of info
+        if not info:
+            self._btin += gen_enum(name, values, prefix)
+            if do_builtins:
+                self.defn += gen_enum_lookup(name, values, prefix)
+        else:
+            self._fwdecl += gen_enum(name, values, prefix)
+            self._fwdefn += gen_enum_lookup(name, values, prefix)
 
     def visit_array_type(self, name, info, element_type):
         if isinstance(element_type, QAPISchemaBuiltinType):
@@ -316,10 +323,11 @@ fdef.write(mcgen('''
 ''',
                  prefix=prefix))
 
+# To avoid circular headers, use only typedefs.h here, not qobject.h
 fdecl.write(mcgen('''
 #include <stdbool.h>
 #include <stdint.h>
-#include "qapi/qmp/qobject.h"
+#include "qemu/typedefs.h"
 '''))
 
 schema = QAPISchema(input_file)
index 94cd11335e0ab5c057ce05fc2dd2507b6843a38d..7ceda18bdbf94cc643ddcc9fccd80e7398b57d8c 100644 (file)
@@ -347,8 +347,15 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
                     isinstance(entity, QAPISchemaObjectType))
 
     def visit_enum_type(self, name, info, values, prefix):
-        self.decl += gen_visit_decl(name, scalar=True)
-        self.defn += gen_visit_enum(name)
+        # Special case for our lone builtin enum type
+        # TODO use something cleaner than existence of info
+        if not info:
+            self._btin += gen_visit_decl(name, scalar=True)
+            if do_builtins:
+                self.defn += gen_visit_enum(name)
+        else:
+            self.decl += gen_visit_decl(name, scalar=True)
+            self.defn += gen_visit_enum(name)
 
     def visit_array_type(self, name, info, element_type):
         decl = gen_visit_decl(name)
index b336fbd57cb51f251cfd7f8acab51c3a800300ed..c9e4ad2d9e3961a4bd9523d21bbdd4be1b3b3203 100644 (file)
@@ -34,6 +34,7 @@ builtin_types = {
     'uint64':   'QTYPE_QINT',
     'size':     'QTYPE_QINT',
     'any':      None,           # any QType possible, actually
+    'QType':    'QTYPE_QSTRING',
 }
 
 # Whitelist of commands allowed to return a non-dictionary
@@ -1244,6 +1245,11 @@ class QAPISchema(object):
         self.the_empty_object_type = QAPISchemaObjectType(':empty', None, None,
                                                           [], None)
         self._def_entity(self.the_empty_object_type)
+        self._def_entity(QAPISchemaEnumType('QType', None,
+                                            ['none', 'qnull', 'qint',
+                                             'qstring', 'qdict', 'qlist',
+                                             'qfloat', 'qbool'],
+                                            'QTYPE'))
 
     def _make_implicit_enum_type(self, name, info, values):
         name = name + 'Kind'   # Use namespace reserved by add_name()
index 0f153b6f60cdc5e5fa7cd31cfa95656029d23b73..02b9876e76debdb73b6c8b01e0502598466d33d2 100644 (file)
@@ -2,3 +2,5 @@ object :empty
 alternate Alt
     case i: int
 enum AltKind ['i']
+enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
+    prefix QTYPE
index 9e2c656fa0ca6ef5da5b7ef3cae34f4565b23c6d..97be601897be6859840c599837b26f3367b74c2e 100644 (file)
@@ -1,2 +1,4 @@
 object :empty
+enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
+    prefix QTYPE
 enum Status ['good', 'bad', 'ugly']
index 272b1616f4f4d79e741a19044031be6f88ae7c5c..6522940dc45f05e3e3363cdaacea19cf51bc60bb 100644 (file)
@@ -1 +1,3 @@
 object :empty
+enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
+    prefix QTYPE
index cdfd264f9c1d61bb13bd3e9b352e12f06a90726f..6350d6497baac560deba5c888c81acb92a70ff2b 100644 (file)
@@ -1,2 +1,4 @@
 object :empty
+enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
+    prefix QTYPE
 event oops None
index 0e0665af3b50157793d797de4f505046880a90bd..eade2d5ac6ec8e1c74d20d0ce58be97b65a3402f 100644 (file)
@@ -2,6 +2,8 @@ object :empty
 object Base
     member type: Empty optional=False
 enum Empty []
+enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
+    prefix QTYPE
 object Union
     base Base
     tag type
index f4542b12d8b452e11590d35d763c57f18725a35e..453e0b2adba02a86a53b6ccb3494796762464f35 100644 (file)
@@ -1,5 +1,7 @@
 object :empty
 object :obj-fooA-arg
     member bar1: str optional=False
+enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
+    prefix QTYPE
 command fooA :obj-fooA-arg -> None
    gen=True success_response=True
index 9e2c656fa0ca6ef5da5b7ef3cae34f4565b23c6d..97be601897be6859840c599837b26f3367b74c2e 100644 (file)
@@ -1,2 +1,4 @@
 object :empty
+enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
+    prefix QTYPE
 enum Status ['good', 'bad', 'ugly']
index 9e2c656fa0ca6ef5da5b7ef3cae34f4565b23c6d..97be601897be6859840c599837b26f3367b74c2e 100644 (file)
@@ -1,2 +1,4 @@
 object :empty
+enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
+    prefix QTYPE
 enum Status ['good', 'bad', 'ugly']
index 9e2c656fa0ca6ef5da5b7ef3cae34f4565b23c6d..97be601897be6859840c599837b26f3367b74c2e 100644 (file)
@@ -1,2 +1,4 @@
 object :empty
+enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
+    prefix QTYPE
 enum Status ['good', 'bad', 'ugly']
index 226d3007985b5b8056ef003de753a25cf9d900e1..ce37ff572b647c65250d13ffa958d75f8befe2d0 100644 (file)
@@ -1,4 +1,6 @@
 object :empty
+enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
+    prefix QTYPE
 command eins None -> None
    gen=True success_response=True
 command zwei None -> None
index 0724a9f9327163f56aebf9e46dbf61c4895840c7..b87cfba5999d502f6483a029224fc21c710267cb 100644 (file)
@@ -101,6 +101,8 @@ object NestedEnumsOne
     member enum4: EnumOne optional=True
 enum QEnumTwo ['value1', 'value2']
     prefix QENUM_TWO
+enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
+    prefix QTYPE
 object TestStruct
     member integer: int optional=False
     member boolean: bool optional=False
index cea8551c4c0cec72e7546f7a3c7f0d941124af0b..f5752f4595164dcf398e1c4b06ac8d721765a536 100644 (file)
@@ -1,6 +1,8 @@
 object :empty
 object :obj-int-wrapper
     member data: int optional=False
+enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
+    prefix QTYPE
 object TestUnion
     member type: TestUnionKind optional=False
     case data: :obj-int-wrapper
index 9c89fd10ba1d467e788e64deb9c8b3859075d96a..bdf17e5b29500650723dc8c06f5341ad03640d28 100644 (file)
@@ -1,4 +1,6 @@
 object :empty
+enum QType ['none', 'qnull', 'qint', 'qstring', 'qdict', 'qlist', 'qfloat', 'qbool']
+    prefix QTYPE
 object Union
     member type: UnionKind optional=False
 enum UnionKind []