qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH v2 03/19] qapi: Update docs to match recent generato


From: Eric Blake
Subject: [Qemu-devel] [PATCH v2 03/19] qapi: Update docs to match recent generator changes
Date: Thu, 25 Feb 2016 16:38:32 -0700

Several commits have been changing the generator, but not updating
the docs to match:
- The implicit tag member is named "type", not "kind".  Screwed up in
commit 39a1815.
- Commit 9f08c8ec made list types lazy, and thereby dropped
UserDefOneList if nothing explicitly uses the list type.
- Commit 51e72bc1 switched the parameter order with 'name' occurring
earlier.
- Commit e65d89bf changed the layout of UserDefOneList.
- We now expose visit_type_FOO_members() for objects.
- etc.

Rework the examples to show slightly more output (we don't want to
show too much; that's what the testsuite is for), and regenerate the
output to match all recent changes.  Also, rearrange output to show
.h files before .c (understanding the interface first often makes
the implementation easier to follow).

Reported-by: Marc-André Lureau <address@hidden>
Signed-off-by: Eric Blake <address@hidden>
Signed-off-by: Markus Armbruster <address@hidden>

---
v2: Fix minor errors and rebase to s/fields/members/ rename
Some content from Markus, hence his S-o-b.
A former version of this patch was posted with subset E v9.
---
 docs/qapi-code-gen.txt | 307 ++++++++++++++++++++++++++-----------------------
 1 file changed, 161 insertions(+), 146 deletions(-)

diff --git a/docs/qapi-code-gen.txt b/docs/qapi-code-gen.txt
index 999f3b9..2519c07 100644
--- a/docs/qapi-code-gen.txt
+++ b/docs/qapi-code-gen.txt
@@ -1,7 +1,7 @@
 = How to use the QAPI code generator =

 Copyright IBM Corp. 2011
-Copyright (C) 2012-2015 Red Hat, Inc.
+Copyright (C) 2012-2016 Red Hat, Inc.

 This work is licensed under the terms of the GNU GPL, version 2 or
 later. See the COPYING file in the top-level directory.
@@ -656,7 +656,7 @@ Union types

     { "name": "BlockdevOptions", "meta-type": "object",
       "members": [
-          { "name": "kind", "type": "BlockdevOptionsKind" } ],
+          { "name": "type", "type": "BlockdevOptionsKind" } ],
       "tag": "type",
       "variants": [
           { "case": "file", "type": ":obj-FileOptions-wrapper" },
@@ -722,33 +722,38 @@ the names of built-in types.  Clients should examine 
member

 == Code generation ==

-Schemas are fed into four scripts to generate all the code/files that,
+Schemas are fed into five scripts to generate all the code/files that,
 paired with the core QAPI libraries, comprise everything required to
 take JSON commands read in by a Client JSON Protocol server, unmarshal
 the arguments into the underlying C types, call into the corresponding
-C function, and map the response back to a Client JSON Protocol
-response to be returned to the user.
+C function, map the response back to a Client JSON Protocol response
+to be returned to the user, and introspect the commands.

-As an example, we'll use the following schema, which describes a single
-complex user-defined type (which will produce a C struct, along with a list
-node structure that can be used to chain together a list of such types in
-case we want to accept/return a list of this type with a command), and a
-command which takes that type as a parameter and returns the same type:
+As an example, we'll use the following schema, which describes a
+single complex user-defined type, along with command which takes a
+list of that type as a parameter, and returns a single element of that
+type.  The user is responsible for writing the implementation of
+qmp_my_command(); everything else is produced by the generator.

     $ cat example-schema.json
     { 'struct': 'UserDefOne',
-      'data': { 'integer': 'int', 'string': 'str' } }
+      'data': { 'integer': 'int', '*string': 'str' } }

     { 'command': 'my-command',
-      'data':    {'arg1': 'UserDefOne'},
+      'data': { 'arg1': ['UserDefOne'] },
       'returns': 'UserDefOne' }

     { 'event': 'MY_EVENT' }

+For a more thorough look at generated code, the testsuite includes
+tests/qapi-schema/qapi-schema-tests.json that covers more examples of
+what the generator will accept, and compiles the resulting C code as
+part of 'make check-unit'.
+
 === scripts/qapi-types.py ===

-Used to generate the C types defined by a schema. The following files are
-created:
+Used to generate the C types defined by a schema, along with
+supporting code. The following files are created:

 $(prefix)qapi-types.h - C types corresponding to types defined in
                         the schema you pass in
@@ -763,38 +768,6 @@ Example:

     $ python scripts/qapi-types.py --output-dir="qapi-generated" \
     --prefix="example-" example-schema.json
-    $ cat qapi-generated/example-qapi-types.c
-[Uninteresting stuff omitted...]
-
-    void qapi_free_UserDefOne(UserDefOne *obj)
-    {
-        QapiDeallocVisitor *qdv;
-        Visitor *v;
-
-        if (!obj) {
-            return;
-        }
-
-        qdv = qapi_dealloc_visitor_new();
-        v = qapi_dealloc_get_visitor(qdv);
-        visit_type_UserDefOne(v, &obj, NULL, NULL);
-        qapi_dealloc_visitor_cleanup(qdv);
-    }
-
-    void qapi_free_UserDefOneList(UserDefOneList *obj)
-    {
-        QapiDeallocVisitor *qdv;
-        Visitor *v;
-
-        if (!obj) {
-            return;
-        }
-
-        qdv = qapi_dealloc_visitor_new();
-        v = qapi_dealloc_get_visitor(qdv);
-        visit_type_UserDefOneList(v, &obj, NULL, NULL);
-        qapi_dealloc_visitor_cleanup(qdv);
-    }
     $ cat qapi-generated/example-qapi-types.h
 [Uninteresting stuff omitted...]

@@ -809,29 +782,59 @@ Example:

     struct UserDefOne {
         int64_t integer;
+        bool has_string;
         char *string;
     };

     void qapi_free_UserDefOne(UserDefOne *obj);

     struct UserDefOneList {
-        union {
-            UserDefOne *value;
-            uint64_t padding;
-        };
         UserDefOneList *next;
+        UserDefOne *value;
     };

     void qapi_free_UserDefOneList(UserDefOneList *obj);

     #endif
+    $ cat qapi-generated/example-qapi-types.c
+[Uninteresting stuff omitted...]
+
+    void qapi_free_UserDefOne(UserDefOne *obj)
+    {
+        QapiDeallocVisitor *qdv;
+        Visitor *v;
+
+        if (!obj) {
+            return;
+        }
+
+        qdv = qapi_dealloc_visitor_new();
+        v = qapi_dealloc_get_visitor(qdv);
+        visit_type_UserDefOne(v, NULL, &obj, NULL);
+        qapi_dealloc_visitor_cleanup(qdv);
+    }
+
+    void qapi_free_UserDefOneList(UserDefOneList *obj)
+    {
+        QapiDeallocVisitor *qdv;
+        Visitor *v;
+
+        if (!obj) {
+            return;
+        }
+
+        qdv = qapi_dealloc_visitor_new();
+        v = qapi_dealloc_get_visitor(qdv);
+        visit_type_UserDefOneList(v, NULL, &obj, NULL);
+        qapi_dealloc_visitor_cleanup(qdv);
+    }

 === scripts/qapi-visit.py ===

-Used to generate the visitor functions used to walk through and convert
-a QObject (as provided by QMP) to a native C data structure and
-vice-versa, as well as the visitor function used to dealloc a complex
-schema-defined C type.
+Used to generate the visitor functions used to walk through and
+convert between a native QAPI C data structure and some other format
+(such as QObject); the generated functions are named visit_type_FOO()
+and visit_type_FOO_members().

 The following files are generated:

@@ -848,41 +851,62 @@ Example:

     $ python scripts/qapi-visit.py --output-dir="qapi-generated"
     --prefix="example-" example-schema.json
+    $ cat qapi-generated/example-qapi-visit.h
+[Uninteresting stuff omitted...]
+
+    #ifndef EXAMPLE_QAPI_VISIT_H
+    #define EXAMPLE_QAPI_VISIT_H
+
+[Visitors for built-in types omitted...]
+
+    void visit_type_UserDefOne_members(Visitor *v, UserDefOne *obj, Error 
**errp);
+    void visit_type_UserDefOne(Visitor *v, const char *name, UserDefOne **obj, 
Error **errp);
+    void visit_type_UserDefOneList(Visitor *v, const char *name, 
UserDefOneList **obj, Error **errp);
+
+    #endif
     $ cat qapi-generated/example-qapi-visit.c
 [Uninteresting stuff omitted...]

-    static void visit_type_UserDefOne_fields(Visitor *v, UserDefOne **obj, 
Error **errp)
+    void visit_type_UserDefOne_members(Visitor *v, UserDefOne *obj, Error 
**errp)
     {
         Error *err = NULL;

-        visit_type_int(v, &(*obj)->integer, "integer", &err);
+        visit_type_int(v, "integer", &obj->integer, &err);
         if (err) {
             goto out;
         }
-        visit_type_str(v, &(*obj)->string, "string", &err);
-        if (err) {
-            goto out;
-        }
-
-    out:
-        error_propagate(errp, err);
-    }
-
-    void visit_type_UserDefOne(Visitor *v, UserDefOne **obj, const char *name, 
Error **errp)
-    {
-        Error *err = NULL;
-
-        visit_start_struct(v, (void **)obj, "UserDefOne", name, 
sizeof(UserDefOne), &err);
-        if (!err) {
-            if (*obj) {
-                visit_type_UserDefOne_fields(v, obj, errp);
+        if (visit_optional(v, "string", &obj->has_string)) {
+            visit_type_str(v, "string", &obj->string, &err);
+            if (err) {
+                goto out;
             }
-            visit_end_struct(v, &err);
         }
+
+    out:
+        error_propagate(errp, err);
+    }
+
+    void visit_type_UserDefOne(Visitor *v, const char *name, UserDefOne **obj, 
Error **errp)
+    {
+        Error *err = NULL;
+
+        visit_start_struct(v, name, (void **)obj, sizeof(UserDefOne), &err);
+        if (err) {
+            goto out;
+        }
+        if (!*obj) {
+            goto out_obj;
+        }
+        visit_type_UserDefOne_members(v, *obj, &err);
+        error_propagate(errp, err);
+        err = NULL;
+    out_obj:
+        visit_end_struct(v, &err);
+    out:
         error_propagate(errp, err);
     }

-    void visit_type_UserDefOneList(Visitor *v, UserDefOneList **obj, const 
char *name, Error **errp)
+    void visit_type_UserDefOneList(Visitor *v, const char *name, 
UserDefOneList **obj, Error **errp)
     {
         Error *err = NULL;
         GenericList *i, **prev;
@@ -893,35 +917,24 @@ Example:
         }

         for (prev = (GenericList **)obj;
-             !err && (i = visit_next_list(v, prev, &err)) != NULL;
+             !err && (i = visit_next_list(v, prev, sizeof(**obj))) != NULL;
              prev = &i) {
             UserDefOneList *native_i = (UserDefOneList *)i;
-            visit_type_UserDefOne(v, &native_i->value, NULL, &err);
+            visit_type_UserDefOne(v, NULL, &native_i->value, &err);
         }

-        error_propagate(errp, err);
-        err = NULL;
-        visit_end_list(v, &err);
+        visit_end_list(v);
     out:
         error_propagate(errp, err);
     }
-    $ cat qapi-generated/example-qapi-visit.h
-[Uninteresting stuff omitted...]
-
-    #ifndef EXAMPLE_QAPI_VISIT_H
-    #define EXAMPLE_QAPI_VISIT_H
-
-[Visitors for built-in types omitted...]
-
-    void visit_type_UserDefOne(Visitor *v, UserDefOne **obj, const char *name, 
Error **errp);
-    void visit_type_UserDefOneList(Visitor *v, UserDefOneList **obj, const 
char *name, Error **errp);
-
-    #endif

 === scripts/qapi-commands.py ===

-Used to generate the marshaling/dispatch functions for the commands defined
-in the schema. The following files are generated:
+Used to generate the marshaling/dispatch functions for the commands
+defined in the schema. The generated code implements
+qmp_marshal_COMMAND() (mentioned in qmp-commands.hx, and registered
+automatically), and declares qmp_COMMAND() that the user must
+implement.  The following files are generated:

 $(prefix)qmp-marshal.c: command marshal/dispatch functions for each
                         QMP command defined in the schema. Functions
@@ -939,6 +952,19 @@ Example:

     $ python scripts/qapi-commands.py --output-dir="qapi-generated"
     --prefix="example-" example-schema.json
+    $ cat qapi-generated/example-qmp-commands.h
+[Uninteresting stuff omitted...]
+
+    #ifndef EXAMPLE_QMP_COMMANDS_H
+    #define EXAMPLE_QMP_COMMANDS_H
+
+    #include "example-qapi-types.h"
+    #include "qapi/qmp/qdict.h"
+    #include "qapi/error.h"
+
+    UserDefOne *qmp_my_command(UserDefOneList *arg1, Error **errp);
+
+    #endif
     $ cat qapi-generated/example-qmp-marshal.c
 [Uninteresting stuff omitted...]

@@ -950,7 +976,7 @@ Example:
         Visitor *v;

         v = qmp_output_get_visitor(qov);
-        visit_type_UserDefOne(v, &ret_in, "unused", &err);
+        visit_type_UserDefOne(v, "unused", &ret_in, &err);
         if (err) {
             goto out;
         }
@@ -961,7 +987,7 @@ Example:
         qmp_output_visitor_cleanup(qov);
         qdv = qapi_dealloc_visitor_new();
         v = qapi_dealloc_get_visitor(qdv);
-        visit_type_UserDefOne(v, &ret_in, "unused", NULL);
+        visit_type_UserDefOne(v, "unused", &ret_in, NULL);
         qapi_dealloc_visitor_cleanup(qdv);
     }

@@ -972,10 +998,10 @@ Example:
         QmpInputVisitor *qiv = qmp_input_visitor_new_strict(QOBJECT(args));
         QapiDeallocVisitor *qdv;
         Visitor *v;
-        UserDefOne *arg1 = NULL;
+        UserDefOneList *arg1 = NULL;

         v = qmp_input_get_visitor(qiv);
-        visit_type_UserDefOne(v, &arg1, "arg1", &err);
+        visit_type_UserDefOneList(v, "arg1", &arg1, &err);
         if (err) {
             goto out;
         }
@@ -992,7 +1018,7 @@ Example:
         qmp_input_visitor_cleanup(qiv);
         qdv = qapi_dealloc_visitor_new();
         v = qapi_dealloc_get_visitor(qdv);
-        visit_type_UserDefOne(v, &arg1, "arg1", NULL);
+        visit_type_UserDefOneList(v, "arg1", &arg1, NULL);
         qapi_dealloc_visitor_cleanup(qdv);
     }

