Skip to content

Commit

Permalink
Merge remote-tracking branch 'remotes/qmp-unstable/queue/qmp' into st…
Browse files Browse the repository at this point in the history
…aging

* remotes/qmp-unstable/queue/qmp:
  qapi: skip redundant includes
  monitor: Add netdev_del id argument completion.
  monitor: Add netdev_add type argument completion.
  monitor: Add set_link arguments completion.
  monitor: Add chardev-add backend argument completion.
  monitor: Add chardev-remove command completion.
  monitor: Convert sendkey to use command_completion.
  qapi: Show qapi-commands.py invocation in qapi-code-gen.txt
  qapi: Replace uncommon use of the error API by the common one
  tests: Don't call visit_end_struct() after visit_start_struct() fails
  hw: Don't call visit_end_struct() after visit_start_struct() fails
  hmp: Call visit_end_struct() after visit_start_struct() succeeds
  qapi: Un-inline visit of implicit struct
  qapi-visit.py: Clean up a sloppy use of field prefix
  qapi: Clean up shadowing of parameters and locals in inner scopes
  qapi-visit.py: Clean up confusing push_indent() / pop_indent() use
  qapi: Replace start_optional()/end_optional() by optional()
  qapi: Remove unused Visitor callbacks start_handle(), end_handle()
  qapi: Normalize marshalling's visitor initialization and cleanup
  qapi: Update qapi-code-gen.txt example to match current code

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
  • Loading branch information
pm215 committed May 19, 2014
2 parents 5bc8f02 + 24fd848 commit c5fa6c8
Show file tree
Hide file tree
Showing 27 changed files with 752 additions and 445 deletions.
194 changes: 120 additions & 74 deletions docs/qapi-code-gen.txt
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ The QAPI schema definitions can be modularized using the 'include' directive:
{ 'include': 'path/to/file.json'}

The directive is evaluated recursively, and include paths are relative to the
file using the directive.
file using the directive. Multiple includes of the same file are safe.


=== Complex types ===
Expand Down Expand Up @@ -230,14 +230,13 @@ 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:

mdroth@illuin:~/w/qemu2.git$ cat example-schema.json
$ cat example-schema.json
{ 'type': 'UserDefOne',
'data': { 'integer': 'int', 'string': 'str' } }

{ 'command': 'my-command',
'data': {'arg1': 'UserDefOne'},
'returns': 'UserDefOne' }
mdroth@illuin:~/w/qemu2.git$

=== scripts/qapi-types.py ===

Expand All @@ -255,14 +254,25 @@ created code.

Example:

mdroth@illuin:~/w/qemu2.git$ python scripts/qapi-types.py \
--output-dir="qapi-generated" --prefix="example-" --input-file=example-schema.json
mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qapi-types.c
/* AUTOMATICALLY GENERATED, DO NOT MODIFY */
$ python scripts/qapi-types.py --output-dir="qapi-generated" \
--prefix="example-" --input-file=example-schema.json
$ cat qapi-generated/example-qapi-types.c
[Uninteresting stuff omitted...]

#include "qapi/qapi-dealloc-visitor.h"
#include "example-qapi-types.h"
#include "example-qapi-visit.h"
void qapi_free_UserDefOneList(UserDefOneList * obj)
{
QapiDeallocVisitor *md;
Visitor *v;

if (!obj) {
return;
}

md = qapi_dealloc_visitor_new();
v = qapi_dealloc_get_visitor(md);
visit_type_UserDefOneList(v, &obj, NULL, NULL);
qapi_dealloc_visitor_cleanup(md);
}

void qapi_free_UserDefOne(UserDefOne * obj)
{
Expand All @@ -279,32 +289,38 @@ Example:
qapi_dealloc_visitor_cleanup(md);
}

mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qapi-types.h
/* AUTOMATICALLY GENERATED, DO NOT MODIFY */
#ifndef QAPI_GENERATED_EXAMPLE_QAPI_TYPES
#define QAPI_GENERATED_EXAMPLE_QAPI_TYPES
$ cat qapi-generated/example-qapi-types.h
[Uninteresting stuff omitted...]

#ifndef EXAMPLE_QAPI_TYPES_H
#define EXAMPLE_QAPI_TYPES_H

#include "qapi/qapi-types-core.h"
[Builtin types omitted...]

typedef struct UserDefOne UserDefOne;

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

[Functions on builtin types omitted...]

struct UserDefOne
{
int64_t integer;
char * string;
};

void qapi_free_UserDefOneList(UserDefOneList * obj);
void qapi_free_UserDefOne(UserDefOne * obj);

#endif


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

Used to generate the visitor functions used to walk through and convert
Expand All @@ -325,51 +341,78 @@ $(prefix)qapi-visit.h: declarations for previously mentioned visitor

