aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--docs/qapi-code-gen.txt2
-rw-r--r--scripts/qapi-commands.py140
-rw-r--r--scripts/qapi-event.py122
-rw-r--r--scripts/qapi-types.py79
-rw-r--r--scripts/qapi-visit.py127
-rw-r--r--scripts/qapi.py127
6 files changed, 272 insertions, 325 deletions
diff --git a/docs/qapi-code-gen.txt b/docs/qapi-code-gen.txt
index 81e87d2ec1..3eaff367a4 100644
--- a/docs/qapi-code-gen.txt
+++ b/docs/qapi-code-gen.txt
@@ -598,7 +598,7 @@ Example:
UserDefOne *value;
uint64_t padding;
};
- struct UserDefOneList *next;
+ UserDefOneList *next;
};
void qapi_free_UserDefOneList(UserDefOneList *obj);
diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
index cbff3560f4..0501582c3b 100644
--- a/scripts/qapi-commands.py
+++ b/scripts/qapi-commands.py
@@ -15,20 +15,22 @@
from qapi import *
import re
-def generate_command_decl(name, args, ret_type):
- arglist=""
- if args:
- for memb in args.members:
- argtype = memb.type.c_type(is_param=True)
+
+def gen_command_decl(name, arg_type, ret_type):
+ argstr = ''
+ if arg_type:
+ for memb in arg_type.members:
if memb.optional:
- arglist += "bool has_%s, " % c_name(memb.name)
- arglist += "%s %s, " % (argtype, c_name(memb.name))
+ argstr += 'bool has_%s, ' % c_name(memb.name)
+ argstr += '%s %s, ' % (memb.type.c_type(is_param=True),
+ c_name(memb.name))
return mcgen('''
-%(ret_type)s qmp_%(name)s(%(args)sError **errp);
+%(c_type)s qmp_%(c_name)s(%(args)sError **errp);
''',
- ret_type=(ret_type and ret_type.c_type()) or 'void',
- name=c_name(name),
- args=arglist)
+ c_type=(ret_type and ret_type.c_type()) or 'void',
+ c_name=c_name(name),
+ args=argstr)
+
def gen_err_check(err):
if not err:
@@ -40,37 +42,42 @@ if (%(err)s) {
''',
err=err)
-def gen_sync_call(name, args, ret_type):
- ret = ""
- arglist=""
- retval=""
- if ret_type:
- retval = "retval = "
- if args:
- for memb in args.members:
+
+def gen_call(name, arg_type, ret_type):
+ ret = ''
+
+ argstr = ''
+ if arg_type:
+ for memb in arg_type.members:
if memb.optional:
- arglist += "has_%s, " % c_name(memb.name)
- arglist += "%s, " % c_name(memb.name)
+ argstr += 'has_%s, ' % c_name(memb.name)
+ argstr += '%s, ' % c_name(memb.name)
+
+ lhs = ''
+ if ret_type:
+ lhs = 'retval = '
+
push_indent()
ret = mcgen('''
-%(retval)sqmp_%(name)s(%(args)s&local_err);
+%(lhs)sqmp_%(c_name)s(%(args)s&local_err);
''',
- name=c_name(name), args=arglist, retval=retval)
+ c_name=c_name(name), args=argstr, lhs=lhs)
if ret_type:
ret += gen_err_check('local_err')
ret += mcgen('''
qmp_marshal_output_%(c_name)s(retval, ret, &local_err);
''',
- c_name=c_name(name))
+ c_name=c_name(name))
pop_indent()
return ret
-def gen_visitor_input_containers_decl(args):
- ret = ""
+
+def gen_visitor_input_containers_decl(arg_type):
+ ret = ''
push_indent()
- if args:
+ if arg_type:
ret += mcgen('''
QmpInputVisitor *mi = qmp_input_visitor_new_strict(QOBJECT(args));
QapiDeallocVisitor *md;
@@ -80,17 +87,18 @@ Visitor *v;
return ret
-def gen_visitor_input_vars_decl(args):
- ret = ""
+
+def gen_visitor_input_vars_decl(arg_type):
+ ret = ''
push_indent()
- if args:
- for memb in args.members:
+ if arg_type:
+ for memb in arg_type.members:
if memb.optional:
ret += mcgen('''
-bool has_%(argname)s = false;
+bool has_%(c_name)s = false;
''',
- argname=c_name(memb.name))
+ c_name=c_name(memb.name))
ret += mcgen('''
%(c_type)s %(c_name)s = %(c_null)s;
''',
@@ -101,19 +109,20 @@ bool has_%(argname)s = false;
pop_indent()
return ret
-def gen_visitor_input_block(args, dealloc=False):
- ret = ""
+
+def gen_visitor_input_block(arg_type, dealloc=False):
+ ret = ''
errparg = '&local_err'
errarg = 'local_err'
- if not args:
+ if not arg_type:
return ret
push_indent()
if dealloc:
errparg = 'NULL'
- errarg = None;
+ errarg = None
ret += mcgen('''
qmp_input_visitor_cleanup(mi);
md = qapi_dealloc_visitor_new();
@@ -124,7 +133,7 @@ v = qapi_dealloc_get_visitor(md);
v = qmp_input_get_visitor(mi);
''')
- for memb in args.members:
+ for memb in arg_type.members:
if memb.optional:
ret += mcgen('''
visit_optional(v, &has_%(c_name)s, "%(name)s", %(errp)s);
@@ -138,10 +147,10 @@ if (has_%(c_name)s) {
c_name=c_name(memb.name))
push_indent()
ret += mcgen('''
-visit_type_%(visitor)s(v, &%(c_name)s, "%(name)s", %(errp)s);
+visit_type_%(c_type)s(v, &%(c_name)s, "%(name)s", %(errp)s);
''',
c_name=c_name(memb.name), name=memb.name,
- visitor=memb.type.c_name(), errp=errparg)
+ c_type=memb.type.c_name(), errp=errparg)
ret += gen_err_check(errarg)
if memb.optional:
pop_indent()
@@ -156,13 +165,14 @@ qapi_dealloc_visitor_cleanup(md);
pop_indent()
return ret
+
def gen_marshal_output(name, ret_type):
if not ret_type:
- return ""
+ return ''
ret = mcgen('''
-static void qmp_marshal_output_%(c_name)s(%(c_ret_type)s ret_in, QObject **ret_out, Error **errp)
+static void qmp_marshal_output_%(c_cmd_name)s(%(c_type)s ret_in, QObject **ret_out, Error **errp)
{
Error *local_err = NULL;
QmpOutputVisitor *mo = qmp_output_visitor_new();
@@ -170,7 +180,7 @@ static void qmp_marshal_output_%(c_name)s(%(c_ret_type)s ret_in, QObject **ret_o
Visitor *v;
v = qmp_output_get_visitor(mo);
- visit_type_%(visitor)s(v, &ret_in, "unused", &local_err);
+ visit_type_%(c_name)s(v, &ret_in, "unused", &local_err);
if (local_err) {
goto out;
}
@@ -181,23 +191,25 @@ out:
qmp_output_visitor_cleanup(mo);
md = qapi_dealloc_visitor_new();
v = qapi_dealloc_get_visitor(md);
- visit_type_%(visitor)s(v, &ret_in, "unused", NULL);
+ visit_type_%(c_name)s(v, &ret_in, "unused", NULL);
qapi_dealloc_visitor_cleanup(md);
}
''',
- c_ret_type=ret_type.c_type(), c_name=c_name(name),
- visitor=ret_type.c_name())
+ c_type=ret_type.c_type(), c_cmd_name=c_name(name),
+ c_name=ret_type.c_name())
return ret
-def gen_marshal_input_decl(name, middle_mode):
+
+def gen_marshal_input_decl(name):
ret = 'void qmp_marshal_input_%s(QDict *args, QObject **ret, Error **errp)' % c_name(name)
if not middle_mode:
- ret = "static " + ret
+ ret = 'static ' + ret
return ret
-def gen_marshal_input(name, args, ret_type, middle_mode):
- hdr = gen_marshal_input_decl(name, middle_mode)
+
+def gen_marshal_input(name, arg_type, ret_type):
+ hdr = gen_marshal_input_decl(name)
ret = mcgen('''
@@ -213,10 +225,10 @@ def gen_marshal_input(name, args, ret_type, middle_mode):
''',
c_type=ret_type.c_type())
- if args:
- ret += gen_visitor_input_containers_decl(args)
- ret += gen_visitor_input_vars_decl(args) + '\n'
- ret += gen_visitor_input_block(args) + '\n'
+ if arg_type:
+ ret += gen_visitor_input_containers_decl(arg_type)
+ ret += gen_visitor_input_vars_decl(arg_type) + '\n'
+ ret += gen_visitor_input_block(arg_type) + '\n'
else:
ret += mcgen('''
@@ -224,9 +236,9 @@ def gen_marshal_input(name, args, ret_type, middle_mode):
''')
- ret += gen_sync_call(name, args, ret_type)
+ ret += gen_call(name, arg_type, ret_type)
- if re.search('^ *goto out\\;', ret, re.MULTILINE):
+ if re.search('^ *goto out;', ret, re.MULTILINE):
ret += mcgen('''
out:
@@ -234,12 +246,13 @@ out:
ret += mcgen('''
error_propagate(errp, local_err);
''')
- ret += gen_visitor_input_block(args, dealloc=True)
+ ret += gen_visitor_input_block(arg_type, dealloc=True)
ret += mcgen('''
}
''')
return ret
+
def gen_register_command(name, success_response):
push_indent()
options = 'QCO_NO_OPTIONS'
@@ -249,11 +262,12 @@ def gen_register_command(name, success_response):
ret = mcgen('''
qmp_register_command("%(name)s", qmp_marshal_input_%(c_name)s, %(opts)s);
''',
- name=name, c_name=c_name(name),
- opts=options)
+ name=name, c_name=c_name(name),
+ opts=options)
pop_indent()
return ret
+
def gen_registry(registry):
ret = mcgen('''
@@ -289,12 +303,12 @@ class QAPISchemaGenCommandVisitor(QAPISchemaVisitor):
gen, success_response):
if not gen:
return
- self.decl += generate_command_decl(name, arg_type, ret_type)
+ self.decl += gen_command_decl(name, arg_type, ret_type)
if ret_type:
self.defn += gen_marshal_output(name, ret_type)
if middle_mode:
- self.decl += gen_marshal_input_decl(name, middle_mode) + ';\n'
- self.defn += gen_marshal_input(name, arg_type, ret_type, middle_mode)
+ self.decl += gen_marshal_input_decl(name) + ';\n'
+ self.defn += gen_marshal_input(name, arg_type, ret_type)
if not middle_mode:
self._regy += gen_register_command(name, success_response)
@@ -355,7 +369,7 @@ fdef.write(mcgen('''
#include "%(prefix)sqmp-commands.h"
''',
- prefix=prefix))
+ prefix=prefix))
fdecl.write(mcgen('''
#include "%(prefix)sqapi-types.h"
diff --git a/scripts/qapi-event.py b/scripts/qapi-event.py
index d19acda7d3..5873a05888 100644
--- a/scripts/qapi-event.py
+++ b/scripts/qapi-event.py
@@ -13,12 +13,13 @@
from qapi import *
-def _generate_event_api_name(event_name, params):
- api_name = "void qapi_event_send_%s(" % c_name(event_name).lower();
+
+def gen_event_send_proto(name, arg_type):
+ api_name = "void qapi_event_send_%s(" % c_name(name).lower()
l = len(api_name)
- if params:
- for m in params.members:
+ if arg_type:
+ for m in arg_type.members:
if m.optional:
api_name += "bool has_%s,\n" % c_name(m.name)
api_name += "".ljust(l)
@@ -28,53 +29,49 @@ def _generate_event_api_name(event_name, params):
api_name += "".ljust(l)
api_name += "Error **errp)"
- return api_name;
-
+ return api_name
-# Following are the core functions that generate C APIs to emit event.
-def generate_event_declaration(api_name):
+def gen_event_send_decl(name, arg_type):
return mcgen('''
-%(api_name)s;
+%(proto)s;
''',
- api_name = api_name)
+ proto=gen_event_send_proto(name, arg_type))
+
-def generate_event_implement(api_name, event_name, params):
- # step 1: declare any variables
- ret = mcgen("""
+def gen_event_send(name, arg_type):
+ ret = mcgen('''
-%(api_name)s
+%(proto)s
{
QDict *qmp;
Error *local_err = NULL;
QMPEventFuncEmit emit;
-""",
- api_name = api_name)
+''',
+ proto=gen_event_send_proto(name, arg_type))
- if params and params.members:
- ret += mcgen("""
+ if arg_type and arg_type.members:
+ ret += mcgen('''
QmpOutputVisitor *qov;
Visitor *v;
QObject *obj;
-""")
+''')
- # step 2: check emit function, create a dict
- ret += mcgen("""
+ ret += mcgen('''
emit = qmp_event_get_func_emit();
if (!emit) {
return;
}
- qmp = qmp_event_build_dict("%(event_name)s");
+ qmp = qmp_event_build_dict("%(name)s");
-""",
- event_name = event_name)
+''',
+ name=name)
- # step 3: visit the params if params != None
- if params and params.members:
- ret += mcgen("""
+ if arg_type and arg_type.members:
+ ret += mcgen('''
qov = qmp_output_visitor_new();
g_assert(qov);
@@ -82,45 +79,46 @@ def generate_event_implement(api_name, event_name, params):
g_assert(v);
/* Fake visit, as if all members are under a structure */
- visit_start_struct(v, NULL, "", "%(event_name)s", 0, &local_err);
+ visit_start_struct(v, NULL, "", "%(name)s", 0, &local_err);
if (local_err) {
goto clean;
}
-""",
- event_name = event_name)
+''',
+ name=name)
- for memb in params.members:
+ for memb in arg_type.members:
if memb.optional:
- ret += mcgen("""
- if (has_%(var)s) {
-""",
- var=c_name(memb.name))
+ ret += mcgen('''
+ if (has_%(c_name)s) {
+''',
+ c_name=c_name(memb.name))
push_indent()
+ # Ugly: need to cast away the const
if memb.type.name == "str":
- var_type = "(char **)"
+ cast = '(char **)'
else:
- var_type = ""
+ cast = ''
- ret += mcgen("""
- visit_type_%(type)s(v, %(var_type)s&%(var)s, "%(name)s", &local_err);
+ ret += mcgen('''
+ visit_type_%(c_type)s(v, %(cast)s&%(c_name)s, "%(name)s", &local_err);
if (local_err) {
goto clean;
}
-""",
- var_type = var_type,
- var=c_name(memb.name),
- type=memb.type.c_name(),
+''',
+ cast=cast,
+ c_name=c_name(memb.name),
+ c_type=memb.type.c_name(),
name=memb.name)
if memb.optional:
pop_indent()
- ret += mcgen("""
+ ret += mcgen('''
}
-""")
+''')
- ret += mcgen("""
+ ret += mcgen('''
visit_end_struct(v, &local_err);
if (local_err) {
@@ -131,27 +129,24 @@ def generate_event_implement(api_name, event_name, params):
g_assert(obj != NULL);
qdict_put_obj(qmp, "data", obj);
-""")
+''')
- # step 4: call qmp event api
- ret += mcgen("""
- emit(%(event_enum_value)s, qmp, &local_err);
+ ret += mcgen('''
+ emit(%(c_enum)s, qmp, &local_err);
-""",
- event_enum_value = c_enum_const(event_enum_name, event_name))
+''',
+ c_enum=c_enum_const(event_enum_name, name))
- # step 5: clean up
- if params and params.members:
- ret += mcgen("""
+ if arg_type and arg_type.members:
+ ret += mcgen('''
clean:
qmp_output_visitor_cleanup(qov);
-""")
- ret += mcgen("""
+''')
+ ret += mcgen('''
error_propagate(errp, local_err);
QDECREF(qmp);
}
-""")
-
+''')
return ret
@@ -167,14 +162,13 @@ class QAPISchemaGenEventVisitor(QAPISchemaVisitor):
self._event_names = []
def visit_end(self):
- self.decl += generate_enum(event_enum_name, self._event_names)
- self.defn += generate_enum_lookup(event_enum_name, self._event_names)
+ self.decl += gen_enum(event_enum_name, self._event_names)
+ self.defn += gen_enum_lookup(event_enum_name, self._event_names)
self._event_names = None
def visit_event(self, name, info, arg_type):
- api_name = _generate_event_api_name(name, arg_type)
- self.decl += generate_event_declaration(api_name)
- self.defn += generate_event_implement(api_name, name, arg_type)
+ self.decl += gen_event_send_decl(name, arg_type)
+ self.defn += gen_event_send(name, arg_type)
self._event_names.append(name)
diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py
index 76c82d96b9..d1fee207e5 100644
--- a/scripts/qapi-types.py
+++ b/scripts/qapi-types.py
@@ -13,25 +13,28 @@
from qapi import *
+
def gen_fwd_object_or_array(name):
return mcgen('''
-typedef struct %(name)s %(name)s;
+typedef struct %(c_name)s %(c_name)s;
''',
- name=c_name(name))
+ c_name=c_name(name))
+
def gen_array(name, element_type):
return mcgen('''
-struct %(name)s {
+struct %(c_name)s {
union {
%(c_type)s value;
uint64_t padding;
};
- struct %(name)s *next;
+ %(c_name)s *next;
};
''',
- name=c_name(name), c_type=element_type.c_type())
+ c_name=c_name(name), c_type=element_type.c_type())
+
def gen_struct_field(name, typ, optional):
ret = ''
@@ -47,30 +50,33 @@ def gen_struct_field(name, typ, optional):
c_type=typ.c_type(), c_name=c_name(name))
return ret
-def generate_struct_fields(members):
+
+def gen_struct_fields(members):
ret = ''
for memb in members:
ret += gen_struct_field(memb.name, memb.type, memb.optional)
return ret
+
def gen_struct(name, base, members):
ret = mcgen('''
-struct %(name)s {
+struct %(c_name)s {
''',
- name=c_name(name))
+ c_name=c_name(name))
if base:
ret += gen_struct_field('base', base, False)
- ret += generate_struct_fields(members)
+ ret += gen_struct_fields(members)
# Make sure that all structs have at least one field; this avoids
- # potential issues with attempting to malloc space for zero-length structs
- # in C, and also incompatibility with C++ (where an empty struct is size 1).
+ # potential issues with attempting to malloc space for zero-length
+ # structs in C, and also incompatibility with C++ (where an empty
+ # struct is size 1).
if not base and not members:
- ret += mcgen('''
+ ret += mcgen('''
char qapi_dummy_field_for_empty_struct;
''')
@@ -80,6 +86,7 @@ struct %(name)s {
return ret
+
def gen_alternate_qtypes_decl(name):
return mcgen('''
@@ -87,12 +94,13 @@ extern const int %(c_name)s_qtypes[];
''',
c_name=c_name(name))
+
def gen_alternate_qtypes(name, variants):
ret = mcgen('''
-const int %(name)s_qtypes[QTYPE_MAX] = {
+const int %(c_name)s_qtypes[QTYPE_MAX] = {
''',
- name=c_name(name))
+ c_name=c_name(name))
for var in variants.variants:
qtype = var.type.alternate_qtype()
@@ -101,7 +109,7 @@ const int %(name)s_qtypes[QTYPE_MAX] = {
ret += mcgen('''
[%(qtype)s] = %(enum_const)s,
''',
- qtype = qtype,
+ qtype=qtype,
enum_const=c_enum_const(variants.tag_member.type.name,
var.name))
@@ -110,28 +118,27 @@ const int %(name)s_qtypes[QTYPE_MAX] = {
''')
return ret
-def gen_union(name, base, variants):
- name = c_name(name)
+def gen_union(name, base, variants):
ret = mcgen('''
-struct %(name)s {
+struct %(c_name)s {
''',
- name=name)
+ c_name=c_name(name))
if base:
ret += mcgen('''
/* Members inherited from %(c_name)s: */
''',
c_name=c_name(base.name))
- ret += generate_struct_fields(base.members)
+ ret += gen_struct_fields(base.members)
ret += mcgen('''
/* Own members: */
''')
else:
ret += mcgen('''
- %(discriminator_type_name)s kind;
+ %(c_type)s kind;
''',
- discriminator_type_name=c_name(variants.tag_member.type.name))
+ c_type=c_name(variants.tag_member.type.name))
# FIXME: What purpose does data serve, besides preventing a union that
# has a branch named 'data'? We use it in qapi-visit.py to decide
@@ -166,18 +173,20 @@ struct %(name)s {
return ret
-def generate_type_cleanup_decl(name):
+
+def gen_type_cleanup_decl(name):
ret = mcgen('''
-void qapi_free_%(name)s(%(name)s *obj);
+void qapi_free_%(c_name)s(%(c_name)s *obj);
''',
- name=c_name(name))
+ c_name=c_name(name))
return ret
-def generate_type_cleanup(name):
+
+def gen_type_cleanup(name):
ret = mcgen('''
-void qapi_free_%(name)s(%(name)s *obj)
+void qapi_free_%(c_name)s(%(c_name)s *obj)
{
QapiDeallocVisitor *md;
Visitor *v;
@@ -188,11 +197,11 @@ void qapi_free_%(name)s(%(name)s *obj)
md = qapi_dealloc_visitor_new();
v = qapi_dealloc_get_visitor(md);
- visit_type_%(name)s(v, &obj, NULL, NULL);
+ visit_type_%(c_name)s(v, &obj, NULL, NULL);
qapi_dealloc_visitor_cleanup(md);
}
''',
- name=c_name(name))
+ c_name=c_name(name))
return ret
@@ -225,20 +234,20 @@ class QAPISchemaGenTypeVisitor(QAPISchemaVisitor):
self._btin = None
def _gen_type_cleanup(self, name):
- self.decl += generate_type_cleanup_decl(name)
- self.defn += generate_type_cleanup(name)
+ self.decl += gen_type_cleanup_decl(name)
+ self.defn += gen_type_cleanup(name)
def visit_enum_type(self, name, info, values, prefix):
- self._fwdecl += generate_enum(name, values, prefix)
- self._fwdefn += generate_enum_lookup(name, values, prefix)
+ 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):
self._btin += gen_fwd_object_or_array(name)
self._btin += gen_array(name, element_type)
- self._btin += generate_type_cleanup_decl(name)
+ self._btin += gen_type_cleanup_decl(name)
if do_builtins:
- self.defn += generate_type_cleanup(name)
+ self.defn += gen_type_cleanup(name)
else:
self._fwdecl += gen_fwd_object_or_array(name)
self.decl += gen_array(name, element_type)
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index 8e6e8cacbe..fae70e2d24 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -18,18 +18,20 @@ import re
implicit_structs_seen = set()
struct_fields_seen = set()
-def generate_visit_implicit_struct(type):
- if type in implicit_structs_seen:
+
+def gen_visit_implicit_struct(typ):
+ if typ in implicit_structs_seen:
return ''
- implicit_structs_seen.add(type)
+ implicit_structs_seen.add(typ)
+
ret = ''
- if type.name not in struct_fields_seen:
+ if typ.name not in struct_fields_seen:
# Need a forward declaration
ret += mcgen('''
static void visit_type_%(c_type)s_fields(Visitor *m, %(c_type)s **obj, Error **errp);
''',
- c_type=type.c_name())
+ c_type=typ.c_name())
ret += mcgen('''
@@ -45,35 +47,36 @@ static void visit_type_implicit_%(c_type)s(Visitor *m, %(c_type)s **obj, Error *
error_propagate(errp, err);
}
''',
- c_type=type.c_name())
+ c_type=typ.c_name())
return ret
-def generate_visit_struct_fields(name, members, base = None):
+
+def gen_visit_struct_fields(name, base, members):
struct_fields_seen.add(name)
ret = ''
if base:
- ret += generate_visit_implicit_struct(base)
+ ret += gen_visit_implicit_struct(base)
ret += mcgen('''
-static void visit_type_%(name)s_fields(Visitor *m, %(name)s **obj, Error **errp)
+static void visit_type_%(c_name)s_fields(Visitor *m, %(c_name)s **obj, Error **errp)
{
Error *err = NULL;
''',
- name=c_name(name))
+ c_name=c_name(name))
push_indent()
if base:
ret += mcgen('''
-visit_type_implicit_%(type)s(m, &(*obj)->%(c_name)s, &err);
+visit_type_implicit_%(c_type)s(m, &(*obj)->%(c_name)s, &err);
if (err) {
goto out;
}
''',
- type=base.c_name(), c_name=c_name('base'))
+ c_type=base.c_name(), c_name=c_name('base'))
for memb in members:
if memb.optional:
@@ -85,9 +88,9 @@ if (!err && (*obj)->has_%(c_name)s) {
push_indent()
ret += mcgen('''
-visit_type_%(type)s(m, &(*obj)->%(c_name)s, "%(name)s", &err);
+visit_type_%(c_type)s(m, &(*obj)->%(c_name)s, "%(name)s", &err);
''',
- type=memb.type.c_name(), c_name=c_name(memb.name),
+ c_type=memb.type.c_name(), c_name=c_name(memb.name),
name=memb.name)
if memb.optional:
@@ -102,7 +105,7 @@ if (err) {
''')
pop_indent()
- if re.search('^ *goto out\\;', ret, re.MULTILINE):
+ if re.search('^ *goto out;', ret, re.MULTILINE):
ret += mcgen('''
out:
@@ -114,7 +117,7 @@ out:
return ret
-def generate_visit_struct_body(name):
+def gen_visit_struct_body(name):
# FIXME: if *obj is NULL on entry, and visit_start_struct() assigns to
# *obj, but then visit_type_FOO_fields() fails, we should clean up *obj
# rather than leaving it non-NULL. As currently written, the caller must
@@ -132,30 +135,30 @@ def generate_visit_struct_body(name):
error_propagate(errp, err);
''',
name=name, c_name=c_name(name))
-
return ret
-def gen_visit_struct(name, base, members):
- ret = generate_visit_struct_fields(name, members, base)
+def gen_visit_struct(name, base, members):
+ ret = gen_visit_struct_fields(name, base, members)
ret += mcgen('''
-void visit_type_%(name)s(Visitor *m, %(name)s **obj, const char *name, Error **errp)
+void visit_type_%(c_name)s(Visitor *m, %(c_name)s **obj, const char *name, Error **errp)
{
''',
- name=c_name(name))
+ c_name=c_name(name))
- ret += generate_visit_struct_body(name)
+ ret += gen_visit_struct_body(name)
ret += mcgen('''
}
''')
return ret
+
def gen_visit_list(name, element_type):
return mcgen('''
-void visit_type_%(name)s(Visitor *m, %(name)s **obj, const char *name, Error **errp)
+void visit_type_%(c_name)s(Visitor *m, %(c_name)s **obj, const char *name, Error **errp)
{
Error *err = NULL;
GenericList *i, **prev;
@@ -168,7 +171,7 @@ void visit_type_%(name)s(Visitor *m, %(name)s **obj, const char *name, Error **e
for (prev = (GenericList **)obj;
!err && (i = visit_next_list(m, prev, &err)) != NULL;
prev = &i) {
- %(name)s *native_i = (%(name)s *)i;
+ %(c_name)s *native_i = (%(c_name)s *)i;
visit_type_%(c_elt_type)s(m, &native_i->value, NULL, &err);
}
@@ -179,10 +182,10 @@ out:
error_propagate(errp, err);
}
''',
- name=c_name(name),
- c_elt_type=element_type.c_name())
+ c_name=c_name(name), c_elt_type=element_type.c_name())
-def generate_visit_enum(name):
+
+def gen_visit_enum(name):
return mcgen('''
void visit_type_%(c_name)s(Visitor *m, %(c_name)s *obj, const char *name, Error **errp)
@@ -192,36 +195,36 @@ void visit_type_%(c_name)s(Visitor *m, %(c_name)s *obj, const char *name, Error
''',
c_name=c_name(name), name=name)
+
def gen_visit_alternate(name, variants):
ret = mcgen('''
-void visit_type_%(name)s(Visitor *m, %(name)s **obj, const char *name, Error **errp)
+void visit_type_%(c_name)s(Visitor *m, %(c_name)s **obj, const char *name, Error **errp)
{
Error *err = NULL;
- visit_start_implicit_struct(m, (void**) obj, sizeof(%(name)s), &err);
+ visit_start_implicit_struct(m, (void**) obj, sizeof(%(c_name)s), &err);
if (err) {
goto out;
}
- visit_get_next_type(m, (int*) &(*obj)->kind, %(name)s_qtypes, name, &err);
+ visit_get_next_type(m, (int*) &(*obj)->kind, %(c_name)s_qtypes, name, &err);
if (err) {
goto out_end;
}
switch ((*obj)->kind) {
''',
- name=c_name(name))
+ c_name=c_name(name))
for var in variants.variants:
- enum_full_value = c_enum_const(variants.tag_member.type.name,
- var.name)
ret += mcgen('''
- case %(enum_full_value)s:
+ case %(case)s:
visit_type_%(c_type)s(m, &(*obj)->%(c_name)s, name, &err);
break;
''',
- enum_full_value = enum_full_value,
- c_type=var.type.c_name(),
- c_name=c_name(var.name))
+ case=c_enum_const(variants.tag_member.type.name,
+ var.name),
+ c_type=var.type.c_name(),
+ c_name=c_name(var.name))
ret += mcgen('''
default:
@@ -238,17 +241,18 @@ out:
return ret
+
def gen_visit_union(name, base, variants):
ret = ''
if base:
members = [m for m in base.members if m != variants.tag_member]
- ret += generate_visit_struct_fields(name, members)
+ ret += gen_visit_struct_fields(name, None, members)
for var in variants.variants:
# Ugly special case for simple union TODO get rid of it
if not var.simple_union_type():
- ret += generate_visit_implicit_struct(var.type)
+ ret += gen_visit_implicit_struct(var.type)
ret += mcgen('''
@@ -266,19 +270,19 @@ void visit_type_%(c_name)s(Visitor *m, %(c_name)s **obj, const char *name, Error
if base:
ret += mcgen('''
- visit_type_%(name)s_fields(m, obj, &err);
+ visit_type_%(c_name)s_fields(m, obj, &err);
if (err) {
goto out_obj;
}
''',
- name=c_name(name))
+ c_name=c_name(name))
- disc_key = variants.tag_member.name
+ tag_key = variants.tag_member.name
if not variants.tag_name:
# we pointlessly use a different key for simple unions
- disc_key = 'type'
+ tag_key = 'type'
ret += mcgen('''
- visit_type_%(disc_type)s(m, &(*obj)->%(c_name)s, "%(disc_key)s", &err);
+ visit_type_%(c_type)s(m, &(*obj)->%(c_name)s, "%(name)s", &err);
if (err) {
goto out_obj;
}
@@ -287,30 +291,36 @@ void visit_type_%(c_name)s(Visitor *m, %(c_name)s **obj, const char *name, Error
}
switch ((*obj)->%(c_name)s) {
''',
- disc_type=variants.tag_member.type.c_name(),
+ c_type=variants.tag_member.type.c_name(),
# TODO ugly special case for simple union
# Use same tag name in C as on the wire to get rid of
# it, then: c_name=c_name(variants.tag_member.name)
c_name=c_name(variants.tag_name or 'kind'),
- disc_key = disc_key)
+ name=tag_key)
for var in variants.variants:
# TODO ugly special case for simple union
simple_union_type = var.simple_union_type()
+ ret += mcgen('''
+ case %(case)s:
+''',
+ case=c_enum_const(variants.tag_member.type.name,
+ var.name))
if simple_union_type:
- fmt = 'visit_type_%(c_type)s(m, &(*obj)->%(c_name)s, "data", &err);'
+ ret += mcgen('''
+ visit_type_%(c_type)s(m, &(*obj)->%(c_name)s, "data", &err);
+''',
+ c_type=simple_union_type.c_name(),
+ c_name=c_name(var.name))
else:
- fmt = 'visit_type_implicit_%(c_type)s(m, &(*obj)->%(c_name)s, &err);'
-
- enum_full_value = c_enum_const(variants.tag_member.type.name, var.name)
+ ret += mcgen('''
+ visit_type_implicit_%(c_type)s(m, &(*obj)->%(c_name)s, &err);
+''',
+ c_type=var.type.c_name(),
+ c_name=c_name(var.name))
ret += mcgen('''
- case %(enum_full_value)s:
- ''' + fmt + '''
break;
-''',
- enum_full_value = enum_full_value,
- c_type=(simple_union_type or var.type).c_name(),
- c_name=c_name(var.name))
+''')
ret += mcgen('''
default:
@@ -331,6 +341,7 @@ out:
return ret
+
def gen_visit_decl(name, scalar=False):
c_type = c_name(name) + ' *'
if not scalar:
@@ -363,7 +374,7 @@ class QAPISchemaGenVisitVisitor(QAPISchemaVisitor):
def visit_enum_type(self, name, info, values, prefix):
self.decl += gen_visit_decl(name, scalar=True)
- self.defn += generate_visit_enum(name)
+ self.defn += gen_visit_enum(name)
def visit_array_type(self, name, info, element_type):
decl = gen_visit_decl(name)
@@ -439,7 +450,7 @@ fdef.write(mcgen('''
#include "qemu-common.h"
#include "%(prefix)sqapi-visit.h"
''',
- prefix = prefix))
+ prefix=prefix))
fdecl.write(mcgen('''
#include "qapi/visitor.h"
diff --git a/scripts/qapi.py b/scripts/qapi.py
index 0ffd02d8c2..7ac72f6a78 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -1086,9 +1086,6 @@ class QAPISchema(object):
self._def_exprs()
self.check()
- def get_exprs(self):
- return [expr_elem['expr'] for expr_elem in self.exprs]
-
def _def_entity(self, ent):
assert ent.name not in self._entity_dict
self._entity_dict[ent.name] = ent
@@ -1281,23 +1278,6 @@ class QAPISchema(object):
# Code generation helpers
#
-def parse_args(typeinfo):
- if isinstance(typeinfo, str):
- struct = find_struct(typeinfo)
- assert struct != None
- typeinfo = struct['data']
-
- for member in typeinfo:
- argname = member
- argentry = typeinfo[member]
- optional = False
- if member.startswith('*'):
- argname = member[1:]
- optional = True
- # Todo: allow argentry to be OrderedDict, for providing the
- # value of an optional argument.
- yield (argname, argentry, optional)
-
def camel_case(name):
new_name = ''
first = True
@@ -1380,67 +1360,9 @@ def c_name(name, protect=True):
return "q_" + name
return name.translate(c_name_trans)
-# Map type @name to the C typedef name for the list form.
-#
-# ['Name'] -> 'NameList', ['x-Foo'] -> 'x_FooList', ['int'] -> 'intList'
-def c_list_type(name):
- return type_name(name) + 'List'
-
-# Map type @value to the C typedef form.
-#
-# Used for converting 'type' from a 'member':'type' qapi definition
-# into the alphanumeric portion of the type for a generated C parameter,
-# as well as generated C function names. See c_type() for the rest of
-# the conversion such as adding '*' on pointer types.
-# 'int' -> 'int', '[x-Foo]' -> 'x_FooList', '__a.b_c' -> '__a_b_c'
-def type_name(value):
- if type(value) == list:
- return c_list_type(value[0])
- if value in builtin_types.keys():
- return value
- return c_name(value)
-
eatspace = '\033EATSPACE.'
pointer_suffix = ' *' + eatspace
-# Map type @name to its C type expression.
-# If @is_param, const-qualify the string type.
-#
-# This function is used for computing the full C type of 'member':'name'.
-# A special suffix is added in c_type() for pointer types, and it's
-# stripped in mcgen(). So please notice this when you check the return
-# value of c_type() outside mcgen().
-def c_type(value, is_param=False):
- if value == 'str':
- if is_param:
- return 'const char' + pointer_suffix
- return 'char' + pointer_suffix
-
- elif value == 'int':
- return 'int64_t'
- elif (value == 'int8' or value == 'int16' or value == 'int32' or
- value == 'int64' or value == 'uint8' or value == 'uint16' or
- value == 'uint32' or value == 'uint64'):
- return value + '_t'
- elif value == 'size':
- return 'uint64_t'
- elif value == 'bool':
- return 'bool'
- elif value == 'number':
- return 'double'
- elif type(value) == list:
- return c_list_type(value[0]) + pointer_suffix
- elif is_enum(value):
- return c_name(value)
- elif value == None:
- return 'void'
- elif value in events:
- return camel_case(value) + 'Event' + pointer_suffix
- else:
- # complex type name
- assert isinstance(value, str) and value != ""
- return c_name(value) + pointer_suffix
-
def genindent(count):
ret = ""
for i in range(count):
@@ -1495,60 +1417,57 @@ def guardend(name):
''',
name=guardname(name))
-def generate_enum_lookup(name, values, prefix=None):
+def gen_enum_lookup(name, values, prefix=None):
ret = mcgen('''
-const char *const %(name)s_lookup[] = {
+const char *const %(c_name)s_lookup[] = {
''',
- name=c_name(name))
+ c_name=c_name(name))
for value in values:
index = c_enum_const(name, value, prefix)
ret += mcgen('''
[%(index)s] = "%(value)s",
''',
- index = index, value = value)
+ index=index, value=value)
max_index = c_enum_const(name, 'MAX', prefix)
ret += mcgen('''
[%(max_index)s] = NULL,
};
''',
- max_index=max_index)
+ max_index=max_index)
return ret
-def generate_enum(name, values, prefix=None):
- name = c_name(name)
- lookup_decl = mcgen('''
-
-extern const char *const %(name)s_lookup[];
-''',
- name=name)
+def gen_enum(name, values, prefix=None):
+ # append automatically generated _MAX value
+ enum_values = values + ['MAX']
- enum_decl = mcgen('''
+ ret = mcgen('''
-typedef enum %(name)s {
+typedef enum %(c_name)s {
''',
- name=name)
-
- # append automatically generated _MAX value
- enum_values = values + [ 'MAX' ]
+ c_name=c_name(name))
i = 0
for value in enum_values:
- enum_full_value = c_enum_const(name, value, prefix)
- enum_decl += mcgen('''
- %(enum_full_value)s = %(i)d,
+ ret += mcgen('''
+ %(c_enum)s = %(i)d,
''',
- enum_full_value = enum_full_value,
+ c_enum=c_enum_const(name, value, prefix),
i=i)
i += 1
- enum_decl += mcgen('''
-} %(name)s;
+ ret += mcgen('''
+} %(c_name)s;
''',
- name=name)
+ c_name=c_name(name))
+
+ ret += mcgen('''
- return enum_decl + lookup_decl
+extern const char *const %(c_name)s_lookup[];
+''',
+ c_name=c_name(name))
+ return ret
#
# Common command line parsing