@@ -1002,24 +1028,12 @@ Example:
     }

     qapi_init(qmp_init_marshal);
-    $ cat qapi-generated/example-qmp-commands.h
-[Uninteresting stuff omitted...]
-
-    #ifndef EXAMPLE_QMP_COMMANDS_H
-    #define EXAMPLE_QMP_COMMANDS_H
-
-    #include "example-qapi-types.h"
-    #include "qapi/qmp/qdict.h"
-    #include "qapi/error.h"
-
-    UserDefOne *qmp_my_command(UserDefOne *arg1, Error **errp);
-
-    #endif

 === scripts/qapi-event.py ===

-Used to generate the event-related C code defined by a schema. The
-following files are created:
+Used to generate the event-related C code defined by a schema, with
+implementations for qapi_event_send_FOO(). The following files are
+created:

 $(prefix)qapi-event.h - Function prototypes for each event type, plus an
                         enumeration of all event names
@@ -1029,6 +1043,27 @@ Example:

     $ python scripts/qapi-event.py --output-dir="qapi-generated"
     --prefix="example-" example-schema.json
+    $ cat qapi-generated/example-qapi-event.h
+[Uninteresting stuff omitted...]
+
+    #ifndef EXAMPLE_QAPI_EVENT_H
+    #define EXAMPLE_QAPI_EVENT_H
+
+    #include "qapi/error.h"
+    #include "qapi/qmp/qdict.h"
+    #include "example-qapi-types.h"
+
+
+    void qapi_event_send_my_event(Error **errp);
+
+    typedef enum example_QAPIEvent {
+        EXAMPLE_QAPI_EVENT_MY_EVENT = 0,
+        EXAMPLE_QAPI_EVENT__MAX = 1,
+    } example_QAPIEvent;
+
+    extern const char *const example_QAPIEvent_lookup[];
+
+    #endif
     $ cat qapi-generated/example-qapi-event.c
 [Uninteresting stuff omitted...]