Example:

mdroth@illuin:~/w/qemu2.git$ python scripts/qapi-visit.py \
--output-dir="qapi-generated" --prefix="example-" --input-file=example-schema.json
mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qapi-visit.c
/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
$ python scripts/qapi-visit.py --output-dir="qapi-generated"
--prefix="example-" --input-file=example-schema.json
$ cat qapi-generated/example-qapi-visit.c
[Uninteresting stuff omitted...]

#include "example-qapi-visit.h"
static void visit_type_UserDefOne_fields(Visitor *m, UserDefOne ** obj, Error **errp)
{
Error *err = NULL;
visit_type_int(m, &(*obj)->integer, "integer", &err);
if (err) {
goto out;
}
visit_type_str(m, &(*obj)->string, "string", &err);
if (err) {
goto out;
}

out:
error_propagate(errp, err);
}

void visit_type_UserDefOne(Visitor *m, UserDefOne ** obj, const char *name, Error **errp)
{
visit_start_struct(m, (void **)obj, "UserDefOne", name, sizeof(UserDefOne), errp);
visit_type_int(m, (obj && *obj) ? &(*obj)->integer : NULL, "integer", errp);
visit_type_str(m, (obj && *obj) ? &(*obj)->string : NULL, "string", errp);
visit_end_struct(m, errp);
Error *err = NULL;

visit_start_struct(m, (void **)obj, "UserDefOne", name, sizeof(UserDefOne), &err);
if (!err) {
if (*obj) {
visit_type_UserDefOne_fields(m, obj, errp);
}
visit_end_struct(m, &err);
}
error_propagate(errp, err);
}

void visit_type_UserDefOneList(Visitor *m, UserDefOneList ** obj, const char *name, Error **errp)
{
GenericList *i, **prev = (GenericList **)obj;
Error *err = NULL;
GenericList *i, **prev;

visit_start_list(m, name, errp);
visit_start_list(m, name, &err);
if (err) {
goto out;
}

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

visit_end_list(m, errp);
error_propagate(errp, err);
err = NULL;
visit_end_list(m, &err);
out:
error_propagate(errp, err);
}
mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qapi-visit.h
/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
$ python scripts/qapi-commands.py --output-dir="qapi-generated" \
--prefix="example-" --input-file=example-schema.json
$ cat qapi-generated/example-qapi-visit.h
[Uninteresting stuff omitted...]

#ifndef QAPI_GENERATED_EXAMPLE_QAPI_VISIT
#define QAPI_GENERATED_EXAMPLE_QAPI_VISIT
#ifndef EXAMPLE_QAPI_VISIT_H
#define EXAMPLE_QAPI_VISIT_H

#include "qapi/qapi-visit-core.h"
#include "example-qapi-types.h"
[Visitors for builtin types omitted...]

void visit_type_UserDefOne(Visitor *m, UserDefOne ** obj, const char *name, Error **errp);
void visit_type_UserDefOneList(Visitor *m, UserDefOneList ** obj, const char *name, Error **errp);

#endif
mdroth@illuin:~/w/qemu2.git$

(The actual structure of the visit_type_* functions is a bit more complex
in order to propagate errors correctly and avoid leaking memory).

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

Expand All @@ -390,77 +433,80 @@ $(prefix)qmp-commands.h: Function prototypes for the QMP commands

Example:

mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qmp-marshal.c
/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */

#include "qemu-objects.h"
#include "qapi/qmp-core.h"
#include "qapi/qapi-visit-core.h"
#include "qapi/qmp-output-visitor.h"
#include "qapi/qmp-input-visitor.h"
#include "qapi/qapi-dealloc-visitor.h"
#include "example-qapi-types.h"
#include "example-qapi-visit.h"
$ cat qapi-generated/example-qmp-marshal.c
[Uninteresting stuff omitted...]

#include "example-qmp-commands.h"
static void qmp_marshal_output_my_command(UserDefOne * ret_in, QObject **ret_out, Error **errp)
{
QapiDeallocVisitor *md = qapi_dealloc_visitor_new();
Error *local_err = NULL;
QmpOutputVisitor *mo = qmp_output_visitor_new();
QapiDeallocVisitor *md;
Visitor *v;

v = qmp_output_get_visitor(mo);
visit_type_UserDefOne(v, &ret_in, "unused", errp);
visit_type_UserDefOne(v, &ret_in, "unused", &local_err);
if (local_err) {
goto out;
}
*ret_out = qmp_output_get_qobject(mo);

out:
error_propagate(errp, local_err);
qmp_output_visitor_cleanup(mo);
md = qapi_dealloc_visitor_new();
v = qapi_dealloc_get_visitor(md);
visit_type_UserDefOne(v, &ret_in, "unused", errp);
visit_type_UserDefOne(v, &ret_in, "unused", NULL);
qapi_dealloc_visitor_cleanup(md);


*ret_out = qmp_output_get_qobject(mo);
}

