qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH v2 2/2] qapi: Allow setting default values for optio


From: Fam Zheng
Subject: [Qemu-devel] [PATCH v2 2/2] qapi: Allow setting default values for optional parameters
Date: Tue, 29 Apr 2014 17:44:16 +0800

In command definition, 'defaults' is now parsed as a dict of default
values. Only optional parameters will have effect in generated code.

'str' and 'int' are supported. In generated code, 'str' will be
converted to g_strdup'ed string pointer, 'int' will be identically
assigned.

E.g.

    { 'command': 'block-commit',
      'data': { 'device': 'str', '*base': 'str', 'top': 'str',
                '*speed': 'int' },
      'defaults': {'base': 'earthquake', 'speed': 100 } }

will generate

    int qmp_marshal_input_block_commit(Monitor *mon, const QDict *qdict, 
QObject **ret)
    {
        ...
        bool has_base = true;
        char * base = g_strdup("earthquake");
        ...
        bool has_speed = true;
        int64_t speed = 100;

Updated docs/qapi-code-gen.txt and qapi-schema tests.

Signed-off-by: Fam Zheng <address@hidden>
---
 docs/qapi-code-gen.txt                  |  8 ++++++--
 scripts/qapi-commands.py                | 29 ++++++++++++++++++++++-------
 scripts/qapi.py                         |  8 ++++++++
 tests/qapi-schema/qapi-schema-test.json |  3 +++
 tests/qapi-schema/qapi-schema-test.out  |  1 +
 tests/test-qmp-commands.c               |  7 +++++++
 6 files changed, 47 insertions(+), 9 deletions(-)

diff --git a/docs/qapi-code-gen.txt b/docs/qapi-code-gen.txt
index d78921f..b4cc6ed 100644
--- a/docs/qapi-code-gen.txt
+++ b/docs/qapi-code-gen.txt
@@ -172,12 +172,16 @@ This example allows using both of the following example 
objects:
 
 Commands are defined by using a list containing three members.  The first
 member is the command name, the second member is a dictionary containing
-arguments, and the third member is the return type.
+arguments, the third member is optional to define default values for optional
+arguments in 'data' dictionary, and the fourth member is the return type.
+
+Non-optional argument names are not allowed in the 'defaults' dictionary.
 
 An example command is:
 
  { 'command': 'my-command',
-   'data': { 'arg1': 'str', '*arg2': 'str' },
+   'data': { 'arg1': 'str', '*arg2': 'str', '*arg3': 'int' },
+   'defaults': { 'arg2': 'default value for arg2', 'arg3': 12345 },
    'returns': 'str' }
 
 
diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
index 9734ab0..aa4ce65 100644
--- a/scripts/qapi-commands.py
+++ b/scripts/qapi-commands.py
@@ -83,16 +83,28 @@ Visitor *v;
 
     return ret.rstrip()
 
-def gen_visitor_input_vars_decl(args):
+def gen_visitor_input_vars_decl(cmd_name, args, defaults):
     ret = ""
     push_indent()
     for argname, argtype, optional, structured in parse_args(args):
         if optional:
             ret += mcgen('''
-bool has_%(argname)s = false;
+bool has_%(argname)s = %(has_val)s;
 ''',
-                         argname=c_var(argname))
-        if c_type(argtype).endswith("*"):
+                         argname=c_var(argname),
+                         has_val="true" if defaults.get(argname) else "false")
+        if defaults.get(argname):
+            if optional:
+                ret += mcgen('''
+%(argtype)s %(argname)s = %(argval)s;
+''',
+                         argname=c_var(argname), argtype=c_type(argtype),
+                         argval=c_val(argtype, defaults[argname]))
+            else:
+                raise Exception('Error while generating "%s": '
+                                'default value given to non-optional value: 
"%s"'
+                                % (cmd_name, argname))
+        elif c_type(argtype).endswith("*"):
             ret += mcgen('''
 %(argtype)s %(argname)s = NULL;
 ''',
@@ -194,7 +206,7 @@ def gen_marshal_input_decl(name, args, ret_type, 
middle_mode):
 
 
 
-def gen_marshal_input(name, args, ret_type, middle_mode):
+def gen_marshal_input(name, args, ret_type, middle_mode, defaults):
     hdr = gen_marshal_input_decl(name, args, ret_type, middle_mode)
 
     ret = mcgen('''
@@ -229,7 +241,7 @@ def gen_marshal_input(name, args, ret_type, middle_mode):
 
 ''',
                      
visitor_input_containers_decl=gen_visitor_input_containers_decl(args),
-                     visitor_input_vars_decl=gen_visitor_input_vars_decl(args),
+                     visitor_input_vars_decl=gen_visitor_input_vars_decl(name, 
args, defaults),
                      visitor_input_block=gen_visitor_input_block(args, 
"QOBJECT(args)"))
     else:
         ret += mcgen('''
@@ -434,9 +446,12 @@ if dispatch_type == "sync":
 
     for cmd in commands:
         arglist = []
+        defaults = {}
         ret_type = None
         if cmd.has_key('data'):
             arglist = cmd['data']
+        if cmd.has_key('defaults'):
+            defaults = cmd['defaults']
         if cmd.has_key('returns'):
             ret_type = cmd['returns']
         ret = generate_command_decl(cmd['command'], arglist, ret_type) + "\n"
@@ -448,7 +463,7 @@ if dispatch_type == "sync":
         if middle_mode:
             fdecl.write('%s;\n' % gen_marshal_input_decl(cmd['command'], 
arglist, ret_type, middle_mode))
 
-        ret = gen_marshal_input(cmd['command'], arglist, ret_type, 
middle_mode) + "\n"
+        ret = gen_marshal_input(cmd['command'], arglist, ret_type, 
middle_mode, defaults) + "\n"
         fdef.write(ret)
 
     fdecl.write("\n#endif\n");
diff --git a/scripts/qapi.py b/scripts/qapi.py
index 6022de5..e1ee232 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -432,6 +432,14 @@ def find_enum(name):
 def is_enum(name):
     return find_enum(name) != None
 
+def c_val(t, val):
+    if t == 'str':
+        return 'g_strdup("%s")' % val
+    elif t == 'int':
+        return val
+    else:
+        assert False, "Unknown type: %s" % t
+
 def c_type(name):
     if name == 'str':
         return 'char *'
diff --git a/tests/qapi-schema/qapi-schema-test.json 
b/tests/qapi-schema/qapi-schema-test.json
index 818c06d..600439e 100644
--- a/tests/qapi-schema/qapi-schema-test.json
+++ b/tests/qapi-schema/qapi-schema-test.json
@@ -74,6 +74,9 @@
   'returns': 'UserDefTwo' }
 { 'command': 'user_def_cmd3', 'data': {'a': 'int', '*b': 'int' },
   'returns': 'int' }
+{ 'command': 'user_def_cmd4', 'data': {'a': 'int', '*b': 'int', '*c': 'str' },
+  'defaults': { 'b': 100, 'c': 'A string' },
+  'returns': 'int' }
 
 # For testing integer range flattening in opts-visitor. The following schema
 # corresponds to the option format:
diff --git a/tests/qapi-schema/qapi-schema-test.out 
b/tests/qapi-schema/qapi-schema-test.out
index 6cd03f3..fb26643 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -15,6 +15,7 @@
  OrderedDict([('command', 'user_def_cmd1'), ('data', OrderedDict([('ud1a', 
'UserDefOne')]))]),
  OrderedDict([('command', 'user_def_cmd2'), ('data', OrderedDict([('ud1a', 
'UserDefOne'), ('*ud1b', 'UserDefOne')])), ('returns', 'UserDefTwo')]),
  OrderedDict([('command', 'user_def_cmd3'), ('data', OrderedDict([('a', 
'int'), ('*b', 'int')])), ('returns', 'int')]),
+ OrderedDict([('command', 'user_def_cmd4'), ('data', OrderedDict([('a', 
'int'), ('*b', 'int'), ('*c', 'str')])), ('defaults', OrderedDict([('b', 100), 
('c', 'A string')])), ('returns', 'int')]),
  OrderedDict([('type', 'UserDefOptions'), ('data', OrderedDict([('*i64', 
['int']), ('*u64', ['uint64']), ('*u16', ['uint16']), ('*i64x', 'int'), 
('*u64x', 'uint64')]))])]
 [{'enum_name': 'EnumOne', 'enum_values': ['value1', 'value2', 'value3']},
  {'enum_name': 'UserDefUnionKind', 'enum_values': None},
diff --git a/tests/test-qmp-commands.c b/tests/test-qmp-commands.c
index 554e222..eb2a77a 100644
--- a/tests/test-qmp-commands.c
+++ b/tests/test-qmp-commands.c
@@ -48,6 +48,13 @@ int64_t qmp_user_def_cmd3(int64_t a, bool has_b, int64_t b, 
Error **errp)
     return a + (has_b ? b : 0);
 }
 
+int64_t qmp_user_def_cmd4(int64_t a, bool has_b, int64_t b,
+                          bool has_c, const char *c,
+                          Error **errp)
+{
+    return has_b && b == 100 && has_c && !strcmp(c, "A string");
+}
+
 /* test commands with no input and no return value */
 static void test_dispatch_cmd(void)
 {
-- 
1.9.2




reply via email to

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