@@ -1054,27 +1089,6 @@ Example:
         [EXAMPLE_QAPI_EVENT_MY_EVENT] = "MY_EVENT",
         [EXAMPLE_QAPI_EVENT__MAX] = NULL,
     };
-    $ cat qapi-generated/example-qapi-event.h
-[Uninteresting stuff omitted...]
-
-    #ifndef EXAMPLE_QAPI_EVENT_H
-    #define EXAMPLE_QAPI_EVENT_H
-
-    #include "qapi/error.h"
-    #include "qapi/qmp/qdict.h"
-    #include "example-qapi-types.h"
-
-
-    void qapi_event_send_my_event(Error **errp);
-
-    typedef enum example_QAPIEvent {
-        EXAMPLE_QAPI_EVENT_MY_EVENT = 0,
-        EXAMPLE_QAPI_EVENT__MAX = 1,
-    } example_QAPIEvent;
-
-    extern const char *const example_QAPIEvent_lookup[];
-
-    #endif

 === scripts/qapi-introspect.py ===

@@ -1089,6 +1103,15 @@ Example:

     $ python scripts/qapi-introspect.py --output-dir="qapi-generated"
     --prefix="example-" example-schema.json
+    $ cat qapi-generated/example-qmp-introspect.h
+[Uninteresting stuff omitted...]
+
+    #ifndef EXAMPLE_QMP_INTROSPECT_H
+    #define EXAMPLE_QMP_INTROSPECT_H
+
+    extern const char example_qmp_schema_json[];
+
+    #endif
     $ cat qapi-generated/example-qmp-introspect.c
 [Uninteresting stuff omitted...]