static void qmp_marshal_input_my_command(QmpState *qmp__sess, QDict *args, QObject **ret, Error **errp)
static void qmp_marshal_input_my_command(QDict *args, QObject **ret, Error **errp)
{
Error *local_err = NULL;
UserDefOne * retval = NULL;
QmpInputVisitor *mi;
QmpInputVisitor *mi = qmp_input_visitor_new_strict(QOBJECT(args));
QapiDeallocVisitor *md;
Visitor *v;
UserDefOne * arg1 = NULL;

mi = qmp_input_visitor_new(QOBJECT(args));
v = qmp_input_get_visitor(mi);
visit_type_UserDefOne(v, &arg1, "arg1", errp);
visit_type_UserDefOne(v, &arg1, "arg1", &local_err);
if (local_err) {
goto out;
}

if (error_is_set(errp)) {
retval = qmp_my_command(arg1, &local_err);
if (local_err) {
goto out;
}
retval = qmp_my_command(arg1, errp);
qmp_marshal_output_my_command(retval, ret, errp);

qmp_marshal_output_my_command(retval, ret, &local_err);

out:
error_propagate(errp, local_err);
qmp_input_visitor_cleanup(mi);
md = qapi_dealloc_visitor_new();
v = qapi_dealloc_get_visitor(md);
visit_type_UserDefOne(v, &arg1, "arg1", errp);
visit_type_UserDefOne(v, &arg1, "arg1", NULL);
qapi_dealloc_visitor_cleanup(md);
return;
}

static void qmp_init_marshal(void)
{
qmp_register_command("my-command", qmp_marshal_input_my_command);
qmp_register_command("my-command", qmp_marshal_input_my_command, QCO_NO_OPTIONS);
}

qapi_init(qmp_init_marshal);
mdroth@illuin:~/w/qemu2.git$ cat qapi-generated/example-qmp-commands.h
/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
$ cat qapi-generated/example-qmp-commands.h
[Uninteresting stuff omitted...]

#ifndef QAPI_GENERATED_EXAMPLE_QMP_COMMANDS
#define QAPI_GENERATED_EXAMPLE_QMP_COMMANDS
#ifndef EXAMPLE_QMP_COMMANDS_H
#define EXAMPLE_QMP_COMMANDS_H

#include "example-qapi-types.h"
#include "error.h"
#include "qapi/qmp/qdict.h"
#include "qapi/error.h"

UserDefOne * qmp_my_command(UserDefOne * arg1, Error **errp);

#endif
mdroth@illuin:~/w/qemu2.git$
8 changes: 7 additions & 1 deletion hmp-commands.hx
Original file line number Diff line number Diff line change
Expand Up @@ -556,6 +556,7 @@ ETEXI
.params = "keys [hold_ms]",
.help = "send keys to the VM (e.g. 'sendkey ctrl-alt-f1', default hold time=100 ms)",
.mhandler.cmd = hmp_send_key,
.command_completion = sendkey_completion,
},

STEXI
Expand Down Expand Up @@ -1233,9 +1234,10 @@ ETEXI
{
.name = "netdev_add",
.args_type = "netdev:O",
.params = "[user|tap|socket|hubport|netmap],id=str[,prop=value][,...]",
.params = "[user|tap|socket|vde|bridge|hubport|netmap],id=str[,prop=value][,...]",
.help = "add host network device",
.mhandler.cmd = hmp_netdev_add,
.command_completion = netdev_add_completion,
},

STEXI
Expand All @@ -1250,6 +1252,7 @@ ETEXI
.params = "id",
.help = "remove host network device",
.mhandler.cmd = hmp_netdev_del,
.command_completion = netdev_del_completion,
},

STEXI
Expand Down Expand Up @@ -1339,6 +1342,7 @@ ETEXI
.params = "name on|off",
.help = "change the link status of a network adapter",
.mhandler.cmd = hmp_set_link,
.command_completion = set_link_completion,
},

STEXI
Expand Down Expand Up @@ -1622,6 +1626,7 @@ ETEXI
.params = "args",
.help = "add chardev",
.mhandler.cmd = hmp_chardev_add,
.command_completion = chardev_add_completion,
},

STEXI
Expand All @@ -1638,6 +1643,7 @@ ETEXI
.params = "id",
.help = "remove chardev",
.mhandler.cmd = hmp_chardev_remove,
.command_completion = chardev_remove_completion,
},

STEXI
Expand Down

0 comments on commit c5fa6c8

Please sign in to comment.