qapi: Another round of fixes and cleanups
-----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJV6aFGAAoJEDhwtADrkYZT8o8P/R7CZzKv6JE85xQYKtIEdgK7 zP+GiNY+ysXL/4uRzXk/Ksh3TYuRe/ptMdeXINayOoC3qG8WYuiIjIB6VTtscWGF NKj/iKUxk6APLHunLBCf/ubW1uqsOHCgmuxZJEB7aZhUpWfpYL+0pvF+n8qm67f/ RaaN2FCppTTzKrGFWjmTP1iwm2GF/ETOdlyNQ79AEjEb3n6IvjpVPuHU9ZcZhqLP CF0efVX172sbZqOlIBiDlvyCmPHsCpoRRUw4D/E5ctAxj/JkhKtv5pwsIAhKQVNj +plsYFYujhkUBT8QRZQF1oH3CQXoDD03qimCRptBSOWHTKsCPYWpSZSaE6BIzOyJ NaFcAr4x+/NCxkZ0Ef/qQZfwIH2NLb5gPpaSUpsVrJQUsx4ImKSpa8t1x+iTLqO4 QnU+pkQ6PdkFNlhj1tOvKcaOWV5wlPTtEfpEflYg0Cx173Ao3nIOPIIYTqdelcn5 1sopuADvFB61/EiMail9NS9aPPuPrnrrOtzVNyFtDZorO+sot7pWOJ24xAzylG6G jOZxMVJteq+XF0DLTdCKJiCxCdwMSrg/wNKnFMmKFGlqJIpRrd7XYPfzVX+pX/s7 gpuCc3r73WPReP1b/sjn8vQ4PBRpaQb8uK8hkh+GQjnr99cSyTZgI/M1anTh5YEC mXPB0mw60g8YA61gJSX0 =CGzi -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/armbru/tags/pull-qapi-2015-09-04' into staging qapi: Another round of fixes and cleanups # gpg: Signature made Fri 04 Sep 2015 14:48:54 BST using RSA key ID EB918653 # gpg: Good signature from "Markus Armbruster <armbru@redhat.com>" # gpg: aka "Markus Armbruster <armbru@pond.sub.org>" * remotes/armbru/tags/pull-qapi-2015-09-04: (33 commits) qapi: Generators crash when --output-dir isn't given, fix docs/qapi-code-gen.txt: Fix QAPI schema examples qapi: Simplify error reporting for array types qapi: Fix errors for non-string, non-dictionary members tests/qapi-schema: Cover non-string, non-dictionary members tests/qapi-schema: Cover two more syntax errors qapi: Drop one of two "simple union must not have base" checks qapi: Generated code cleanup qapi-commands: Drop useless initialization qapi-commands: Don't feed output of mcgen() to mcgen() again qapi-commands: Inline gen_marshal_output_call() qapi-commands: Fix gen_err_check(e) for e and e != 'local_err' qapi: Command returning anonymous type doesn't work, outlaw qapi: Fix to reject union command and event arguments qapi-tests: New tests for union, alternate command arguments tests/qapi-schema: Rename tests from data- to args- tests/qapi-schema: Restore test case for flat union base bug qapi: Document flaws in checking of names qapi: Document shortcoming with union 'data' branch qapi: Document that input visitor semantics are prone to leaks ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
b5bff7518d
|
@ -163,7 +163,7 @@ The QAPI schema definitions can be modularized using the 'include' directive:
|
|||
|
||||
The directive is evaluated recursively, and include paths are relative to the
|
||||
file using the directive. Multiple includes of the same file are
|
||||
safe. No other keys should appear in the expression, and the include
|
||||
idempotent. No other keys should appear in the expression, and the include
|
||||
value should be a string.
|
||||
|
||||
As a matter of style, it is a good idea to have all files be
|
||||
|
@ -300,7 +300,6 @@ an implicit C enum 'NameKind' is created, corresponding to the union
|
|||
the union can be named 'max', as this would collide with the implicit
|
||||
enum. The value for each branch can be of any type.
|
||||
|
||||
|
||||
A flat union definition specifies a struct as its base, and
|
||||
avoids nesting on the wire. All branches of the union must be
|
||||
complex types, and the top-level fields of the union dictionary on
|
||||
|
@ -314,7 +313,7 @@ adding a common field 'readonly', renaming the discriminator to
|
|||
something more applicable, and reducing the number of {} required on
|
||||
the wire:
|
||||
|
||||
{ 'enum': 'BlockdevDriver', 'data': [ 'raw', 'qcow2' ] }
|
||||
{ 'enum': 'BlockdevDriver', 'data': [ 'file', 'qcow2' ] }
|
||||
{ 'struct': 'BlockdevCommonOptions',
|
||||
'data': { 'driver': 'BlockdevDriver', 'readonly': 'bool' } }
|
||||
{ 'union': 'BlockdevOptions',
|
||||
|
@ -350,7 +349,7 @@ is identical on the wire to:
|
|||
{ 'struct': 'Base', 'data': { 'type': 'Enum' } }
|
||||
{ 'struct': 'Branch1', 'data': { 'data': 'str' } }
|
||||
{ 'struct': 'Branch2', 'data': { 'data': 'int' } }
|
||||
{ 'union': 'Flat': 'base': 'Base', 'discriminator': 'type',
|
||||
{ 'union': 'Flat', 'base': 'Base', 'discriminator': 'type',
|
||||
'data': { 'one': 'Branch1', 'two': 'Branch2' } }
|
||||
|
||||
|
||||
|
@ -394,7 +393,7 @@ following example objects:
|
|||
=== Commands ===
|
||||
|
||||
Usage: { 'command': STRING, '*data': COMPLEX-TYPE-NAME-OR-DICT,
|
||||
'*returns': TYPE-NAME-OR-DICT,
|
||||
'*returns': TYPE-NAME,
|
||||
'*gen': false, '*success-response': false }
|
||||
|
||||
Commands are defined by using a dictionary containing several members,
|
||||
|
@ -405,10 +404,9 @@ Client JSON Protocol command exchange.
|
|||
The 'data' argument maps to the "arguments" dictionary passed in as
|
||||
part of a Client JSON Protocol command. The 'data' member is optional
|
||||
and defaults to {} (an empty dictionary). If present, it must be the
|
||||
string name of a complex type, a one-element array containing the name
|
||||
of a complex type, or a dictionary that declares an anonymous type
|
||||
with the same semantics as a 'struct' expression, with one exception
|
||||
noted below when 'gen' is used.
|
||||
string name of a complex type, or a dictionary that declares an
|
||||
anonymous type with the same semantics as a 'struct' expression, with
|
||||
one exception noted below when 'gen' is used.
|
||||
|
||||
The 'returns' member describes what will appear in the "return" field
|
||||
of a Client JSON Protocol reply on successful completion of a command.
|
||||
|
@ -416,14 +414,13 @@ The member is optional from the command declaration; if absent, the
|
|||
"return" field will be an empty dictionary. If 'returns' is present,
|
||||
it must be the string name of a complex or built-in type, a
|
||||
one-element array containing the name of a complex or built-in type,
|
||||
or a dictionary that declares an anonymous type with the same
|
||||
semantics as a 'struct' expression, with one exception noted below
|
||||
when 'gen' is used. Although it is permitted to have the 'returns'
|
||||
member name a built-in type or an array of built-in types, any command
|
||||
that does this cannot be extended to return additional information in
|
||||
the future; thus, new commands should strongly consider returning a
|
||||
dictionary-based type or an array of dictionaries, even if the
|
||||
dictionary only contains one field at the present.
|
||||
with one exception noted below when 'gen' is used. Although it is
|
||||
permitted to have the 'returns' member name a built-in type or an
|
||||
array of built-in types, any command that does this cannot be extended
|
||||
to return additional information in the future; thus, new commands
|
||||
should strongly consider returning a dictionary-based type or an array
|
||||
of dictionaries, even if the dictionary only contains one field at the
|
||||
present.
|
||||
|
||||
All commands in Client JSON Protocol use a dictionary to report
|
||||
failure, with no way to specify that in QAPI. Where the error return
|
||||
|
@ -555,6 +552,7 @@ Example:
|
|||
qapi_dealloc_visitor_cleanup(md);
|
||||
}
|
||||
|
||||
|
||||
void qapi_free_UserDefOne(UserDefOne *obj)
|
||||
{
|
||||
QapiDeallocVisitor *md;
|
||||
|
@ -569,7 +567,6 @@ Example:
|
|||
visit_type_UserDefOne(v, &obj, NULL, NULL);
|
||||
qapi_dealloc_visitor_cleanup(md);
|
||||
}
|
||||
|
||||
$ cat qapi-generated/example-qapi-types.h
|
||||
[Uninteresting stuff omitted...]
|
||||
|
||||
|
@ -580,8 +577,7 @@ Example:
|
|||
|
||||
typedef struct UserDefOne UserDefOne;
|
||||
|
||||
typedef struct UserDefOneList
|
||||
{
|
||||
typedef struct UserDefOneList {
|
||||
union {
|
||||
UserDefOne *value;
|
||||
uint64_t padding;
|
||||
|
@ -589,10 +585,10 @@ Example:
|
|||
struct UserDefOneList *next;
|
||||
} UserDefOneList;
|
||||
|
||||
|
||||
[Functions on built-in types omitted...]
|
||||
|
||||
struct UserDefOne
|
||||
{
|
||||
struct UserDefOne {
|
||||
int64_t integer;
|
||||
char *string;
|
||||
};
|
||||
|
@ -630,6 +626,7 @@ Example:
|
|||
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;
|
||||
|
@ -743,7 +740,7 @@ Example:
|
|||
static void qmp_marshal_input_my_command(QDict *args, QObject **ret, Error **errp)
|
||||
{
|
||||
Error *local_err = NULL;
|
||||
UserDefOne *retval = NULL;
|
||||
UserDefOne *retval;
|
||||
QmpInputVisitor *mi = qmp_input_visitor_new_strict(QOBJECT(args));
|
||||
QapiDeallocVisitor *md;
|
||||
Visitor *v;
|
||||
|
@ -769,7 +766,6 @@ Example:
|
|||
v = qapi_dealloc_get_visitor(md);
|
||||
visit_type_UserDefOne(v, &arg1, "arg1", NULL);
|
||||
qapi_dealloc_visitor_cleanup(md);
|
||||
return;
|
||||
}
|
||||
|
||||
static void qmp_init_marshal(void)
|
||||
|
@ -826,7 +822,7 @@ Example:
|
|||
QDECREF(qmp);
|
||||
}
|
||||
|
||||
const char *EXAMPLE_QAPIEvent_lookup[] = {
|
||||
const char *example_QAPIEvent_lookup[] = {
|
||||
"MY_EVENT",
|
||||
NULL,
|
||||
};
|
||||
|
@ -843,11 +839,10 @@ Example:
|
|||
|
||||
void qapi_event_send_my_event(Error **errp);
|
||||
|
||||
extern const char *EXAMPLE_QAPIEvent_lookup[];
|
||||
typedef enum EXAMPLE_QAPIEvent
|
||||
{
|
||||
extern const char *example_QAPIEvent_lookup[];
|
||||
typedef enum example_QAPIEvent {
|
||||
EXAMPLE_QAPI_EVENT_MY_EVENT = 0,
|
||||
EXAMPLE_QAPI_EVENT_MAX = 1,
|
||||
} EXAMPLE_QAPIEvent;
|
||||
} example_QAPIEvent;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -27,18 +27,19 @@ def generate_command_decl(name, args, ret_type):
|
|||
%(ret_type)s qmp_%(name)s(%(args)sError **errp);
|
||||
''',
|
||||
ret_type=c_type(ret_type), name=c_name(name),
|
||||
args=arglist).strip()
|
||||
args=arglist)
|
||||
|
||||
def gen_err_check(errvar):
|
||||
if errvar:
|
||||
def gen_err_check(err):
|
||||
if not err:
|
||||
return ''
|
||||
return mcgen('''
|
||||
if (local_err) {
|
||||
if (%(err)s) {
|
||||
goto out;
|
||||
}
|
||||
''')
|
||||
return ''
|
||||
''',
|
||||
err=err)
|
||||
|
||||
def gen_sync_call(name, args, ret_type, indent=0):
|
||||
def gen_sync_call(name, args, ret_type):
|
||||
ret = ""
|
||||
arglist=""
|
||||
retval=""
|
||||
|
@ -48,41 +49,34 @@ def gen_sync_call(name, args, ret_type, indent=0):
|
|||
if optional:
|
||||
arglist += "has_%s, " % c_name(argname)
|
||||
arglist += "%s, " % (c_name(argname))
|
||||
push_indent(indent)
|
||||
push_indent()
|
||||
ret = mcgen('''
|
||||
%(retval)sqmp_%(name)s(%(args)s&local_err);
|
||||
|
||||
''',
|
||||
name=c_name(name), args=arglist, retval=retval).rstrip()
|
||||
name=c_name(name), args=arglist, retval=retval)
|
||||
if ret_type:
|
||||
ret += "\n" + gen_err_check('local_err')
|
||||
ret += "\n" + mcgen(''''
|
||||
%(marshal_output_call)s
|
||||
ret += gen_err_check('local_err')
|
||||
ret += mcgen('''
|
||||
|
||||
qmp_marshal_output_%(c_name)s(retval, ret, &local_err);
|
||||
''',
|
||||
marshal_output_call=gen_marshal_output_call(name, ret_type)).rstrip()
|
||||
pop_indent(indent)
|
||||
return ret.rstrip()
|
||||
c_name=c_name(name))
|
||||
pop_indent()
|
||||
return ret
|
||||
|
||||
|
||||
def gen_marshal_output_call(name, ret_type):
|
||||
if not ret_type:
|
||||
return ""
|
||||
return "qmp_marshal_output_%s(retval, ret, &local_err);" % c_name(name)
|
||||
|
||||
def gen_visitor_input_containers_decl(args, obj):
|
||||
def gen_visitor_input_containers_decl(args):
|
||||
ret = ""
|
||||
|
||||
push_indent()
|
||||
if len(args) > 0:
|
||||
ret += mcgen('''
|
||||
QmpInputVisitor *mi = qmp_input_visitor_new_strict(%(obj)s);
|
||||
QmpInputVisitor *mi = qmp_input_visitor_new_strict(QOBJECT(args));
|
||||
QapiDeallocVisitor *md;
|
||||
Visitor *v;
|
||||
''',
|
||||
obj=obj)
|
||||
''')
|
||||
pop_indent()
|
||||
|
||||
return ret.rstrip()
|
||||
return ret
|
||||
|
||||
def gen_visitor_input_vars_decl(args):
|
||||
ret = ""
|
||||
|
@ -105,7 +99,7 @@ bool has_%(argname)s = false;
|
|||
argname=c_name(argname), argtype=c_type(argtype))
|
||||
|
||||
pop_indent()
|
||||
return ret.rstrip()
|
||||
return ret
|
||||
|
||||
def gen_visitor_input_block(args, dealloc=False):
|
||||
ret = ""
|
||||
|
@ -159,9 +153,9 @@ visit_type_%(visitor)s(v, &%(c_name)s, "%(name)s", %(errp)s);
|
|||
qapi_dealloc_visitor_cleanup(md);
|
||||
''')
|
||||
pop_indent()
|
||||
return ret.rstrip()
|
||||
return ret
|
||||
|
||||
def gen_marshal_output(name, args, ret_type, middle_mode):
|
||||
def gen_marshal_output(name, ret_type):
|
||||
if not ret_type:
|
||||
return ""
|
||||
|
||||
|
@ -194,14 +188,14 @@ out:
|
|||
|
||||
return ret
|
||||
|
||||
def gen_marshal_input_decl(name, args, ret_type, middle_mode):
|
||||
def gen_marshal_input_decl(name, middle_mode):
|
||||
ret = 'void qmp_marshal_input_%s(QDict *args, QObject **ret, Error **errp)' % c_name(name)
|
||||
if not middle_mode:
|
||||
ret = "static " + ret
|
||||
return ret
|
||||
|
||||
def gen_marshal_input(name, args, ret_type, middle_mode):
|
||||
hdr = gen_marshal_input_decl(name, args, ret_type, middle_mode)
|
||||
hdr = gen_marshal_input_decl(name, middle_mode)
|
||||
|
||||
ret = mcgen('''
|
||||
%(header)s
|
||||
|
@ -211,36 +205,24 @@ def gen_marshal_input(name, args, ret_type, middle_mode):
|
|||
header=hdr)
|
||||
|
||||
if ret_type:
|
||||
if is_c_ptr(ret_type):
|
||||
retval = " %s retval = NULL;" % c_type(ret_type)
|
||||
else:
|
||||
retval = " %s retval;" % c_type(ret_type)
|
||||
ret += mcgen('''
|
||||
%(retval)s
|
||||
%(c_type)s retval;
|
||||
''',
|
||||
retval=retval)
|
||||
c_type=c_type(ret_type))
|
||||
|
||||
if len(args) > 0:
|
||||
ret += mcgen('''
|
||||
%(visitor_input_containers_decl)s
|
||||
%(visitor_input_vars_decl)s
|
||||
|
||||
%(visitor_input_block)s
|
||||
|
||||
''',
|
||||
visitor_input_containers_decl=gen_visitor_input_containers_decl(args, "QOBJECT(args)"),
|
||||
visitor_input_vars_decl=gen_visitor_input_vars_decl(args),
|
||||
visitor_input_block=gen_visitor_input_block(args))
|
||||
ret += gen_visitor_input_containers_decl(args)
|
||||
ret += gen_visitor_input_vars_decl(args) + '\n'
|
||||
ret += gen_visitor_input_block(args) + '\n'
|
||||
else:
|
||||
ret += mcgen('''
|
||||
|
||||
(void)args;
|
||||
|
||||
''')
|
||||
|
||||
ret += mcgen('''
|
||||
%(sync_call)s
|
||||
''',
|
||||
sync_call=gen_sync_call(name, args, ret_type, indent=4))
|
||||
ret += gen_sync_call(name, args, ret_type)
|
||||
|
||||
if re.search('^ *goto out\\;', ret, re.MULTILINE):
|
||||
ret += mcgen('''
|
||||
|
||||
|
@ -248,11 +230,11 @@ out:
|
|||
''')
|
||||
ret += mcgen('''
|
||||
error_propagate(errp, local_err);
|
||||
%(visitor_input_block_cleanup)s
|
||||
''')
|
||||
ret += gen_visitor_input_block(args, dealloc=True)
|
||||
ret += mcgen('''
|
||||
}
|
||||
''',
|
||||
visitor_input_block_cleanup=gen_visitor_input_block(args,
|
||||
dealloc=True))
|
||||
''')
|
||||
return ret
|
||||
|
||||
def gen_registry(commands):
|
||||
|
@ -272,12 +254,13 @@ qmp_register_command("%(name)s", qmp_marshal_input_%(c_name)s, %(opts)s);
|
|||
ret = mcgen('''
|
||||
static void qmp_init_marshal(void)
|
||||
{
|
||||
%(registry)s
|
||||
''')
|
||||
ret += registry
|
||||
ret += mcgen('''
|
||||
}
|
||||
|
||||
qapi_init(qmp_init_marshal);
|
||||
''',
|
||||
registry=registry.rstrip())
|
||||
''')
|
||||
return ret
|
||||
|
||||
middle_mode = False
|
||||
|
@ -357,14 +340,14 @@ for cmd in commands:
|
|||
arglist = cmd['data']
|
||||
if cmd.has_key('returns'):
|
||||
ret_type = cmd['returns']
|
||||
ret = generate_command_decl(cmd['command'], arglist, ret_type) + "\n"
|
||||
ret = generate_command_decl(cmd['command'], arglist, ret_type)
|
||||
fdecl.write(ret)
|
||||
if ret_type:
|
||||
ret = gen_marshal_output(cmd['command'], arglist, ret_type, middle_mode) + "\n"
|
||||
ret = gen_marshal_output(cmd['command'], ret_type) + "\n"
|
||||
fdef.write(ret)
|
||||
|
||||
if middle_mode:
|
||||
fdecl.write('%s;\n' % gen_marshal_input_decl(cmd['command'], arglist, ret_type, middle_mode))
|
||||
fdecl.write('%s;\n' % gen_marshal_input_decl(cmd['command'], middle_mode))
|
||||
|
||||
ret = gen_marshal_input(cmd['command'], arglist, ret_type, middle_mode) + "\n"
|
||||
fdef.write(ret)
|
||||
|
|
|
@ -167,8 +167,7 @@ extern const char *%(event_enum_name)s_lookup[];
|
|||
event_enum_name = event_enum_name)
|
||||
|
||||
enum_decl = mcgen('''
|
||||
typedef enum %(event_enum_name)s
|
||||
{
|
||||
typedef enum %(event_enum_name)s {
|
||||
''',
|
||||
event_enum_name = event_enum_name)
|
||||
|
||||
|
@ -199,7 +198,6 @@ const char *%(event_enum_name)s_lookup[] = {
|
|||
''',
|
||||
event_enum_name = event_enum_name)
|
||||
|
||||
i = 0
|
||||
for string in event_enum_strings:
|
||||
ret += mcgen('''
|
||||
"%(string)s",
|
||||
|
@ -267,7 +265,7 @@ fdecl.write(mcgen('''
|
|||
|
||||
exprs = parse_schema(input_file)
|
||||
|
||||
event_enum_name = prefix.upper().replace('-', '_') + "QAPIEvent"
|
||||
event_enum_name = c_name(prefix + "QAPIEvent", protect=False)
|
||||
event_enum_values = []
|
||||
event_enum_strings = []
|
||||
|
||||
|
|
|
@ -15,8 +15,7 @@ from qapi import *
|
|||
def generate_fwd_builtin(name):
|
||||
return mcgen('''
|
||||
|
||||
typedef struct %(name)sList
|
||||
{
|
||||
typedef struct %(name)sList {
|
||||
union {
|
||||
%(type)s value;
|
||||
uint64_t padding;
|
||||
|
@ -32,8 +31,7 @@ def generate_fwd_struct(name):
|
|||
|
||||
typedef struct %(name)s %(name)s;
|
||||
|
||||
typedef struct %(name)sList
|
||||
{
|
||||
typedef struct %(name)sList {
|
||||
union {
|
||||
%(name)s *value;
|
||||
uint64_t padding;
|
||||
|
@ -45,8 +43,8 @@ typedef struct %(name)sList
|
|||
|
||||
def generate_fwd_enum_struct(name):
|
||||
return mcgen('''
|
||||
typedef struct %(name)sList
|
||||
{
|
||||
|
||||
typedef struct %(name)sList {
|
||||
union {
|
||||
%(name)s value;
|
||||
uint64_t padding;
|
||||
|
@ -79,8 +77,8 @@ def generate_struct(expr):
|
|||
base = expr.get('base')
|
||||
|
||||
ret = mcgen('''
|
||||
struct %(name)s
|
||||
{
|
||||
|
||||
struct %(name)s {
|
||||
''',
|
||||
name=c_name(structname))
|
||||
|
||||
|
@ -105,10 +103,10 @@ struct %(name)s
|
|||
|
||||
def generate_enum_lookup(name, values):
|
||||
ret = mcgen('''
|
||||
const char * const %(name)s_lookup[] = {
|
||||
|
||||
const char *const %(name)s_lookup[] = {
|
||||
''',
|
||||
name=c_name(name))
|
||||
i = 0
|
||||
for value in values:
|
||||
index = c_enum_const(name, value)
|
||||
ret += mcgen('''
|
||||
|
@ -120,7 +118,6 @@ const char * const %(name)s_lookup[] = {
|
|||
ret += mcgen('''
|
||||
[%(max_index)s] = NULL,
|
||||
};
|
||||
|
||||
''',
|
||||
max_index=max_index)
|
||||
return ret
|
||||
|
@ -128,13 +125,14 @@ const char * const %(name)s_lookup[] = {
|
|||
def generate_enum(name, values):
|
||||
name = c_name(name)
|
||||
lookup_decl = mcgen('''
|
||||
extern const char * const %(name)s_lookup[];
|
||||
|
||||
extern const char *const %(name)s_lookup[];
|
||||
''',
|
||||
name=name)
|
||||
|
||||
enum_decl = mcgen('''
|
||||
typedef enum %(name)s
|
||||
{
|
||||
|
||||
typedef enum %(name)s {
|
||||
''',
|
||||
name=name)
|
||||
|
||||
|
@ -156,7 +154,7 @@ typedef enum %(name)s
|
|||
''',
|
||||
name=name)
|
||||
|
||||
return lookup_decl + enum_decl
|
||||
return enum_decl + lookup_decl
|
||||
|
||||
def generate_alternate_qtypes(expr):
|
||||
|
||||
|
@ -164,6 +162,7 @@ def generate_alternate_qtypes(expr):
|
|||
members = expr['data']
|
||||
|
||||
ret = mcgen('''
|
||||
|
||||
const int %(name)s_qtypes[QTYPE_MAX] = {
|
||||
''',
|
||||
name=c_name(name))
|
||||
|
@ -199,14 +198,40 @@ def generate_union(expr, meta):
|
|||
discriminator_type_name = '%sKind' % (name)
|
||||
|
||||
ret = mcgen('''
|
||||
struct %(name)s
|
||||
{
|
||||
|
||||
struct %(name)s {
|
||||
''',
|
||||
name=name)
|
||||
if base:
|
||||
ret += mcgen('''
|
||||
/* Members inherited from %(c_name)s: */
|
||||
''',
|
||||
c_name=c_name(base))
|
||||
base_fields = find_struct(base)['data']
|
||||
ret += generate_struct_fields(base_fields)
|
||||
ret += mcgen('''
|
||||
/* Own members: */
|
||||
''')
|
||||
else:
|
||||
assert not discriminator
|
||||
ret += mcgen('''
|
||||
%(discriminator_type_name)s kind;
|
||||
union {
|
||||
''',
|
||||
discriminator_type_name=c_name(discriminator_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
|
||||
# whether to bypass the switch statement if visiting the discriminator
|
||||
# failed; but since we 0-initialize structs, and cannot tell what
|
||||
# branch of the union is in use if the discriminator is invalid, there
|
||||
# should not be any data leaks even without a data pointer. Or, if
|
||||
# 'data' is merely added to guarantee we don't have an empty union,
|
||||
# shouldn't we enforce that at .json parse time?
|
||||
ret += mcgen('''
|
||||
union { /* union tag is @%(c_name)s */
|
||||
void *data;
|
||||
''',
|
||||
name=name,
|
||||
discriminator_type_name=c_name(discriminator_type_name))
|
||||
c_name=c_name(discriminator or 'kind'))
|
||||
|
||||
for key in typeinfo:
|
||||
ret += mcgen('''
|
||||
|
@ -217,17 +242,6 @@ struct %(name)s
|
|||
|
||||
ret += mcgen('''
|
||||
};
|
||||
''')
|
||||
|
||||
if base:
|
||||
assert discriminator
|
||||
base_fields = find_struct(base)['data'].copy()
|
||||
del base_fields[discriminator]
|
||||
ret += generate_struct_fields(base_fields)
|
||||
else:
|
||||
assert not discriminator
|
||||
|
||||
ret += mcgen('''
|
||||
};
|
||||
''')
|
||||
if meta == 'alternate':
|
||||
|
@ -314,14 +328,12 @@ fdef.write(mcgen('''
|
|||
#include "qapi/dealloc-visitor.h"
|
||||
#include "%(prefix)sqapi-types.h"
|
||||
#include "%(prefix)sqapi-visit.h"
|
||||
|
||||
''',
|
||||
prefix=prefix))
|
||||
|
||||
fdecl.write(mcgen('''
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
'''))
|
||||
|
||||
exprs = parse_schema(input_file)
|
||||
|
@ -332,22 +344,22 @@ for typename in builtin_types.keys():
|
|||
fdecl.write(guardend("QAPI_TYPES_BUILTIN_STRUCT_DECL"))
|
||||
|
||||
for expr in exprs:
|
||||
ret = "\n"
|
||||
ret = ""
|
||||
if expr.has_key('struct'):
|
||||
ret += generate_fwd_struct(expr['struct'])
|
||||
elif expr.has_key('enum'):
|
||||
ret += generate_enum(expr['enum'], expr['data']) + "\n"
|
||||
ret += generate_enum(expr['enum'], expr['data'])
|
||||
ret += generate_fwd_enum_struct(expr['enum'])
|
||||
fdef.write(generate_enum_lookup(expr['enum'], expr['data']))
|
||||
elif expr.has_key('union'):
|
||||
ret += generate_fwd_struct(expr['union']) + "\n"
|
||||
ret += generate_fwd_struct(expr['union'])
|
||||
enum_define = discriminator_find_enum_define(expr)
|
||||
if not enum_define:
|
||||
ret += generate_enum('%sKind' % expr['union'], expr['data'].keys())
|
||||
fdef.write(generate_enum_lookup('%sKind' % expr['union'],
|
||||
expr['data'].keys()))
|
||||
elif expr.has_key('alternate'):
|
||||
ret += generate_fwd_struct(expr['alternate']) + "\n"
|
||||
ret += generate_fwd_struct(expr['alternate'])
|
||||
ret += generate_enum('%sKind' % expr['alternate'], expr['data'].keys())
|
||||
fdef.write(generate_enum_lookup('%sKind' % expr['alternate'],
|
||||
expr['data'].keys()))
|
||||
|
@ -367,34 +379,32 @@ fdecl.write(guardend("QAPI_TYPES_BUILTIN_CLEANUP_DECL"))
|
|||
# have the functions defined, so we use -b option to provide control
|
||||
# over these cases
|
||||
if do_builtins:
|
||||
fdef.write(guardstart("QAPI_TYPES_BUILTIN_CLEANUP_DEF"))
|
||||
for typename in builtin_types.keys():
|
||||
fdef.write(generate_type_cleanup(typename + "List"))
|
||||
fdef.write(guardend("QAPI_TYPES_BUILTIN_CLEANUP_DEF"))
|
||||
|
||||
for expr in exprs:
|
||||
ret = "\n"
|
||||
ret = ""
|
||||
if expr.has_key('struct'):
|
||||
ret += generate_struct(expr) + "\n"
|
||||
ret += generate_type_cleanup_decl(expr['struct'] + "List")
|
||||
fdef.write(generate_type_cleanup(expr['struct'] + "List") + "\n")
|
||||
fdef.write(generate_type_cleanup(expr['struct'] + "List"))
|
||||
ret += generate_type_cleanup_decl(expr['struct'])
|
||||
fdef.write(generate_type_cleanup(expr['struct']) + "\n")
|
||||
fdef.write(generate_type_cleanup(expr['struct']))
|
||||
elif expr.has_key('union'):
|
||||
ret += generate_union(expr, 'union')
|
||||
ret += generate_union(expr, 'union') + "\n"
|
||||
ret += generate_type_cleanup_decl(expr['union'] + "List")
|
||||
fdef.write(generate_type_cleanup(expr['union'] + "List") + "\n")
|
||||
fdef.write(generate_type_cleanup(expr['union'] + "List"))
|
||||
ret += generate_type_cleanup_decl(expr['union'])
|
||||
fdef.write(generate_type_cleanup(expr['union']) + "\n")
|
||||
fdef.write(generate_type_cleanup(expr['union']))
|
||||
elif expr.has_key('alternate'):
|
||||
ret += generate_union(expr, 'alternate')
|
||||
ret += generate_union(expr, 'alternate') + "\n"
|
||||
ret += generate_type_cleanup_decl(expr['alternate'] + "List")
|
||||
fdef.write(generate_type_cleanup(expr['alternate'] + "List") + "\n")
|
||||
fdef.write(generate_type_cleanup(expr['alternate'] + "List"))
|
||||
ret += generate_type_cleanup_decl(expr['alternate'])
|
||||
fdef.write(generate_type_cleanup(expr['alternate']) + "\n")
|
||||
fdef.write(generate_type_cleanup(expr['alternate']))
|
||||
elif expr.has_key('enum'):
|
||||
ret += generate_type_cleanup_decl(expr['enum'] + "List")
|
||||
fdef.write(generate_type_cleanup(expr['enum'] + "List") + "\n")
|
||||
ret += "\n" + generate_type_cleanup_decl(expr['enum'] + "List")
|
||||
fdef.write(generate_type_cleanup(expr['enum'] + "List"))
|
||||
else:
|
||||
continue
|
||||
fdecl.write(ret)
|
||||
|
|
|
@ -16,14 +16,23 @@ from ordereddict import OrderedDict
|
|||
from qapi import *
|
||||
import re
|
||||
|
||||
implicit_structs = []
|
||||
implicit_structs_seen = set()
|
||||
struct_fields_seen = set()
|
||||
|
||||
def generate_visit_implicit_struct(type):
|
||||
global implicit_structs
|
||||
if type in implicit_structs:
|
||||
if type in implicit_structs_seen:
|
||||
return ''
|
||||
implicit_structs.append(type)
|
||||
return mcgen('''
|
||||
implicit_structs_seen.add(type)
|
||||
ret = ''
|
||||
if type 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_name(type))
|
||||
|
||||
ret += mcgen('''
|
||||
|
||||
static void visit_type_implicit_%(c_type)s(Visitor *m, %(c_type)s **obj, Error **errp)
|
||||
{
|
||||
|
@ -38,9 +47,11 @@ static void visit_type_implicit_%(c_type)s(Visitor *m, %(c_type)s **obj, Error *
|
|||
}
|
||||
''',
|
||||
c_type=type_name(type))
|
||||
return ret
|
||||
|
||||
def generate_visit_struct_fields(name, members, base = None):
|
||||
substructs = []
|
||||
struct_fields_seen.add(name)
|
||||
|
||||
ret = ''
|
||||
|
||||
if base:
|
||||
|
@ -51,6 +62,7 @@ def generate_visit_struct_fields(name, members, base = None):
|
|||
static void visit_type_%(name)s_fields(Visitor *m, %(name)s **obj, Error **errp)
|
||||
{
|
||||
Error *err = NULL;
|
||||
|
||||
''',
|
||||
name=c_name(name))
|
||||
push_indent()
|
||||
|
@ -103,7 +115,11 @@ out:
|
|||
return ret
|
||||
|
||||
|
||||
def generate_visit_struct_body(name, members):
|
||||
def generate_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
|
||||
# call qapi_free_FOO() to avoid a memory leak of the partial FOO.
|
||||
ret = mcgen('''
|
||||
Error *err = NULL;
|
||||
|
||||
|
@ -135,14 +151,14 @@ void visit_type_%(name)s(Visitor *m, %(name)s **obj, const char *name, Error **e
|
|||
''',
|
||||
name=c_name(name))
|
||||
|
||||
ret += generate_visit_struct_body(name, members)
|
||||
ret += generate_visit_struct_body(name)
|
||||
|
||||
ret += mcgen('''
|
||||
}
|
||||
''')
|
||||
return ret
|
||||
|
||||
def generate_visit_list(name, members):
|
||||
def generate_visit_list(name):
|
||||
return mcgen('''
|
||||
|
||||
void visit_type_%(name)sList(Visitor *m, %(name)sList **obj, const char *name, Error **errp)
|
||||
|
@ -171,15 +187,15 @@ out:
|
|||
''',
|
||||
name=type_name(name))
|
||||
|
||||
def generate_visit_enum(name, members):
|
||||
def generate_visit_enum(name):
|
||||
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)
|
||||
{
|
||||
visit_type_enum(m, (int *)obj, %(name)s_lookup, "%(name)s", name, errp);
|
||||
visit_type_enum(m, (int *)obj, %(c_name)s_lookup, "%(name)s", name, errp);
|
||||
}
|
||||
''',
|
||||
name=c_name(name))
|
||||
c_name=c_name(name), name=name)
|
||||
|
||||
def generate_visit_alternate(name, members):
|
||||
ret = mcgen('''
|
||||
|
@ -252,7 +268,7 @@ def generate_visit_union(expr):
|
|||
else:
|
||||
# There will always be a discriminator in the C switch code, by default
|
||||
# it is an enum type generated silently
|
||||
ret = generate_visit_enum(name + 'Kind', members.keys())
|
||||
ret = generate_visit_enum(name + 'Kind')
|
||||
disc_type = c_name(name) + 'Kind'
|
||||
|
||||
if base:
|
||||
|
@ -267,17 +283,17 @@ def generate_visit_union(expr):
|
|||
|
||||
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_struct(m, (void **)obj, "%(name)s", name, sizeof(%(name)s), &err);
|
||||
visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(c_name)s), &err);
|
||||
if (err) {
|
||||
goto out;
|
||||
}
|
||||
if (*obj) {
|
||||
''',
|
||||
name=c_name(name))
|
||||
c_name=c_name(name), name=name)
|
||||
|
||||
if base:
|
||||
ret += mcgen('''
|
||||
|
@ -289,20 +305,23 @@ void visit_type_%(name)s(Visitor *m, %(name)s **obj, const char *name, Error **e
|
|||
name=c_name(name))
|
||||
|
||||
if not discriminator:
|
||||
tag = 'kind'
|
||||
disc_key = "type"
|
||||
else:
|
||||
tag = discriminator
|
||||
disc_key = discriminator
|
||||
ret += mcgen('''
|
||||
visit_type_%(disc_type)s(m, &(*obj)->kind, "%(disc_key)s", &err);
|
||||
visit_type_%(disc_type)s(m, &(*obj)->%(c_tag)s, "%(disc_key)s", &err);
|
||||
if (err) {
|
||||
goto out_obj;
|
||||
}
|
||||
if (!visit_start_union(m, !!(*obj)->data, &err) || err) {
|
||||
goto out_obj;
|
||||
}
|
||||
switch ((*obj)->kind) {
|
||||
switch ((*obj)->%(c_tag)s) {
|
||||
''',
|
||||
disc_type = disc_type,
|
||||
c_tag=c_name(tag),
|
||||
disc_key = disc_key)
|
||||
|
||||
for key in members:
|
||||
|
@ -340,7 +359,7 @@ out:
|
|||
|
||||
return ret
|
||||
|
||||
def generate_declaration(name, members, builtin_type=False):
|
||||
def generate_declaration(name, builtin_type=False):
|
||||
ret = ""
|
||||
if not builtin_type:
|
||||
name = c_name(name)
|
||||
|
@ -357,7 +376,7 @@ void visit_type_%(name)sList(Visitor *m, %(name)sList **obj, const char *name, E
|
|||
|
||||
return ret
|
||||
|
||||
def generate_enum_declaration(name, members):
|
||||
def generate_enum_declaration(name):
|
||||
ret = mcgen('''
|
||||
void visit_type_%(name)sList(Visitor *m, %(name)sList **obj, const char *name, Error **errp);
|
||||
''',
|
||||
|
@ -365,7 +384,7 @@ void visit_type_%(name)sList(Visitor *m, %(name)sList **obj, const char *name, E
|
|||
|
||||
return ret
|
||||
|
||||
def generate_decl_enum(name, members):
|
||||
def generate_decl_enum(name):
|
||||
return mcgen('''
|
||||
|
||||
void visit_type_%(name)s(Visitor *m, %(name)s *obj, const char *name, Error **errp);
|
||||
|
@ -433,7 +452,7 @@ exprs = parse_schema(input_file)
|
|||
# for built-in types in our header files and simply guard them
|
||||
fdecl.write(guardstart("QAPI_VISIT_BUILTIN_VISITOR_DECL"))
|
||||
for typename in builtin_types.keys():
|
||||
fdecl.write(generate_declaration(typename, None, builtin_type=True))
|
||||
fdecl.write(generate_declaration(typename, builtin_type=True))
|
||||
fdecl.write(guardend("QAPI_VISIT_BUILTIN_VISITOR_DECL"))
|
||||
|
||||
# ...this doesn't work for cases where we link in multiple objects that
|
||||
|
@ -441,44 +460,42 @@ fdecl.write(guardend("QAPI_VISIT_BUILTIN_VISITOR_DECL"))
|
|||
# over these cases
|
||||
if do_builtins:
|
||||
for typename in builtin_types.keys():
|
||||
fdef.write(generate_visit_list(typename, None))
|
||||
fdef.write(generate_visit_list(typename))
|
||||
|
||||
for expr in exprs:
|
||||
if expr.has_key('struct'):
|
||||
ret = generate_visit_struct(expr)
|
||||
ret += generate_visit_list(expr['struct'], expr['data'])
|
||||
ret += generate_visit_list(expr['struct'])
|
||||
fdef.write(ret)
|
||||
|
||||
ret = generate_declaration(expr['struct'], expr['data'])
|
||||
ret = generate_declaration(expr['struct'])
|
||||
fdecl.write(ret)
|
||||
elif expr.has_key('union'):
|
||||
ret = generate_visit_union(expr)
|
||||
ret += generate_visit_list(expr['union'], expr['data'])
|
||||
ret += generate_visit_list(expr['union'])
|
||||
fdef.write(ret)
|
||||
|
||||
enum_define = discriminator_find_enum_define(expr)
|
||||
ret = ""
|
||||
if not enum_define:
|
||||
ret = generate_decl_enum('%sKind' % expr['union'],
|
||||
expr['data'].keys())
|
||||
ret += generate_declaration(expr['union'], expr['data'])
|
||||
ret = generate_decl_enum('%sKind' % expr['union'])
|
||||
ret += generate_declaration(expr['union'])
|
||||
fdecl.write(ret)
|
||||
elif expr.has_key('alternate'):
|
||||
ret = generate_visit_alternate(expr['alternate'], expr['data'])
|
||||
ret += generate_visit_list(expr['alternate'], expr['data'])
|
||||
ret += generate_visit_list(expr['alternate'])
|
||||
fdef.write(ret)
|
||||
|
||||
ret = generate_decl_enum('%sKind' % expr['alternate'],
|
||||
expr['data'].keys())
|
||||
ret += generate_declaration(expr['alternate'], expr['data'])
|
||||
ret = generate_decl_enum('%sKind' % expr['alternate'])
|
||||
ret += generate_declaration(expr['alternate'])
|
||||
fdecl.write(ret)
|
||||
elif expr.has_key('enum'):
|
||||
ret = generate_visit_list(expr['enum'], expr['data'])
|
||||
ret += generate_visit_enum(expr['enum'], expr['data'])
|
||||
ret = generate_visit_list(expr['enum'])
|
||||
ret += generate_visit_enum(expr['enum'])
|
||||
fdef.write(ret)
|
||||
|
||||
ret = generate_decl_enum(expr['enum'], expr['data'])
|
||||
ret += generate_enum_declaration(expr['enum'], expr['data'])
|
||||
ret = generate_decl_enum(expr['enum'])
|
||||
ret += generate_enum_declaration(expr['enum'])
|
||||
fdecl.write(ret)
|
||||
|
||||
close_output(fdef, fdecl)
|
||||
|
|
|
@ -341,6 +341,8 @@ def discriminator_find_enum_define(expr):
|
|||
|
||||
return find_enum(discriminator_type)
|
||||
|
||||
# FIXME should enforce "other than downstream extensions [...], all
|
||||
# names should begin with a letter".
|
||||
valid_name = re.compile('^[a-zA-Z_][a-zA-Z0-9_.-]*$')
|
||||
def check_name(expr_info, source, name, allow_optional = False,
|
||||
enum_member = False):
|
||||
|
@ -367,6 +369,8 @@ def check_name(expr_info, source, name, allow_optional = False,
|
|||
def add_name(name, info, meta, implicit = False):
|
||||
global all_names
|
||||
check_name(info, "'%s'" % meta, name)
|
||||
# FIXME should reject names that differ only in '_' vs. '.'
|
||||
# vs. '-', because they're liable to clash in generated C.
|
||||
if name in all_names:
|
||||
raise QAPIExprError(info,
|
||||
"%s '%s' is already defined"
|
||||
|
@ -422,7 +426,6 @@ def check_type(expr_info, source, value, allow_array = False,
|
|||
allow_dict = False, allow_optional = False,
|
||||
allow_star = False, allow_metas = []):
|
||||
global all_names
|
||||
orig_value = value
|
||||
|
||||
if value is None:
|
||||
return
|
||||
|
@ -440,7 +443,6 @@ def check_type(expr_info, source, value, allow_array = False,
|
|||
"%s: array type must contain single type name"
|
||||
% source)
|
||||
value = value[0]
|
||||
orig_value = "array of %s" %value
|
||||
|
||||
# Check if type name for value is okay
|
||||
if isinstance(value, str):
|
||||
|
@ -451,20 +453,22 @@ def check_type(expr_info, source, value, allow_array = False,
|
|||
if not value in all_names:
|
||||
raise QAPIExprError(expr_info,
|
||||
"%s uses unknown type '%s'"
|
||||
% (source, orig_value))
|
||||
% (source, value))
|
||||
if not all_names[value] in allow_metas:
|
||||
raise QAPIExprError(expr_info,
|
||||
"%s cannot use %s type '%s'"
|
||||
% (source, all_names[value], orig_value))
|
||||
% (source, all_names[value], value))
|
||||
return
|
||||
|
||||
# value is a dictionary, check that each member is okay
|
||||
if not isinstance(value, OrderedDict):
|
||||
raise QAPIExprError(expr_info,
|
||||
"%s should be a dictionary" % source)
|
||||
if not allow_dict:
|
||||
raise QAPIExprError(expr_info,
|
||||
"%s should be a type name" % source)
|
||||
|
||||
if not isinstance(value, OrderedDict):
|
||||
raise QAPIExprError(expr_info,
|
||||
"%s should be a dictionary or type name" % source)
|
||||
|
||||
# value is a dictionary, check that each member is okay
|
||||
for (key, arg) in value.items():
|
||||
check_name(expr_info, "Member of %s" % source, key,
|
||||
allow_optional=allow_optional)
|
||||
|
@ -495,26 +499,25 @@ def check_command(expr, expr_info):
|
|||
|
||||
check_type(expr_info, "'data' for command '%s'" % name,
|
||||
expr.get('data'), allow_dict=True, allow_optional=True,
|
||||
allow_metas=['union', 'struct'], allow_star=allow_star)
|
||||
allow_metas=['struct'], allow_star=allow_star)
|
||||
returns_meta = ['union', 'struct']
|
||||
if name in returns_whitelist:
|
||||
returns_meta += ['built-in', 'alternate', 'enum']
|
||||
check_type(expr_info, "'returns' for command '%s'" % name,
|
||||
expr.get('returns'), allow_array=True, allow_dict=True,
|
||||
expr.get('returns'), allow_array=True,
|
||||
allow_optional=True, allow_metas=returns_meta,
|
||||
allow_star=allow_star)
|
||||
|
||||
def check_event(expr, expr_info):
|
||||
global events
|
||||
name = expr['event']
|
||||
params = expr.get('data')
|
||||
|
||||
if name.upper() == 'MAX':
|
||||
raise QAPIExprError(expr_info, "Event name 'MAX' cannot be created")
|
||||
events.append(name)
|
||||
check_type(expr_info, "'data' for event '%s'" % name,
|
||||
expr.get('data'), allow_dict=True, allow_optional=True,
|
||||
allow_metas=['union', 'struct'])
|
||||
allow_metas=['struct'])
|
||||
|
||||
def check_union(expr, expr_info):
|
||||
name = expr['union']
|
||||
|
@ -523,14 +526,6 @@ def check_union(expr, expr_info):
|
|||
members = expr['data']
|
||||
values = { 'MAX': '(automatic)' }
|
||||
|
||||
# If the object has a member 'base', its value must name a struct,
|
||||
# and there must be a discriminator.
|
||||
if base is not None:
|
||||
if discriminator is None:
|
||||
raise QAPIExprError(expr_info,
|
||||
"Union '%s' requires a discriminator to go "
|
||||
"along with base" %name)
|
||||
|
||||
# Two types of unions, determined by discriminator.
|
||||
|
||||
# With no discriminator it is a simple union.
|
||||
|
@ -943,24 +938,24 @@ def pop_indent(indent_amount=4):
|
|||
global indent_level
|
||||
indent_level -= indent_amount
|
||||
|
||||
# Generate @code with @kwds interpolated.
|
||||
# Obey indent_level, and strip eatspace.
|
||||
def cgen(code, **kwds):
|
||||
raw = code % kwds
|
||||
if indent_level:
|
||||
indent = genindent(indent_level)
|
||||
lines = code.split('\n')
|
||||
lines = map(lambda x: indent + x, lines)
|
||||
return '\n'.join(lines) % kwds + '\n'
|
||||
|
||||
def mcgen(code, **kwds):
|
||||
raw = cgen('\n'.join(code.split('\n')[1:-1]), **kwds)
|
||||
raw = re.subn("^.", indent + r'\g<0>', raw, 0, re.MULTILINE)
|
||||
raw = raw[0]
|
||||
return re.sub(re.escape(eatspace) + ' *', '', raw)
|
||||
|
||||
def basename(filename):
|
||||
return filename.split("/")[-1]
|
||||
def mcgen(code, **kwds):
|
||||
if code[0] == '\n':
|
||||
code = code[1:]
|
||||
return cgen(code, **kwds)
|
||||
|
||||
|
||||
def guardname(filename):
|
||||
guard = basename(filename).rsplit(".", 1)[0]
|
||||
for substr in [".", " ", "-"]:
|
||||
guard = guard.replace(substr, "_")
|
||||
return guard.upper() + '_H'
|
||||
return c_name(filename, protect=False).upper()
|
||||
|
||||
def guardstart(name):
|
||||
return mcgen('''
|
||||
|
@ -1003,6 +998,12 @@ def parse_command_line(extra_options = "", extra_long_options = []):
|
|||
for oa in opts:
|
||||
o, a = oa
|
||||
if o in ("-p", "--prefix"):
|
||||
match = re.match('([A-Za-z_.-][A-Za-z0-9_.-]*)?', a)
|
||||
if match.end() != len(a):
|
||||
print >>sys.stderr, \
|
||||
"%s: 'funny character '%s' in argument of --prefix" \
|
||||
% (sys.argv[0], a[match.end()])
|
||||
sys.exit(1)
|
||||
prefix = a
|
||||
elif o in ("-o", "--output-dir"):
|
||||
output_dir = a + "/"
|
||||
|
@ -1030,9 +1031,11 @@ def parse_command_line(extra_options = "", extra_long_options = []):
|
|||
|
||||
def open_output(output_dir, do_c, do_h, prefix, c_file, h_file,
|
||||
c_comment, h_comment):
|
||||
guard = guardname(prefix + h_file)
|
||||
c_file = output_dir + prefix + c_file
|
||||
h_file = output_dir + prefix + h_file
|
||||
|
||||
if output_dir:
|
||||
try:
|
||||
os.makedirs(output_dir)
|
||||
except os.error, e:
|
||||
|
@ -1062,7 +1065,7 @@ def open_output(output_dir, do_c, do_h, prefix, c_file, h_file,
|
|||
#define %(guard)s
|
||||
|
||||
''',
|
||||
comment = h_comment, guard = guardname(h_file)))
|
||||
comment = h_comment, guard = guard))
|
||||
|
||||
return (fdef, fdecl)
|
||||
|
||||
|
|
|
@ -229,13 +229,17 @@ check-qapi-schema-y := $(addprefix tests/qapi-schema/, \
|
|||
redefined-type.json redefined-command.json redefined-builtin.json \
|
||||
redefined-event.json command-int.json bad-data.json event-max.json \
|
||||
type-bypass.json type-bypass-no-gen.json type-bypass-bad-gen.json \
|
||||
data-array-empty.json data-array-unknown.json data-int.json \
|
||||
data-unknown.json data-member-unknown.json data-member-array.json \
|
||||
data-member-array-bad.json returns-array-bad.json returns-int.json \
|
||||
args-invalid.json \
|
||||
args-array-empty.json args-array-unknown.json args-int.json \
|
||||
args-unknown.json args-member-unknown.json args-member-array.json \
|
||||
args-member-array-bad.json args-alternate.json args-union.json \
|
||||
returns-array-bad.json returns-int.json returns-dict.json \
|
||||
returns-unknown.json returns-alternate.json returns-whitelist.json \
|
||||
missing-colon.json missing-comma-list.json missing-comma-object.json \
|
||||
nested-struct-data.json nested-struct-returns.json non-objects.json \
|
||||
struct-data-invalid.json struct-member-invalid.json \
|
||||
nested-struct-data.json non-objects.json \
|
||||
qapi-schema-test.json quoted-structural-chars.json \
|
||||
leading-comma-list.json leading-comma-object.json \
|
||||
trailing-comma-list.json trailing-comma-object.json \
|
||||
unclosed-list.json unclosed-object.json unclosed-string.json \
|
||||
duplicate-key.json union-invalid-base.json union-bad-branch.json \
|
||||
|
|
1
tests/qapi-schema/args-alternate.err
Normal file
1
tests/qapi-schema/args-alternate.err
Normal file
|
@ -0,0 +1 @@
|
|||
tests/qapi-schema/args-alternate.json:3: 'data' for command 'oops' cannot use alternate type 'Alt'
|
3
tests/qapi-schema/args-alternate.json
Normal file
3
tests/qapi-schema/args-alternate.json
Normal file
|
@ -0,0 +1,3 @@
|
|||
# we do not allow alternate arguments
|
||||
{ 'alternate': 'Alt', 'data': { 'case1': 'int', 'case2': 'str' } }
|
||||
{ 'command': 'oops', 'data': 'Alt' }
|
|
@ -1 +1 @@
|
|||
tests/qapi-schema/data-array-empty.json:2: Member 'empty' of 'data' for command 'oops': array type must contain single type name
|
||||
tests/qapi-schema/args-array-empty.json:2: Member 'empty' of 'data' for command 'oops': array type must contain single type name
|
1
tests/qapi-schema/args-array-unknown.err
Normal file
1
tests/qapi-schema/args-array-unknown.err
Normal file
|
@ -0,0 +1 @@
|
|||
tests/qapi-schema/args-array-unknown.json:2: Member 'array' of 'data' for command 'oops' uses unknown type 'NoSuchType'
|
1
tests/qapi-schema/args-int.err
Normal file
1
tests/qapi-schema/args-int.err
Normal file
|
@ -0,0 +1 @@
|
|||
tests/qapi-schema/args-int.json:2: 'data' for command 'oops' cannot use built-in type 'int'
|
1
tests/qapi-schema/args-invalid.err
Normal file
1
tests/qapi-schema/args-invalid.err
Normal file
|
@ -0,0 +1 @@
|
|||
tests/qapi-schema/args-invalid.json:1: 'data' for command 'foo' should be a dictionary or type name
|
2
tests/qapi-schema/args-invalid.json
Normal file
2
tests/qapi-schema/args-invalid.json
Normal file
|
@ -0,0 +1,2 @@
|
|||
{ 'command': 'foo',
|
||||
'data': false }
|
|
@ -1 +1 @@
|
|||
tests/qapi-schema/data-member-array-bad.json:2: Member 'member' of 'data' for command 'oops': array type must contain single type name
|
||||
tests/qapi-schema/args-member-array-bad.json:2: Member 'member' of 'data' for command 'oops': array type must contain single type name
|
1
tests/qapi-schema/args-member-unknown.err
Normal file
1
tests/qapi-schema/args-member-unknown.err
Normal file
|
@ -0,0 +1 @@
|
|||
tests/qapi-schema/args-member-unknown.json:2: Member 'member' of 'data' for command 'oops' uses unknown type 'NoSuchType'
|
1
tests/qapi-schema/args-union.err
Normal file
1
tests/qapi-schema/args-union.err
Normal file
|
@ -0,0 +1 @@
|
|||
tests/qapi-schema/args-union.json:4: 'data' for command 'oops' cannot use union type 'Uni'
|
1
tests/qapi-schema/args-union.exit
Normal file
1
tests/qapi-schema/args-union.exit
Normal file
|
@ -0,0 +1 @@
|
|||
1
|
4
tests/qapi-schema/args-union.json
Normal file
4
tests/qapi-schema/args-union.json
Normal file
|
@ -0,0 +1,4 @@
|
|||
# we do not allow union arguments
|
||||
# TODO should we support this?
|
||||
{ 'union': 'Uni', 'data': { 'case1': 'int', 'case2': 'str' } }
|
||||
{ 'command': 'oops', 'data': 'Uni' }
|
0
tests/qapi-schema/args-union.out
Normal file
0
tests/qapi-schema/args-union.out
Normal file
1
tests/qapi-schema/args-unknown.err
Normal file
1
tests/qapi-schema/args-unknown.err
Normal file
|
@ -0,0 +1 @@
|
|||
tests/qapi-schema/args-unknown.json:2: 'data' for command 'oops' uses unknown type 'NoSuchType'
|
1
tests/qapi-schema/args-unknown.exit
Normal file
1
tests/qapi-schema/args-unknown.exit
Normal file
|
@ -0,0 +1 @@
|
|||
1
|
0
tests/qapi-schema/args-unknown.out
Normal file
0
tests/qapi-schema/args-unknown.out
Normal file
|
@ -1,3 +1,2 @@
|
|||
# we reject collisions between commands and types
|
||||
{ 'command': 'int', 'data': { 'character': 'str' },
|
||||
'returns': { 'value': 'int' } }
|
||||
{ 'command': 'int', 'data': { 'character': 'str' } }
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
tests/qapi-schema/data-array-unknown.json:2: Member 'array' of 'data' for command 'oops' uses unknown type 'array of NoSuchType'
|
|
@ -1 +0,0 @@
|
|||
tests/qapi-schema/data-int.json:2: 'data' for command 'oops' cannot use built-in type 'int'
|
|
@ -1 +0,0 @@
|
|||
tests/qapi-schema/data-member-unknown.json:2: Member 'member' of 'data' for command 'oops' uses unknown type 'NoSuchType'
|
|
@ -1 +0,0 @@
|
|||
tests/qapi-schema/data-unknown.json:2: 'data' for command 'oops' uses unknown type 'NoSuchType'
|
1
tests/qapi-schema/leading-comma-list.err
Normal file
1
tests/qapi-schema/leading-comma-list.err
Normal file
|
@ -0,0 +1 @@
|
|||
tests/qapi-schema/leading-comma-list.json:2:13: Expected "{", "[", "]", string, boolean or "null"
|
1
tests/qapi-schema/leading-comma-list.exit
Normal file
1
tests/qapi-schema/leading-comma-list.exit
Normal file
|
@ -0,0 +1 @@
|
|||
1
|
2
tests/qapi-schema/leading-comma-list.json
Normal file
2
tests/qapi-schema/leading-comma-list.json
Normal file
|
@ -0,0 +1,2 @@
|
|||
{ 'enum': 'Status',
|
||||
'data': [ , 'good', 'bad', 'ugly' ] }
|
0
tests/qapi-schema/leading-comma-list.out
Normal file
0
tests/qapi-schema/leading-comma-list.out
Normal file
1
tests/qapi-schema/leading-comma-object.err
Normal file
1
tests/qapi-schema/leading-comma-object.err
Normal file
|
@ -0,0 +1 @@
|
|||
tests/qapi-schema/leading-comma-object.json:1:3: Expected string or "}"
|
1
tests/qapi-schema/leading-comma-object.exit
Normal file
1
tests/qapi-schema/leading-comma-object.exit
Normal file
|
@ -0,0 +1 @@
|
|||
1
|
2
tests/qapi-schema/leading-comma-object.json
Normal file
2
tests/qapi-schema/leading-comma-object.json
Normal file
|
@ -0,0 +1,2 @@
|
|||
{ , 'enum': 'Status',
|
||||
'data': [ 'good', 'bad', 'ugly' ] }
|
0
tests/qapi-schema/leading-comma-object.out
Normal file
0
tests/qapi-schema/leading-comma-object.out
Normal file
|
@ -1,4 +1,3 @@
|
|||
# inline subtypes collide with our desired future use of defaults
|
||||
{ 'command': 'foo',
|
||||
'data': { 'a' : { 'string' : 'str', 'integer': 'int' }, 'b' : 'str' },
|
||||
'returns': {} }
|
||||
'data': { 'a' : { 'string' : 'str', 'integer': 'int' }, 'b' : 'str' } }
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
tests/qapi-schema/nested-struct-returns.json:2: Member 'a' of 'returns' for command 'foo' should be a type name
|
|
@ -1,3 +0,0 @@
|
|||
# inline subtypes collide with our desired future use of defaults
|
||||
{ 'command': 'foo',
|
||||
'returns': { 'a' : { 'string' : 'str', 'integer': 'int' }, 'b' : 'str' } }
|
|
@ -7,13 +7,13 @@
|
|||
'data': { 'enum1': 'EnumOne', '*enum2': 'EnumOne', 'enum3': 'EnumOne', '*enum4': 'EnumOne' } }
|
||||
|
||||
# for testing nested structs
|
||||
{ 'struct': 'UserDefOne',
|
||||
'base': 'UserDefZero', # intentional forward reference
|
||||
'data': { 'string': 'str', '*enum1': 'EnumOne' } }
|
||||
|
||||
{ 'struct': 'UserDefZero',
|
||||
'data': { 'integer': 'int' } }
|
||||
|
||||
{ 'struct': 'UserDefOne',
|
||||
'base': 'UserDefZero',
|
||||
'data': { 'string': 'str', '*enum1': 'EnumOne' } }
|
||||
|
||||
{ 'struct': 'UserDefTwoDictDict',
|
||||
'data': { 'userdef': 'UserDefOne', 'string': 'str' } }
|
||||
|
||||
|
@ -31,30 +31,36 @@
|
|||
'data': { 'boolean': 'bool' } }
|
||||
|
||||
{ 'struct': 'UserDefB',
|
||||
'data': { 'integer': 'int' } }
|
||||
|
||||
{ 'struct': 'UserDefC',
|
||||
'data': { 'string1': 'str', 'string2': 'str' } }
|
||||
|
||||
{ 'struct': 'UserDefUnionBase',
|
||||
'data': { 'string': 'str', 'enum1': 'EnumOne' } }
|
||||
'data': { 'intb': 'int' } }
|
||||
|
||||
{ 'union': 'UserDefFlatUnion',
|
||||
'base': 'UserDefUnionBase',
|
||||
'base': 'UserDefUnionBase', # intentional forward reference
|
||||
'discriminator': 'enum1',
|
||||
'data': { 'value1' : 'UserDefA', 'value2' : 'UserDefB', 'value3' : 'UserDefB' } }
|
||||
'data': { 'value1' : 'UserDefA',
|
||||
'value2' : 'UserDefB',
|
||||
'value3' : 'UserDefB' } }
|
||||
# FIXME generated struct UserDefFlatUnion has members for direct base
|
||||
# UserDefOne, but lacks members for indirect base UserDefZero
|
||||
# UserDefUnionBase, but lacks members for indirect base UserDefZero
|
||||
|
||||
{ 'struct': 'UserDefUnionBase',
|
||||
'base': 'UserDefZero',
|
||||
'data': { 'string': 'str', 'enum1': 'EnumOne' } }
|
||||
|
||||
# this variant of UserDefFlatUnion defaults to a union that uses fields with
|
||||
# allocated types to test corner cases in the cleanup/dealloc visitor
|
||||
{ 'union': 'UserDefFlatUnion2',
|
||||
'base': 'UserDefUnionBase',
|
||||
'discriminator': 'enum1',
|
||||
'data': { 'value1' : 'UserDefC', 'value2' : 'UserDefB', 'value3' : 'UserDefA' } }
|
||||
'data': { 'value1' : 'UserDefC', # intentional forward reference
|
||||
'value2' : 'UserDefB',
|
||||
'value3' : 'UserDefA' } }
|
||||
|
||||
{ 'alternate': 'UserDefAlternate',
|
||||
'data': { 'uda': 'UserDefA', 's': 'str', 'i': 'int' } }
|
||||
# FIXME only a declaration of visit_type_UserDefAlternateKind() generated
|
||||
|
||||
{ 'struct': 'UserDefC',
|
||||
'data': { 'string1': 'str', 'string2': 'str' } }
|
||||
|
||||
# for testing native lists
|
||||
{ 'union': 'UserDefNativeListUnion',
|
||||
|
@ -123,6 +129,9 @@
|
|||
{ 'alternate': '__org.qemu_x-Alt',
|
||||
'data': { '__org.qemu_x-branch': 'str', 'b': '__org.qemu_x-Base' } }
|
||||
{ 'event': '__ORG.QEMU_X-EVENT', 'data': '__org.qemu_x-Struct' }
|
||||
# FIXME generated qapi_event_send___org_qemu_x_event() has only a
|
||||
# parameter for data's member __org_qemu_x_member2, none for its base
|
||||
# __org.qemu_x-Base's member __org_qemu_x_member1
|
||||
{ 'command': '__org.qemu_x-command',
|
||||
'data': { 'a': ['__org.qemu_x-Enum'], 'b': ['__org.qemu_x-Struct'],
|
||||
'c': '__org.qemu_x-Union2', 'd': '__org.qemu_x-Alt' },
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
[OrderedDict([('enum', 'EnumOne'), ('data', ['value1', 'value2', 'value3'])]),
|
||||
OrderedDict([('struct', 'NestedEnumsOne'), ('data', OrderedDict([('enum1', 'EnumOne'), ('*enum2', 'EnumOne'), ('enum3', 'EnumOne'), ('*enum4', 'EnumOne')]))]),
|
||||
OrderedDict([('struct', 'UserDefZero'), ('data', OrderedDict([('integer', 'int')]))]),
|
||||
OrderedDict([('struct', 'UserDefOne'), ('base', 'UserDefZero'), ('data', OrderedDict([('string', 'str'), ('*enum1', 'EnumOne')]))]),
|
||||
OrderedDict([('struct', 'UserDefZero'), ('data', OrderedDict([('integer', 'int')]))]),
|
||||
OrderedDict([('struct', 'UserDefTwoDictDict'), ('data', OrderedDict([('userdef', 'UserDefOne'), ('string', 'str')]))]),
|
||||
OrderedDict([('struct', 'UserDefTwoDict'), ('data', OrderedDict([('string1', 'str'), ('dict2', 'UserDefTwoDictDict'), ('*dict3', 'UserDefTwoDictDict')]))]),
|
||||
OrderedDict([('struct', 'UserDefTwo'), ('data', OrderedDict([('string0', 'str'), ('dict1', 'UserDefTwoDict')]))]),
|
||||
OrderedDict([('struct', 'UserDefA'), ('data', OrderedDict([('boolean', 'bool')]))]),
|
||||
OrderedDict([('struct', 'UserDefB'), ('data', OrderedDict([('integer', 'int')]))]),
|
||||
OrderedDict([('struct', 'UserDefC'), ('data', OrderedDict([('string1', 'str'), ('string2', 'str')]))]),
|
||||
OrderedDict([('struct', 'UserDefUnionBase'), ('data', OrderedDict([('string', 'str'), ('enum1', 'EnumOne')]))]),
|
||||
OrderedDict([('struct', 'UserDefB'), ('data', OrderedDict([('intb', 'int')]))]),
|
||||
OrderedDict([('union', 'UserDefFlatUnion'), ('base', 'UserDefUnionBase'), ('discriminator', 'enum1'), ('data', OrderedDict([('value1', 'UserDefA'), ('value2', 'UserDefB'), ('value3', 'UserDefB')]))]),
|
||||
OrderedDict([('struct', 'UserDefUnionBase'), ('base', 'UserDefZero'), ('data', OrderedDict([('string', 'str'), ('enum1', 'EnumOne')]))]),
|
||||
OrderedDict([('union', 'UserDefFlatUnion2'), ('base', 'UserDefUnionBase'), ('discriminator', 'enum1'), ('data', OrderedDict([('value1', 'UserDefC'), ('value2', 'UserDefB'), ('value3', 'UserDefA')]))]),
|
||||
OrderedDict([('alternate', 'UserDefAlternate'), ('data', OrderedDict([('uda', 'UserDefA'), ('s', 'str'), ('i', 'int')]))]),
|
||||
OrderedDict([('struct', 'UserDefC'), ('data', OrderedDict([('string1', 'str'), ('string2', 'str')]))]),
|
||||
OrderedDict([('union', 'UserDefNativeListUnion'), ('data', OrderedDict([('integer', ['int']), ('s8', ['int8']), ('s16', ['int16']), ('s32', ['int32']), ('s64', ['int64']), ('u8', ['uint8']), ('u16', ['uint16']), ('u32', ['uint32']), ('u64', ['uint64']), ('number', ['number']), ('boolean', ['bool']), ('string', ['str']), ('sizes', ['size'])]))]),
|
||||
OrderedDict([('command', 'user_def_cmd'), ('data', OrderedDict())]),
|
||||
OrderedDict([('command', 'user_def_cmd1'), ('data', OrderedDict([('ud1a', 'UserDefOne')]))]),
|
||||
|
@ -39,15 +39,15 @@
|
|||
{'enum_name': '__org.qemu_x-Union1Kind', 'enum_values': None},
|
||||
{'enum_name': '__org.qemu_x-AltKind', 'enum_values': None}]
|
||||
[OrderedDict([('struct', 'NestedEnumsOne'), ('data', OrderedDict([('enum1', 'EnumOne'), ('*enum2', 'EnumOne'), ('enum3', 'EnumOne'), ('*enum4', 'EnumOne')]))]),
|
||||
OrderedDict([('struct', 'UserDefZero'), ('data', OrderedDict([('integer', 'int')]))]),
|
||||
OrderedDict([('struct', 'UserDefOne'), ('base', 'UserDefZero'), ('data', OrderedDict([('string', 'str'), ('*enum1', 'EnumOne')]))]),
|
||||
OrderedDict([('struct', 'UserDefZero'), ('data', OrderedDict([('integer', 'int')]))]),
|
||||
OrderedDict([('struct', 'UserDefTwoDictDict'), ('data', OrderedDict([('userdef', 'UserDefOne'), ('string', 'str')]))]),
|
||||
OrderedDict([('struct', 'UserDefTwoDict'), ('data', OrderedDict([('string1', 'str'), ('dict2', 'UserDefTwoDictDict'), ('*dict3', 'UserDefTwoDictDict')]))]),
|
||||
OrderedDict([('struct', 'UserDefTwo'), ('data', OrderedDict([('string0', 'str'), ('dict1', 'UserDefTwoDict')]))]),
|
||||
OrderedDict([('struct', 'UserDefA'), ('data', OrderedDict([('boolean', 'bool')]))]),
|
||||
OrderedDict([('struct', 'UserDefB'), ('data', OrderedDict([('integer', 'int')]))]),
|
||||
OrderedDict([('struct', 'UserDefB'), ('data', OrderedDict([('intb', 'int')]))]),
|
||||
OrderedDict([('struct', 'UserDefUnionBase'), ('base', 'UserDefZero'), ('data', OrderedDict([('string', 'str'), ('enum1', 'EnumOne')]))]),
|
||||
OrderedDict([('struct', 'UserDefC'), ('data', OrderedDict([('string1', 'str'), ('string2', 'str')]))]),
|
||||
OrderedDict([('struct', 'UserDefUnionBase'), ('data', OrderedDict([('string', 'str'), ('enum1', 'EnumOne')]))]),
|
||||
OrderedDict([('struct', 'UserDefOptions'), ('data', OrderedDict([('*i64', ['int']), ('*u64', ['uint64']), ('*u16', ['uint16']), ('*i64x', 'int'), ('*u64x', 'uint64')]))]),
|
||||
OrderedDict([('struct', 'EventStructOne'), ('data', OrderedDict([('struct1', 'UserDefOne'), ('string', 'str'), ('*enum2', 'EnumOne')]))]),
|
||||
OrderedDict([('struct', '__org.qemu_x-Base'), ('data', OrderedDict([('__org.qemu_x-member1', '__org.qemu_x-Enum')]))]),
|
||||
|
|
1
tests/qapi-schema/returns-dict.err
Normal file
1
tests/qapi-schema/returns-dict.err
Normal file
|
@ -0,0 +1 @@
|
|||
tests/qapi-schema/returns-dict.json:2: 'returns' for command 'oops' should be a type name
|
1
tests/qapi-schema/returns-dict.exit
Normal file
1
tests/qapi-schema/returns-dict.exit
Normal file
|
@ -0,0 +1 @@
|
|||
1
|
2
tests/qapi-schema/returns-dict.json
Normal file
2
tests/qapi-schema/returns-dict.json
Normal file
|
@ -0,0 +1,2 @@
|
|||
# we reject inline struct return type
|
||||
{ 'command': 'oops', 'returns': { 'a': 'str' } }
|
0
tests/qapi-schema/returns-dict.out
Normal file
0
tests/qapi-schema/returns-dict.out
Normal file
|
@ -1 +1 @@
|
|||
tests/qapi-schema/returns-whitelist.json:10: 'returns' for command 'no-way-this-will-get-whitelisted' cannot use built-in type 'array of int'
|
||||
tests/qapi-schema/returns-whitelist.json:10: 'returns' for command 'no-way-this-will-get-whitelisted' cannot use built-in type 'int'
|
||||
|
|
1
tests/qapi-schema/struct-data-invalid.err
Normal file
1
tests/qapi-schema/struct-data-invalid.err
Normal file
|
@ -0,0 +1 @@
|
|||
tests/qapi-schema/struct-data-invalid.json:1: 'data' for struct 'foo' should be a dictionary or type name
|
1
tests/qapi-schema/struct-data-invalid.exit
Normal file
1
tests/qapi-schema/struct-data-invalid.exit
Normal file
|
@ -0,0 +1 @@
|
|||
1
|
2
tests/qapi-schema/struct-data-invalid.json
Normal file
2
tests/qapi-schema/struct-data-invalid.json
Normal file
|
@ -0,0 +1,2 @@
|
|||
{ 'struct': 'foo',
|
||||
'data': false }
|
0
tests/qapi-schema/struct-data-invalid.out
Normal file
0
tests/qapi-schema/struct-data-invalid.out
Normal file
1
tests/qapi-schema/struct-member-invalid.err
Normal file
1
tests/qapi-schema/struct-member-invalid.err
Normal file
|
@ -0,0 +1 @@
|
|||
tests/qapi-schema/struct-member-invalid.json:1: Member 'a' of 'data' for struct 'foo' should be a type name
|
1
tests/qapi-schema/struct-member-invalid.exit
Normal file
1
tests/qapi-schema/struct-member-invalid.exit
Normal file
|
@ -0,0 +1 @@
|
|||
1
|
2
tests/qapi-schema/struct-member-invalid.json
Normal file
2
tests/qapi-schema/struct-member-invalid.json
Normal file
|
@ -0,0 +1,2 @@
|
|||
{ 'struct': 'foo',
|
||||
'data': { 'a': false } }
|
0
tests/qapi-schema/struct-member-invalid.out
Normal file
0
tests/qapi-schema/struct-member-invalid.out
Normal file
|
@ -1 +1 @@
|
|||
tests/qapi-schema/union-base-no-discriminator.json:11: Union 'TestUnion' requires a discriminator to go along with base
|
||||
tests/qapi-schema/union-base-no-discriminator.json:11: Simple union 'TestUnion' must not have a base
|
||||
|
|
|
@ -94,7 +94,7 @@ static bool qdict_cmp_simple(QDict *a, QDict *b)
|
|||
|
||||
/* This function is hooked as final emit function, which can verify the
|
||||
correctness. */
|
||||
static void event_test_emit(TEST_QAPIEvent event, QDict *d, Error **errp)
|
||||
static void event_test_emit(test_QAPIEvent event, QDict *d, Error **errp)
|
||||
{
|
||||
QObject *obj;
|
||||
QDict *t;
|
||||
|
|
|
@ -313,7 +313,7 @@ static void test_visitor_in_union_flat(TestInputVisitorData *data,
|
|||
|
||||
visit_type_UserDefFlatUnion(v, &tmp, NULL, &err);
|
||||
g_assert(err == NULL);
|
||||
g_assert_cmpint(tmp->kind, ==, ENUM_ONE_VALUE1);
|
||||
g_assert_cmpint(tmp->enum1, ==, ENUM_ONE_VALUE1);
|
||||
g_assert_cmpstr(tmp->string, ==, "str");
|
||||
/* TODO g_assert_cmpint(tmp->integer, ==, 41); */
|
||||
g_assert_cmpint(tmp->value1->boolean, ==, true);
|
||||
|
@ -636,6 +636,8 @@ static void test_visitor_in_errors(TestInputVisitorData *data,
|
|||
|
||||
visit_type_TestStruct(v, &p, NULL, &err);
|
||||
g_assert(err);
|
||||
/* FIXME - a failed parse should not leave a partially-allocated p
|
||||
* for us to clean up; this could cause callers to leak memory. */
|
||||
g_assert(p->string == NULL);
|
||||
|
||||
error_free(err);
|
||||
|
|
|
@ -437,7 +437,7 @@ static void test_visitor_out_union_flat(TestOutputVisitorData *data,
|
|||
Error *err = NULL;
|
||||
|
||||
UserDefFlatUnion *tmp = g_malloc0(sizeof(UserDefFlatUnion));
|
||||
tmp->kind = ENUM_ONE_VALUE1;
|
||||
tmp->enum1 = ENUM_ONE_VALUE1;
|
||||
tmp->string = g_strdup("str");
|
||||
tmp->value1 = g_malloc0(sizeof(UserDefA));
|
||||
/* TODO when generator bug is fixed: tmp->integer = 41; */
|
||||
|
|
Loading…
Reference in a new issue