@@ -1096,16 +1119,8 @@ Example:
         "{\"arg-type\": \"0\", \"meta-type\": \"event\", \"name\": 
\"MY_EVENT\"}, "
         "{\"arg-type\": \"1\", \"meta-type\": \"command\", \"name\": 
\"my-command\", \"ret-type\": \"2\"}, "
         "{\"members\": [], \"meta-type\": \"object\", \"name\": \"0\"}, "
-        "{\"members\": [{\"name\": \"arg1\", \"type\": \"2\"}], \"meta-type\": 
\"object\", \"name\": \"1\"}, "
-        "{\"members\": [{\"name\": \"integer\", \"type\": \"int\"}, {\"name\": 
\"string\", \"type\": \"str\"}], \"meta-type\": \"object\", \"name\": \"2\"}, "
+        "{\"members\": [{\"name\": \"arg1\", \"type\": \"[2]\"}], 
\"meta-type\": \"object\", \"name\": \"1\"}, "
+        "{\"members\": [{\"name\": \"integer\", \"type\": \"int\"}, 
{\"default\": null, \"name\": \"string\", \"type\": \"str\"}], \"meta-type\": 
\"object\", \"name\": \"2\"}, "
+        "{\"element-type\": \"2\", \"meta-type\": \"array\", \"name\": 
\"[2]\"}, "
         "{\"json-type\": \"int\", \"meta-type\": \"builtin\", \"name\": 
\"int\"}, "
         "{\"json-type\": \"string\", \"meta-type\": \"builtin\", \"name\": 
\"str\"}]";
-    $ cat qapi-generated/example-qmp-introspect.h
-[Uninteresting stuff omitted...]
-
-    #ifndef EXAMPLE_QMP_INTROSPECT_H
-    #define EXAMPLE_QMP_INTROSPECT_H
-
-    extern const char example_qmp_schema_json[];
-
-    #endif
-- 
2.5.0




reply via email to

[Prev in Thread] Current Thread [Next in Thread]