qapi: Fix qapi mangling of downstream names, and more

-----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABAgAGBQJVViG7AAoJEDhwtADrkYZTqu0QAJCtZI2V3JZ3RmUfj/ISpekZ
 9gery42k6mc9dnMp+YOEdfbYYkjtcb3NqSPQi1iJUtBS1GjYGgvC2dqYDs6Eemow
 OEMyat7pwzPL7oOgoXC2F3fd/LMkpGU+qNIcj9ofqrd0I46MXYCTuwS6f8j1geDQ
 QtG+P57g6VFNzoy6I2H7NV3u3kLw1uwUTGaIEuuoCPUmSSWJrCxmoN2pFmHK1Rwk
 8rjuN5ZBLt2Vonqkj59qv/MA7/VmpasIVdbfsbnt36Jih7IyojDxpcNB80xTMlnh
 2AmVXSTsP62f7xhG2xWJf9+aOu4MWqfKCmv2f4wxuLV78eHRqjBz9zvMZTzSIE3j
 ca71KBl5qXIPB0YdCXZrI6k6UnsXzkO8V51IfrclWqzGKX23JBaNltaKyFnAeFEU
 mkVZFX2STFqE1sv9rpYlXcwnXf0OzERtoSK0yeQOFCUVRdFuZkUBHMoCcb06cZMt
 kfP+gLt5d3hM9u1nv4rd2pfIq09HME+L6yyyG6x38EF1gvY7Up+ckqYSTaeioVWZ
 S4lv1Wus/QFll5EZ5RIQNmA9PW58CJ7v5E3M2II82WNcqoWjhvcnjFtmaorvJ8N1
 PFqIbODjbG3WOUTe5jZnJemzSoXKeX1QhQ4nwhAPMQQpvWiheOWlgE1sAj3vnK+l
 7PUF4BnOPk0pH6nCeWY6
 =wbUI
 -----END PGP SIGNATURE-----

Merge remote-tracking branch 'remotes/armbru/tags/pull-qapi-2015-05-15' into staging

qapi: Fix qapi mangling of downstream names, and more

# gpg: Signature made Fri May 15 17:41:31 2015 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-05-15: (26 commits)
  qapi: Inline gen_command_decl_prologue(), gen_command_def_prologue()
  qapi: Drop pointless flush() before close()
  qapi: Factor open_output(), close_output() out of generators
  qapi: Turn generators' mandatory option -i into an argument
  qapi: Fix generators to report command line errors decently
  qapi: Factor parse_command_line() out of the generators
  qapi: qapi-commands.py option --type is unused, drop it
  qapi: qapi-event.py option -b does nothing, drop it
  tests: Add missing dependencies on $(qapi-py)
  qapi: Support downstream events and commands
  qapi: Support downstream alternates
  qapi: Support downstream flat unions
  qapi: Support downstream simple unions
  qapi: Support downstream structs
  qapi: Support downstream enums
  qapi: Make c_type() consistently convert qapi names
  qapi: Tidy c_type() logic
  qapi: Move camel_to_upper(), c_enum_const() to closely related code
  qapi: Use c_enum_const() in generate_alternate_qtypes()
  qapi: Simplify c_enum_const()
  ...

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
Peter Maydell 2015-05-15 17:51:20 +01:00
commit 385057cbec
15 changed files with 478 additions and 577 deletions

View File

@ -243,17 +243,17 @@ qapi-py = $(SRC_PATH)/scripts/qapi.py $(SRC_PATH)/scripts/ordereddict.py
qga/qapi-generated/qga-qapi-types.c qga/qapi-generated/qga-qapi-types.h :\
$(SRC_PATH)/qga/qapi-schema.json $(SRC_PATH)/scripts/qapi-types.py $(qapi-py)
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py \
$(gen-out-type) -o qga/qapi-generated -p "qga-" -i $<, \
$(gen-out-type) -o qga/qapi-generated -p "qga-" $<, \
" GEN $@")
qga/qapi-generated/qga-qapi-visit.c qga/qapi-generated/qga-qapi-visit.h :\
$(SRC_PATH)/qga/qapi-schema.json $(SRC_PATH)/scripts/qapi-visit.py $(qapi-py)
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py \
$(gen-out-type) -o qga/qapi-generated -p "qga-" -i $<, \
$(gen-out-type) -o qga/qapi-generated -p "qga-" $<, \
" GEN $@")
qga/qapi-generated/qga-qmp-commands.h qga/qapi-generated/qga-qmp-marshal.c :\
$(SRC_PATH)/qga/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py)
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py \
$(gen-out-type) -o qga/qapi-generated -p "qga-" -i $<, \
$(gen-out-type) -o qga/qapi-generated -p "qga-" $<, \
" GEN $@")
qapi-modules = $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/qapi/common.json \
@ -263,22 +263,22 @@ qapi-modules = $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/qapi/common.json \
qapi-types.c qapi-types.h :\
$(qapi-modules) $(SRC_PATH)/scripts/qapi-types.py $(qapi-py)
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py \
$(gen-out-type) -o "." -b -i $<, \
$(gen-out-type) -o "." -b $<, \
" GEN $@")
qapi-visit.c qapi-visit.h :\
$(qapi-modules) $(SRC_PATH)/scripts/qapi-visit.py $(qapi-py)
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py \
$(gen-out-type) -o "." -b -i $<, \
$(gen-out-type) -o "." -b $<, \
" GEN $@")
qapi-event.c qapi-event.h :\
$(qapi-modules) $(SRC_PATH)/scripts/qapi-event.py $(qapi-py)
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-event.py \
$(gen-out-type) -o "." -b -i $<, \
$(gen-out-type) -o "." $<, \
" GEN $@")
qmp-commands.h qmp-marshal.c :\
$(qapi-modules) $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py)
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py \
$(gen-out-type) -o "." -m -i $<, \
$(gen-out-type) -o "." -m $<, \
" GEN $@")
QGALIB_GEN=$(addprefix qga/qapi-generated/, qga-qapi-types.h qga-qapi-visit.h qga-qmp-commands.h)

1
cpus.c
View File

@ -1435,6 +1435,7 @@ CpuInfoList *qmp_query_cpus(Error **errp)
info->value->CPU = cpu->cpu_index;
info->value->current = (cpu == first_cpu);
info->value->halted = cpu->halted;
info->value->qom_path = object_get_canonical_path(OBJECT(cpu));
info->value->thread_id = cpu->thread_id;
#if defined(TARGET_I386)
info->value->has_pc = true;

View File

@ -536,7 +536,7 @@ created code.
Example:
$ python scripts/qapi-types.py --output-dir="qapi-generated" \
--prefix="example-" --input-file=example-schema.json
--prefix="example-" example-schema.json
$ cat qapi-generated/example-qapi-types.c
[Uninteresting stuff omitted...]
@ -623,7 +623,7 @@ $(prefix)qapi-visit.h: declarations for previously mentioned visitor
Example:
$ python scripts/qapi-visit.py --output-dir="qapi-generated"
--prefix="example-" --input-file=example-schema.json
--prefix="example-" example-schema.json
$ cat qapi-generated/example-qapi-visit.c
[Uninteresting stuff omitted...]
@ -681,7 +681,7 @@ Example:
error_propagate(errp, err);
}
$ python scripts/qapi-commands.py --output-dir="qapi-generated" \
--prefix="example-" --input-file=example-schema.json
--prefix="example-" example-schema.json
$ cat qapi-generated/example-qapi-visit.h
[Uninteresting stuff omitted...]
@ -715,7 +715,7 @@ $(prefix)qmp-commands.h: Function prototypes for the QMP commands
Example:
$ python scripts/qapi-commands.py --output-dir="qapi-generated"
--prefix="example-" --input-file=example-schema.json
--prefix="example-" example-schema.json
$ cat qapi-generated/example-qmp-marshal.c
[Uninteresting stuff omitted...]
@ -806,7 +806,7 @@ $(prefix)qapi-event.c - Implementation of functions to send an event
Example:
$ python scripts/qapi-event.py --output-dir="qapi-generated"
--prefix="example-" --input-file=example-schema.json
--prefix="example-" example-schema.json
$ cat qapi-generated/example-qapi-event.c
[Uninteresting stuff omitted...]

View File

@ -232,7 +232,7 @@ Example:
{ "event": "GUEST_PANICKED",
"data": { "action": "pause" } }
MEM_HOT_UNPLUG_ERROR
MEM_UNPLUG_ERROR
--------------------
Emitted when memory hot unplug error occurs.
@ -243,7 +243,7 @@ Data:
Example:
{ "event": "MEM_HOT_UNPLUG_ERROR"
{ "event": "MEM_UNPLUG_ERROR"
"data": { "device": "dimm1",
"msg": "acpi: device unplug for unsupported device"
},

View File

@ -679,6 +679,8 @@
# @halted: true if the virtual CPU is in the halt state. Halt usually refers
# to a processor specific low power mode.
#
# @qom_path: path to the CPU object in the QOM tree (since 2.4)
#
# @pc: #optional If the target is i386 or x86_64, this is the 64-bit instruction
# pointer.
# If the target is Sparc, this is the PC component of the
@ -699,8 +701,10 @@
# data is sent to the client, the guest may no longer be halted.
##
{ 'struct': 'CpuInfo',
'data': {'CPU': 'int', 'current': 'bool', 'halted': 'bool', '*pc': 'int',
'*nip': 'int', '*npc': 'int', '*PC': 'int', 'thread_id': 'int'} }
'data': {'CPU': 'int', 'current': 'bool', 'halted': 'bool',
'qom_path': 'str',
'*pc': 'int', '*nip': 'int', '*npc': 'int', '*PC': 'int',
'thread_id': 'int'} }
##
# @query-cpus:

View File

@ -2569,6 +2569,7 @@ Return a json-array. Each CPU is represented by a json-object, which contains:
- "CPU": CPU index (json-int)
- "current": true if this is the current CPU, false otherwise (json-bool)
- "halted": true if the cpu is halted, false otherwise (json-bool)
- "qom_path": path to the CPU object in the QOM tree (json-str)
- Current program counter. The key's name depends on the architecture:
"pc": i386/x86_64 (json-int)
"nip": PPC (json-int)
@ -2585,14 +2586,16 @@ Example:
"CPU":0,
"current":true,
"halted":false,
"pc":3227107138
"qom_path":"/machine/unattached/device[0]",
"pc":3227107138,
"thread_id":3134
},
{
"CPU":1,
"current":false,
"halted":true,
"pc":7108165
"qom_path":"/machine/unattached/device[2]",
"pc":7108165,
"thread_id":3135
}
]

View File

@ -15,28 +15,19 @@
from ordereddict import OrderedDict
from qapi import *
import re
import sys
import os
import getopt
import errno
def type_visitor(name):
if type(name) == list:
return 'visit_type_%sList' % name[0]
else:
return 'visit_type_%s' % name
def generate_command_decl(name, args, ret_type):
arglist=""
for argname, argtype, optional in parse_args(args):
argtype = c_type(argtype, is_param=True)
if optional:
arglist += "bool has_%s, " % c_var(argname)
arglist += "%s %s, " % (argtype, c_var(argname))
arglist += "bool has_%s, " % c_name(argname)
arglist += "%s %s, " % (argtype, c_name(argname))
return mcgen('''
%(ret_type)s qmp_%(name)s(%(args)sError **errp);
''',
ret_type=c_type(ret_type), name=c_fun(name), args=arglist).strip()
ret_type=c_type(ret_type), name=c_name(name),
args=arglist).strip()
def gen_err_check(errvar):
if errvar:
@ -55,14 +46,14 @@ def gen_sync_call(name, args, ret_type, indent=0):
retval = "retval = "
for argname, argtype, optional in parse_args(args):
if optional:
arglist += "has_%s, " % c_var(argname)
arglist += "%s, " % (c_var(argname))
arglist += "has_%s, " % c_name(argname)
arglist += "%s, " % (c_name(argname))
push_indent(indent)
ret = mcgen('''
%(retval)sqmp_%(name)s(%(args)s&local_err);
''',
name=c_fun(name), args=arglist, retval=retval).rstrip()
name=c_name(name), args=arglist, retval=retval).rstrip()
if ret_type:
ret += "\n" + gen_err_check('local_err')
ret += "\n" + mcgen(''''
@ -76,7 +67,7 @@ def gen_sync_call(name, args, ret_type, indent=0):
def gen_marshal_output_call(name, ret_type):
if not ret_type:
return ""
return "qmp_marshal_output_%s(retval, ret, &local_err);" % c_fun(name)
return "qmp_marshal_output_%s(retval, ret, &local_err);" % c_name(name)
def gen_visitor_input_containers_decl(args, obj):
ret = ""
@ -101,17 +92,17 @@ def gen_visitor_input_vars_decl(args):
ret += mcgen('''
bool has_%(argname)s = false;
''',
argname=c_var(argname))
argname=c_name(argname))
if is_c_ptr(argtype):
ret += mcgen('''
%(argtype)s %(argname)s = NULL;
''',
argname=c_var(argname), argtype=c_type(argtype))
argname=c_name(argname), argtype=c_type(argtype))
else:
ret += mcgen('''
%(argtype)s %(argname)s = {0};
''',
argname=c_var(argname), argtype=c_type(argtype))
argname=c_name(argname), argtype=c_type(argtype))
pop_indent()
return ret.rstrip()
@ -144,18 +135,18 @@ v = qmp_input_get_visitor(mi);
ret += mcgen('''
visit_optional(v, &has_%(c_name)s, "%(name)s", %(errp)s);
''',
c_name=c_var(argname), name=argname, errp=errparg)
c_name=c_name(argname), name=argname, errp=errparg)
ret += gen_err_check(errarg)
ret += mcgen('''
if (has_%(c_name)s) {
''',
c_name=c_var(argname))
c_name=c_name(argname))
push_indent()
ret += mcgen('''
%(visitor)s(v, &%(c_name)s, "%(name)s", %(errp)s);
visit_type_%(visitor)s(v, &%(c_name)s, "%(name)s", %(errp)s);
''',
c_name=c_var(argname), name=argname, argtype=argtype,
visitor=type_visitor(argtype), errp=errparg)
c_name=c_name(argname), name=argname, argtype=argtype,
visitor=type_name(argtype), errp=errparg)
ret += gen_err_check(errarg)
if optional:
pop_indent()
@ -183,7 +174,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);
%(visitor)s(v, &ret_in, "unused", &local_err);
visit_type_%(visitor)s(v, &ret_in, "unused", &local_err);
if (local_err) {
goto out;
}
@ -194,20 +185,20 @@ out:
qmp_output_visitor_cleanup(mo);
md = qapi_dealloc_visitor_new();
v = qapi_dealloc_get_visitor(md);
%(visitor)s(v, &ret_in, "unused", NULL);
visit_type_%(visitor)s(v, &ret_in, "unused", NULL);
qapi_dealloc_visitor_cleanup(md);
}
''',
c_ret_type=c_type(ret_type), c_name=c_fun(name),
visitor=type_visitor(ret_type))
c_ret_type=c_type(ret_type), c_name=c_name(name),
visitor=type_name(ret_type))
return ret
def gen_marshal_input_decl(name, args, ret_type, middle_mode):
if middle_mode:
return 'int qmp_marshal_input_%s(Monitor *mon, const QDict *qdict, QObject **ret)' % c_fun(name)
return 'int qmp_marshal_input_%s(Monitor *mon, const QDict *qdict, QObject **ret)' % c_name(name)
else:
return 'static void qmp_marshal_input_%s(QDict *args, QObject **ret, Error **errp)' % c_fun(name)
return 'static void qmp_marshal_input_%s(QDict *args, QObject **ret, Error **errp)' % c_name(name)
@ -304,7 +295,7 @@ def gen_registry(commands):
registry += mcgen('''
qmp_register_command("%(name)s", qmp_marshal_input_%(c_name)s, %(opts)s);
''',
name=cmd['command'], c_name=c_fun(cmd['command']),
name=cmd['command'], c_name=c_name(cmd['command']),
opts=options)
pop_indent()
ret = mcgen('''
@ -318,38 +309,20 @@ qapi_init(qmp_init_marshal);
registry=registry.rstrip())
return ret
def gen_command_decl_prologue(header, guard, prefix=""):
ret = mcgen('''
/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
middle_mode = False
/*
* schema-defined QAPI function prototypes
*
* Copyright IBM, Corp. 2011
*
* Authors:
* Anthony Liguori <aliguori@us.ibm.com>
*
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
* See the COPYING.LIB file in the top-level directory.
*
*/
(input_file, output_dir, do_c, do_h, prefix, opts) = \
parse_command_line("m", ["middle"])
#ifndef %(guard)s
#define %(guard)s
for o, a in opts:
if o in ("-m", "--middle"):
middle_mode = True
#include "%(prefix)sqapi-types.h"
#include "qapi/qmp/qdict.h"
#include "qapi/error.h"
''',
header=basename(header), guard=guardname(header), prefix=prefix)
return ret
def gen_command_def_prologue(prefix="", proxy=False):
ret = mcgen('''
/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
exprs = parse_schema(input_file)
commands = filter(lambda expr: expr.has_key('command'), exprs)
commands = filter(lambda expr: not expr.has_key('gen'), commands)
c_comment = '''
/*
* schema-defined QMP->QAPI command dispatch
*
@ -362,7 +335,27 @@ def gen_command_def_prologue(prefix="", proxy=False):
* See the COPYING.LIB file in the top-level directory.
*
*/
'''
h_comment = '''
/*
* schema-defined QAPI function prototypes
*
* Copyright IBM, Corp. 2011
*
* Authors:
* Anthony Liguori <aliguori@us.ibm.com>
*
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
* See the COPYING.LIB file in the top-level directory.
*
*/
'''
(fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix,
'qmp-marshal.c', 'qmp-commands.h',
c_comment, h_comment)
fdef.write(mcgen('''
#include "qemu-common.h"
#include "qemu/module.h"
#include "qapi/qmp/qerror.h"
@ -374,82 +367,20 @@ def gen_command_def_prologue(prefix="", proxy=False):
#include "qapi/dealloc-visitor.h"
#include "%(prefix)sqapi-types.h"
#include "%(prefix)sqapi-visit.h"
#include "%(prefix)sqmp-commands.h"
''',
prefix=prefix)
if not proxy:
ret += '#include "%sqmp-commands.h"' % prefix
return ret + "\n\n"
prefix=prefix))
fdecl.write(mcgen('''
#include "%(prefix)sqapi-types.h"
#include "qapi/qmp/qdict.h"
#include "qapi/error.h"
try:
opts, args = getopt.gnu_getopt(sys.argv[1:], "chp:i:o:m",
["source", "header", "prefix=",
"input-file=", "output-dir=",
"type=", "middle"])
except getopt.GetoptError, err:
print str(err)
sys.exit(1)
''',
prefix=prefix))
output_dir = ""
prefix = ""
dispatch_type = "sync"
c_file = 'qmp-marshal.c'
h_file = 'qmp-commands.h'
middle_mode = False
do_c = False
do_h = False
for o, a in opts:
if o in ("-p", "--prefix"):
prefix = a
elif o in ("-i", "--input-file"):
input_file = a
elif o in ("-o", "--output-dir"):
output_dir = a + "/"
elif o in ("-t", "--type"):
dispatch_type = a
elif o in ("-m", "--middle"):
middle_mode = True
elif o in ("-c", "--source"):
do_c = True
elif o in ("-h", "--header"):
do_h = True
if not do_c and not do_h:
do_c = True
do_h = True
c_file = output_dir + prefix + c_file
h_file = output_dir + prefix + h_file
def maybe_open(really, name, opt):
if really:
return open(name, opt)
else:
import StringIO
return StringIO.StringIO()
try:
os.makedirs(output_dir)
except os.error, e:
if e.errno != errno.EEXIST:
raise
exprs = parse_schema(input_file)
commands = filter(lambda expr: expr.has_key('command'), exprs)
commands = filter(lambda expr: not expr.has_key('gen'), commands)
if dispatch_type == "sync":
fdecl = maybe_open(do_h, h_file, 'w')
fdef = maybe_open(do_c, c_file, 'w')
ret = gen_command_decl_prologue(header=basename(h_file), guard=guardname(h_file), prefix=prefix)
fdecl.write(ret)
ret = gen_command_def_prologue(prefix=prefix)
fdef.write(ret)
for cmd in commands:
for cmd in commands:
arglist = []
ret_type = None
if cmd.has_key('data'):
@ -468,13 +399,8 @@ if dispatch_type == "sync":
ret = gen_marshal_input(cmd['command'], arglist, ret_type, middle_mode) + "\n"
fdef.write(ret)
fdecl.write("\n#endif\n");
if not middle_mode:
if not middle_mode:
ret = gen_registry(commands)
fdef.write(ret)
fdef.flush()
fdef.close()
fdecl.flush()
fdecl.close()
close_output(fdef, fdecl)

View File

@ -11,23 +11,19 @@
from ordereddict import OrderedDict
from qapi import *
import sys
import os
import getopt
import errno
def _generate_event_api_name(event_name, params):
api_name = "void qapi_event_send_%s(" % c_fun(event_name).lower();
api_name = "void qapi_event_send_%s(" % c_name(event_name).lower();
l = len(api_name)
if params:
for argname, argentry, optional in parse_args(params):
if optional:
api_name += "bool has_%s,\n" % c_var(argname)
api_name += "bool has_%s,\n" % c_name(argname)
api_name += "".ljust(l)
api_name += "%s %s,\n" % (c_type(argentry, is_param=True),
c_var(argname))
c_name(argname))
api_name += "".ljust(l)
api_name += "Error **errp)"
@ -98,7 +94,7 @@ def generate_event_implement(api_name, event_name, params):
ret += mcgen("""
if (has_%(var)s) {
""",
var = c_var(argname))
var = c_name(argname))
push_indent()
if argentry == "str":
@ -113,7 +109,7 @@ def generate_event_implement(api_name, event_name, params):
}
""",
var_type = var_type,
var = c_var(argname),
var = c_name(argname),
type = type_name(argentry),
name = argname)
@ -177,7 +173,7 @@ typedef enum %(event_enum_name)s
event_enum_name = event_enum_name)
# append automatically generated _MAX value
enum_max_value = generate_enum_full_value(event_enum_name, "MAX")
enum_max_value = c_enum_const(event_enum_name, "MAX")
enum_values = event_enum_values + [ enum_max_value ]
i = 0
@ -216,67 +212,9 @@ const char *%(event_enum_name)s_lookup[] = {
''')
return ret
(input_file, output_dir, do_c, do_h, prefix, dummy) = parse_command_line()
# Start the real job
try:
opts, args = getopt.gnu_getopt(sys.argv[1:], "chbp:i:o:",
["source", "header", "builtins", "prefix=",
"input-file=", "output-dir="])
except getopt.GetoptError, err:
print str(err)
sys.exit(1)
input_file = ""
output_dir = ""
prefix = ""
c_file = 'qapi-event.c'
h_file = 'qapi-event.h'
do_c = False
do_h = False
do_builtins = False
for o, a in opts:
if o in ("-p", "--prefix"):
prefix = a
elif o in ("-i", "--input-file"):
input_file = a
elif o in ("-o", "--output-dir"):
output_dir = a + "/"
elif o in ("-c", "--source"):
do_c = True
elif o in ("-h", "--header"):
do_h = True
elif o in ("-b", "--builtins"):
do_builtins = True
if not do_c and not do_h:
do_c = True
do_h = True
c_file = output_dir + prefix + c_file
h_file = output_dir + prefix + h_file
try:
os.makedirs(output_dir)
except os.error, e:
if e.errno != errno.EEXIST:
raise
def maybe_open(really, name, opt):
if really:
return open(name, opt)
else:
import StringIO
return StringIO.StringIO()
fdef = maybe_open(do_c, c_file, 'w')
fdecl = maybe_open(do_h, h_file, 'w')
fdef.write(mcgen('''
/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
c_comment = '''
/*
* schema-defined QAPI event functions
*
@ -289,41 +227,43 @@ fdef.write(mcgen('''
* See the COPYING.LIB file in the top-level directory.
*
*/
'''
h_comment = '''
/*
* schema-defined QAPI event functions
*
* Copyright (c) 2014 Wenchao Xia
*
* Authors:
* Wenchao Xia <wenchaoqemu@gmail.com>
*
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
* See the COPYING.LIB file in the top-level directory.
*
*/
'''
(fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix,
'qapi-event.c', 'qapi-event.h',
c_comment, h_comment)
fdef.write(mcgen('''
#include "qemu-common.h"
#include "%(header)s"
#include "%(prefix)sqapi-event.h"
#include "%(prefix)sqapi-visit.h"
#include "qapi/qmp-output-visitor.h"
#include "qapi/qmp-event.h"
''',
prefix=prefix, header=basename(h_file)))
prefix=prefix))
fdecl.write(mcgen('''
/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
/*
* schema-defined QAPI event functions
*
* Copyright (c) 2014 Wenchao Xia
*
* Authors:
* Wenchao Xia <wenchaoqemu@gmail.com>
*
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
* See the COPYING.LIB file in the top-level directory.
*
*/
#ifndef %(guard)s
#define %(guard)s
#include "qapi/error.h"
#include "qapi/qmp/qdict.h"
#include "%(prefix)sqapi-types.h"
''',
prefix=prefix, guard=guardname(h_file)))
prefix=prefix))
exprs = parse_schema(input_file)
@ -343,8 +283,7 @@ for expr in exprs:
fdecl.write(ret)
# We need an enum value per event
event_enum_value = generate_enum_full_value(event_enum_name,
event_name)
event_enum_value = c_enum_const(event_enum_name, event_name)
ret = generate_event_implement(api_name, event_name, params)
fdef.write(ret)
@ -357,12 +296,4 @@ fdecl.write(ret)
ret = generate_event_enum_lookup(event_enum_name, event_enum_strings)
fdef.write(ret)
fdecl.write('''
#endif
''')
fdecl.flush()
fdecl.close()
fdef.flush()
fdef.close()
close_output(fdef, fdecl)

View File

@ -11,10 +11,6 @@
from ordereddict import OrderedDict
from qapi import *
import sys
import os
import getopt
import errno
def generate_fwd_struct(name, members, builtin_type=False):
if builtin_type:
@ -45,7 +41,7 @@ typedef struct %(name)sList
struct %(name)sList *next;
} %(name)sList;
''',
name=name)
name=c_name(name))
def generate_fwd_enum_struct(name, members):
return mcgen('''
@ -58,7 +54,7 @@ typedef struct %(name)sList
struct %(name)sList *next;
} %(name)sList;
''',
name=name)
name=c_name(name))
def generate_struct_fields(members):
ret = ''
@ -68,11 +64,11 @@ def generate_struct_fields(members):
ret += mcgen('''
bool has_%(c_name)s;
''',
c_name=c_var(argname))
c_name=c_name(argname))
ret += mcgen('''
%(c_type)s %(c_name)s;
''',
c_type=c_type(argentry), c_name=c_var(argname))
c_type=c_type(argentry), c_name=c_name(argname))
return ret
@ -87,7 +83,7 @@ def generate_struct(expr):
struct %(name)s
{
''',
name=structname)
name=c_name(structname))
if base:
ret += generate_struct_fields({'base': base})
@ -115,16 +111,16 @@ def generate_enum_lookup(name, values):
ret = mcgen('''
const char *%(name)s_lookup[] = {
''',
name=name)
name=c_name(name))
i = 0
for value in values:
index = generate_enum_full_value(name, value)
index = c_enum_const(name, value)
ret += mcgen('''
[%(index)s] = "%(value)s",
''',
index = index, value = value)
max_index = generate_enum_full_value(name, 'MAX')
max_index = c_enum_const(name, 'MAX')
ret += mcgen('''
[%(max_index)s] = NULL,
};
@ -134,6 +130,7 @@ const char *%(name)s_lookup[] = {
return ret
def generate_enum(name, values):
name = c_name(name)
lookup_decl = mcgen('''
extern const char *%(name)s_lookup[];
''',
@ -150,7 +147,7 @@ typedef enum %(name)s
i = 0
for value in enum_values:
enum_full_value = generate_enum_full_value(name, value)
enum_full_value = c_enum_const(name, value)
enum_decl += mcgen('''
%(enum_full_value)s = %(i)d,
''',
@ -173,18 +170,17 @@ def generate_alternate_qtypes(expr):
ret = mcgen('''
const int %(name)s_qtypes[QTYPE_MAX] = {
''',
name=name)
name=c_name(name))
for key in members:
qtype = find_alternate_member_qtype(members[key])
assert qtype, "Invalid alternate member"
ret += mcgen('''
[ %(qtype)s ] = %(abbrev)s_KIND_%(enum)s,
[%(qtype)s] = %(enum_const)s,
''',
qtype = qtype,
abbrev = de_camel_case(name).upper(),
enum = c_fun(de_camel_case(key),False).upper())
enum_const = c_enum_const(name + 'Kind', key))
ret += mcgen('''
};
@ -194,7 +190,7 @@ const int %(name)s_qtypes[QTYPE_MAX] = {
def generate_union(expr, meta):
name = expr[meta]
name = c_name(expr[meta])
typeinfo = expr['data']
base = expr.get('base')
@ -214,14 +210,14 @@ struct %(name)s
void *data;
''',
name=name,
discriminator_type_name=discriminator_type_name)
discriminator_type_name=c_name(discriminator_type_name))
for key in typeinfo:
ret += mcgen('''
%(c_type)s %(c_name)s;
''',
c_type=c_type(typeinfo[key]),
c_name=c_fun(key))
c_name=c_name(key))
ret += mcgen('''
};
@ -249,15 +245,15 @@ extern const int %(name)s_qtypes[];
def generate_type_cleanup_decl(name):
ret = mcgen('''
void qapi_free_%(type)s(%(c_type)s obj);
void qapi_free_%(name)s(%(c_type)s obj);
''',
c_type=c_type(name),type=name)
c_type=c_type(name), name=c_name(name))
return ret
def generate_type_cleanup(name):
ret = mcgen('''
void qapi_free_%(type)s(%(c_type)s obj)
void qapi_free_%(name)s(%(c_type)s obj)
{
QapiDeallocVisitor *md;
Visitor *v;
@ -268,72 +264,23 @@ void qapi_free_%(type)s(%(c_type)s obj)
md = qapi_dealloc_visitor_new();
v = qapi_dealloc_get_visitor(md);
visit_type_%(type)s(v, &obj, NULL, NULL);
visit_type_%(name)s(v, &obj, NULL, NULL);
qapi_dealloc_visitor_cleanup(md);
}
''',
c_type=c_type(name),type=name)
c_type=c_type(name), name=c_name(name))
return ret
try:
opts, args = getopt.gnu_getopt(sys.argv[1:], "chbp:i:o:",
["source", "header", "builtins",
"prefix=", "input-file=", "output-dir="])
except getopt.GetoptError, err:
print str(err)
sys.exit(1)
output_dir = ""
input_file = ""
prefix = ""
c_file = 'qapi-types.c'
h_file = 'qapi-types.h'
do_c = False
do_h = False
do_builtins = False
(input_file, output_dir, do_c, do_h, prefix, opts) = \
parse_command_line("b", ["builtins"])
for o, a in opts:
if o in ("-p", "--prefix"):
prefix = a
elif o in ("-i", "--input-file"):
input_file = a
elif o in ("-o", "--output-dir"):
output_dir = a + "/"
elif o in ("-c", "--source"):
do_c = True
elif o in ("-h", "--header"):
do_h = True
elif o in ("-b", "--builtins"):
if o in ("-b", "--builtins"):
do_builtins = True
if not do_c and not do_h:
do_c = True
do_h = True
c_file = output_dir + prefix + c_file
h_file = output_dir + prefix + h_file
try:
os.makedirs(output_dir)
except os.error, e:
if e.errno != errno.EEXIST:
raise
def maybe_open(really, name, opt):
if really:
return open(name, opt)
else:
import StringIO
return StringIO.StringIO()
fdef = maybe_open(do_c, c_file, 'w')
fdecl = maybe_open(do_h, h_file, 'w')
fdef.write(mcgen('''
/* AUTOMATICALLY GENERATED, DO NOT MODIFY */
c_comment = '''
/*
* deallocation functions for schema-defined QAPI types
*
@ -347,16 +294,8 @@ fdef.write(mcgen('''
* See the COPYING.LIB file in the top-level directory.
*
*/
#include "qapi/dealloc-visitor.h"
#include "%(prefix)sqapi-types.h"
#include "%(prefix)sqapi-visit.h"
''', prefix=prefix))
fdecl.write(mcgen('''
/* AUTOMATICALLY GENERATED, DO NOT MODIFY */
'''
h_comment = '''
/*
* schema-defined QAPI types
*
@ -369,15 +308,25 @@ fdecl.write(mcgen('''
* See the COPYING.LIB file in the top-level directory.
*
*/
'''
#ifndef %(guard)s
#define %(guard)s
(fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix,
'qapi-types.c', 'qapi-types.h',
c_comment, h_comment)
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>
''',
guard=guardname(h_file)))
'''))
exprs = parse_schema(input_file)
exprs = filter(lambda expr: not expr.has_key('gen'), exprs)
@ -455,12 +404,4 @@ for expr in exprs:
continue
fdecl.write(ret)
fdecl.write('''
#endif
''')
fdecl.flush()
fdecl.close()
fdef.flush()
fdef.close()
close_output(fdef, fdecl)

View File

@ -15,10 +15,6 @@
from ordereddict import OrderedDict
from qapi import *
import re
import sys
import os
import getopt
import errno
implicit_structs = []
@ -56,7 +52,7 @@ static void visit_type_%(name)s_fields(Visitor *m, %(name)s **obj, Error **errp)
{
Error *err = NULL;
''',
name=name)
name=c_name(name))
push_indent()
if base:
@ -66,7 +62,7 @@ if (err) {
goto out;
}
''',
type=type_name(base), c_name=c_var('base'))
type=type_name(base), c_name=c_name('base'))
for argname, argentry, optional in parse_args(members):
if optional:
@ -74,13 +70,13 @@ if (err) {
visit_optional(m, &(*obj)->has_%(c_name)s, "%(name)s", &err);
if (!err && (*obj)->has_%(c_name)s) {
''',
c_name=c_var(argname), name=argname)
c_name=c_name(argname), name=argname)
push_indent()
ret += mcgen('''
visit_type_%(type)s(m, &(*obj)->%(c_name)s, "%(name)s", &err);
''',
type=type_name(argentry), c_name=c_var(argname),
type=type_name(argentry), c_name=c_name(argname),
name=argname)
if optional:
@ -111,16 +107,16 @@ def generate_visit_struct_body(name, members):
ret = mcgen('''
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) {
if (*obj) {
visit_type_%(name)s_fields(m, obj, errp);
visit_type_%(c_name)s_fields(m, obj, errp);
}
visit_end_struct(m, &err);
}
error_propagate(errp, err);
''',
name=name)
name=name, c_name=c_name(name))
return ret
@ -137,7 +133,7 @@ def generate_visit_struct(expr):
void visit_type_%(name)s(Visitor *m, %(name)s **obj, const char *name, Error **errp)
{
''',
name=name)
name=c_name(name))
ret += generate_visit_struct_body(name, members)
@ -173,7 +169,7 @@ out:
error_propagate(errp, err);
}
''',
name=name)
name=type_name(name))
def generate_visit_enum(name, members):
return mcgen('''
@ -183,7 +179,7 @@ void visit_type_%(name)s(Visitor *m, %(name)s *obj, const char *name, Error **er
visit_type_enum(m, (int *)obj, %(name)s_lookup, "%(name)s", name, errp);
}
''',
name=name)
name=c_name(name))
def generate_visit_alternate(name, members):
ret = mcgen('''
@ -202,11 +198,11 @@ void visit_type_%(name)s(Visitor *m, %(name)s **obj, const char *name, Error **e
}
switch ((*obj)->kind) {
''',
name=name)
name=c_name(name))
# For alternate, always use the default enum type automatically generated
# as "'%sKind' % (name)"
disc_type = '%sKind' % (name)
# as name + 'Kind'
disc_type = c_name(name) + 'Kind'
for key in members:
assert (members[key] in builtin_types.keys()
@ -214,7 +210,7 @@ void visit_type_%(name)s(Visitor *m, %(name)s **obj, const char *name, Error **e
or find_union(members[key])
or find_enum(members[key])), "Invalid alternate member"
enum_full_value = generate_enum_full_value(disc_type, key)
enum_full_value = c_enum_const(disc_type, key)
ret += mcgen('''
case %(enum_full_value)s:
visit_type_%(c_type)s(m, &(*obj)->%(c_name)s, name, &err);
@ -222,7 +218,7 @@ void visit_type_%(name)s(Visitor *m, %(name)s **obj, const char *name, Error **e
''',
enum_full_value = enum_full_value,
c_type = type_name(members[key]),
c_name = c_fun(key))
c_name = c_name(key))
ret += mcgen('''
default:
@ -252,12 +248,12 @@ def generate_visit_union(expr):
if enum_define:
# Use the enum type as discriminator
ret = ""
disc_type = enum_define['enum_name']
disc_type = c_name(enum_define['enum_name'])
else:
# There will always be a discriminator in the C switch code, by default
# it is an enum type generated silently as "'%sKind' % (name)"
ret = generate_visit_enum('%sKind' % name, members.keys())
disc_type = '%sKind' % (name)
# it is an enum type generated silently
ret = generate_visit_enum(name + 'Kind', members.keys())
disc_type = c_name(name) + 'Kind'
if base:
assert discriminator
@ -281,7 +277,7 @@ void visit_type_%(name)s(Visitor *m, %(name)s **obj, const char *name, Error **e
}
if (*obj) {
''',
name=name)
name=c_name(name))
if base:
ret += mcgen('''
@ -290,7 +286,7 @@ void visit_type_%(name)s(Visitor *m, %(name)s **obj, const char *name, Error **e
goto out_obj;
}
''',
name=name)
name=c_name(name))
if not discriminator:
disc_key = "type"
@ -315,7 +311,7 @@ void visit_type_%(name)s(Visitor *m, %(name)s **obj, const char *name, Error **e
else:
fmt = 'visit_type_implicit_%(c_type)s(m, &(*obj)->%(c_name)s, &err);'
enum_full_value = generate_enum_full_value(disc_type, key)
enum_full_value = c_enum_const(disc_type, key)
ret += mcgen('''
case %(enum_full_value)s:
''' + fmt + '''
@ -323,7 +319,7 @@ void visit_type_%(name)s(Visitor *m, %(name)s **obj, const char *name, Error **e
''',
enum_full_value = enum_full_value,
c_type=type_name(members[key]),
c_name=c_fun(key))
c_name=c_name(key))
ret += mcgen('''
default:
@ -347,6 +343,7 @@ out:
def generate_declaration(name, members, builtin_type=False):
ret = ""
if not builtin_type:
name = c_name(name)
ret += mcgen('''
void visit_type_%(name)s(Visitor *m, %(name)s **obj, const char *name, Error **errp);
@ -364,7 +361,7 @@ def generate_enum_declaration(name, members):
ret = mcgen('''
void visit_type_%(name)sList(Visitor *m, %(name)sList **obj, const char *name, Error **errp);
''',
name=name)
name=c_name(name))
return ret
@ -373,108 +370,62 @@ def generate_decl_enum(name, members):
void visit_type_%(name)s(Visitor *m, %(name)s *obj, const char *name, Error **errp);
''',
name=name)
name=c_name(name))
try:
opts, args = getopt.gnu_getopt(sys.argv[1:], "chbp:i:o:",
["source", "header", "builtins", "prefix=",
"input-file=", "output-dir="])
except getopt.GetoptError, err:
print str(err)
sys.exit(1)
input_file = ""
output_dir = ""
prefix = ""
c_file = 'qapi-visit.c'
h_file = 'qapi-visit.h'
do_c = False
do_h = False
do_builtins = False
(input_file, output_dir, do_c, do_h, prefix, opts) = \
parse_command_line("b", ["builtins"])
for o, a in opts:
if o in ("-p", "--prefix"):
prefix = a
elif o in ("-i", "--input-file"):
input_file = a
elif o in ("-o", "--output-dir"):
output_dir = a + "/"
elif o in ("-c", "--source"):
do_c = True
elif o in ("-h", "--header"):
do_h = True
elif o in ("-b", "--builtins"):
if o in ("-b", "--builtins"):
do_builtins = True
if not do_c and not do_h:
do_c = True
do_h = True
c_comment = '''
/*
* schema-defined QAPI visitor functions
*
* Copyright IBM, Corp. 2011
*
* Authors:
* Anthony Liguori <aliguori@us.ibm.com>
*
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
* See the COPYING.LIB file in the top-level directory.
*
*/
'''
h_comment = '''
/*
* schema-defined QAPI visitor functions
*
* Copyright IBM, Corp. 2011
*
* Authors:
* Anthony Liguori <aliguori@us.ibm.com>
*
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
* See the COPYING.LIB file in the top-level directory.
*
*/
'''
c_file = output_dir + prefix + c_file
h_file = output_dir + prefix + h_file
try:
os.makedirs(output_dir)
except os.error, e:
if e.errno != errno.EEXIST:
raise
def maybe_open(really, name, opt):
if really:
return open(name, opt)
else:
import StringIO
return StringIO.StringIO()
fdef = maybe_open(do_c, c_file, 'w')
fdecl = maybe_open(do_h, h_file, 'w')
(fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix,
'qapi-visit.c', 'qapi-visit.h',
c_comment, h_comment)
fdef.write(mcgen('''
/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
/*
* schema-defined QAPI visitor functions
*
* Copyright IBM, Corp. 2011
*
* Authors:
* Anthony Liguori <aliguori@us.ibm.com>
*
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
* See the COPYING.LIB file in the top-level directory.
*
*/
#include "qemu-common.h"
#include "%(header)s"
#include "%(prefix)sqapi-visit.h"
''',
header=basename(h_file)))
prefix = prefix))
fdecl.write(mcgen('''
/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
/*
* schema-defined QAPI visitor functions
*
* Copyright IBM, Corp. 2011
*
* Authors:
* Anthony Liguori <aliguori@us.ibm.com>
*
* This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
* See the COPYING.LIB file in the top-level directory.
*
*/
#ifndef %(guard)s
#define %(guard)s
#include "qapi/visitor.h"
#include "%(prefix)sqapi-types.h"
''',
prefix=prefix, guard=guardname(h_file)))
prefix=prefix))
exprs = parse_schema(input_file)
@ -530,12 +481,4 @@ for expr in exprs:
ret += generate_enum_declaration(expr['enum'], expr['data'])
fdecl.write(ret)
fdecl.write('''
#endif
''')
fdecl.flush()
fdecl.close()
fdef.flush()
fdef.close()
close_output(fdef, fdecl)

View File

@ -13,8 +13,11 @@
import re
from ordereddict import OrderedDict
import errno
import getopt
import os
import sys
import string
builtin_types = {
'str': 'QTYPE_QSTRING',
@ -537,7 +540,7 @@ def check_union(expr, expr_info):
# Otherwise, check for conflicts in the generated enum
else:
c_key = _generate_enum_string(key)
c_key = camel_to_upper(key)
if c_key in values:
raise QAPIExprError(expr_info,
"Union '%s' member '%s' clashes with '%s'"
@ -555,7 +558,7 @@ def check_alternate(expr, expr_info):
check_name(expr_info, "Member of alternate '%s'" % name, key)
# Check for conflicts in the generated enum
c_key = _generate_enum_string(key)
c_key = camel_to_upper(key)
if c_key in values:
raise QAPIExprError(expr_info,
"Alternate '%s' member '%s' clashes with '%s'"
@ -586,7 +589,7 @@ def check_enum(expr, expr_info):
for member in members:
check_name(expr_info, "Member of enum '%s'" %name, member,
enum_member=True)
key = _generate_enum_string(member)
key = camel_to_upper(member)
if key in values:
raise QAPIExprError(expr_info,
"Enum '%s' member '%s' clashes with '%s'"
@ -728,17 +731,6 @@ def parse_args(typeinfo):
# value of an optional argument.
yield (argname, argentry, optional)
def de_camel_case(name):
new_name = ''
for ch in name:
if ch.isupper() and new_name:
new_name += '_'
if ch == '-':
new_name += '_'
else:
new_name += ch.lower()
return new_name
def camel_case(name):
new_name = ''
first = True
@ -752,7 +744,43 @@ def camel_case(name):
new_name += ch.lower()
return new_name
def c_var(name, protect=True):
# ENUMName -> ENUM_NAME, EnumName1 -> ENUM_NAME1
# ENUM_NAME -> ENUM_NAME, ENUM_NAME1 -> ENUM_NAME1, ENUM_Name2 -> ENUM_NAME2
# ENUM24_Name -> ENUM24_NAME
def camel_to_upper(value):
c_fun_str = c_name(value, False)
if value.isupper():
return c_fun_str
new_name = ''
l = len(c_fun_str)
for i in range(l):
c = c_fun_str[i]
# When c is upper and no "_" appears before, do more checks
if c.isupper() and (i > 0) and c_fun_str[i - 1] != "_":
# Case 1: next string is lower
# Case 2: previous string is digit
if (i < (l - 1) and c_fun_str[i + 1].islower()) or \
c_fun_str[i - 1].isdigit():
new_name += '_'
new_name += c
return new_name.lstrip('_').upper()
def c_enum_const(type_name, const_name):
return camel_to_upper(type_name + '_' + const_name)
c_name_trans = string.maketrans('.-', '__')
# Map @name to a valid C identifier.
# If @protect, avoid returning certain ticklish identifiers (like
# C keywords) by prepending "q_".
#
# Used for converting 'name' from a 'name':'type' qapi definition
# into a generated struct member, as well as converting type names
# into substrings of a generated C function name.
# '__a.b_c' -> '__a_b_c', 'x-foo' -> 'x_foo'
# protect=True: 'int' -> 'q_int'; protect=False: 'int' -> 'int'
def c_name(name, protect=True):
# ANSI X3J11/88-090, 3.1.1
c89_words = set(['auto', 'break', 'case', 'char', 'const', 'continue',
'default', 'do', 'double', 'else', 'enum', 'extern', 'float',
@ -781,18 +809,27 @@ def c_var(name, protect=True):
polluted_words = set(['unix', 'errno'])
if protect and (name in c89_words | c99_words | c11_words | gcc_words | cpp_words | polluted_words):
return "q_" + name
return name.replace('-', '_').lstrip("*")
def c_fun(name, protect=True):
return c_var(name, protect).replace('.', '_')
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 '%sList' % name
return type_name(name) + 'List'
def type_name(name):
if type(name) == list:
return c_list_type(name[0])
return name
# 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)
def add_name(name, info, meta, implicit = False):
global all_names
@ -849,42 +886,48 @@ def is_enum(name):
return find_enum(name) != None
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(name, is_param=False):
if name == 'str':
def c_type(value, is_param=False):
if value == 'str':
if is_param:
return 'const char *' + eatspace
return 'char *' + eatspace
return 'const char' + pointer_suffix
return 'char' + pointer_suffix
elif name == 'int':
elif value == 'int':
return 'int64_t'
elif (name == 'int8' or name == 'int16' or name == 'int32' or
name == 'int64' or name == 'uint8' or name == 'uint16' or
name == 'uint32' or name == 'uint64'):
return name + '_t'
elif name == 'size':
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 name == 'bool':
elif value == 'bool':
return 'bool'
elif name == 'number':
elif value == 'number':
return 'double'
elif type(name) == list:
return '%s *%s' % (c_list_type(name[0]), eatspace)
elif is_enum(name):
return name
elif name == None or len(name) == 0:
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 name in events:
return '%sEvent *%s' % (camel_case(name), eatspace)
elif value in events:
return camel_case(value) + 'Event' + pointer_suffix
else:
return '%s *%s' % (name, eatspace)
# complex type name
assert isinstance(value, str) and value != ""
return c_name(value) + pointer_suffix
def is_c_ptr(name):
suffix = "*" + eatspace
return c_type(name).endswith(suffix)
def is_c_ptr(value):
return c_type(value).endswith(pointer_suffix)
def genindent(count):
ret = ""
@ -938,29 +981,88 @@ def guardend(name):
''',
name=guardname(name))
# ENUMName -> ENUM_NAME, EnumName1 -> ENUM_NAME1
# ENUM_NAME -> ENUM_NAME, ENUM_NAME1 -> ENUM_NAME1, ENUM_Name2 -> ENUM_NAME2
# ENUM24_Name -> ENUM24_NAME
def _generate_enum_string(value):
c_fun_str = c_fun(value, False)
if value.isupper():
return c_fun_str
def parse_command_line(extra_options = "", extra_long_options = []):
new_name = ''
l = len(c_fun_str)
for i in range(l):
c = c_fun_str[i]
# When c is upper and no "_" appears before, do more checks
if c.isupper() and (i > 0) and c_fun_str[i - 1] != "_":
# Case 1: next string is lower
# Case 2: previous string is digit
if (i < (l - 1) and c_fun_str[i + 1].islower()) or \
c_fun_str[i - 1].isdigit():
new_name += '_'
new_name += c
return new_name.lstrip('_').upper()
try:
opts, args = getopt.gnu_getopt(sys.argv[1:],
"chp:o:" + extra_options,
["source", "header", "prefix=",
"output-dir="] + extra_long_options)
except getopt.GetoptError, err:
print >>sys.stderr, "%s: %s" % (sys.argv[0], str(err))
sys.exit(1)
def generate_enum_full_value(enum_name, enum_value):
abbrev_string = _generate_enum_string(enum_name)
value_string = _generate_enum_string(enum_value)
return "%s_%s" % (abbrev_string, value_string)
output_dir = ""
prefix = ""
do_c = False
do_h = False
extra_opts = []
for oa in opts:
o, a = oa
if o in ("-p", "--prefix"):
prefix = a
elif o in ("-o", "--output-dir"):
output_dir = a + "/"
elif o in ("-c", "--source"):
do_c = True
elif o in ("-h", "--header"):
do_h = True
else:
extra_opts.append(oa)
if not do_c and not do_h:
do_c = True
do_h = True
if len(args) != 1:
print >>sys.stderr, "%s: need exactly one argument" % sys.argv[0]
sys.exit(1)
input_file = args[0]
return (input_file, output_dir, do_c, do_h, prefix, extra_opts)
def open_output(output_dir, do_c, do_h, prefix, c_file, h_file,
c_comment, h_comment):
c_file = output_dir + prefix + c_file
h_file = output_dir + prefix + h_file
try:
os.makedirs(output_dir)
except os.error, e:
if e.errno != errno.EEXIST:
raise
def maybe_open(really, name, opt):
if really:
return open(name, opt)
else:
import StringIO
return StringIO.StringIO()
fdef = maybe_open(do_c, c_file, 'w')
fdecl = maybe_open(do_h, h_file, 'w')
fdef.write(mcgen('''
/* AUTOMATICALLY GENERATED, DO NOT MODIFY */
%(comment)s
''',
comment = c_comment))
fdecl.write(mcgen('''
/* AUTOMATICALLY GENERATED, DO NOT MODIFY */
%(comment)s
#ifndef %(guard)s
#define %(guard)s
''',
comment = h_comment, guard = guardname(h_file)))
return (fdef, fdecl)
def close_output(fdef, fdecl):
fdecl.write('''
#endif
''')
fdecl.close()
fdef.close()

View File

@ -301,24 +301,24 @@ tests/test-vmstate$(EXESUF): tests/test-vmstate.o \
libqemuutil.a libqemustub.a
tests/test-qapi-types.c tests/test-qapi-types.h :\
$(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-types.py
$(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-types.py $(qapi-py)
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-types.py \
$(gen-out-type) -o tests -p "test-" -i $<, \
$(gen-out-type) -o tests -p "test-" $<, \
" GEN $@")
tests/test-qapi-visit.c tests/test-qapi-visit.h :\
$(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-visit.py
$(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-visit.py $(qapi-py)
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py \
$(gen-out-type) -o tests -p "test-" -i $<, \
$(gen-out-type) -o tests -p "test-" $<, \
" GEN $@")
tests/test-qmp-commands.h tests/test-qmp-marshal.c :\
$(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-commands.py
$(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-commands.py $(qapi-py)
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py \
$(gen-out-type) -o tests -p "test-" -i $<, \
$(gen-out-type) -o tests -p "test-" $<, \
" GEN $@")
tests/test-qapi-event.c tests/test-qapi-event.h :\
$(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-event.py
$(SRC_PATH)/tests/qapi-schema/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-event.py $(qapi-py)
$(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-event.py \
$(gen-out-type) -o tests -p "test-" -i $<, \
$(gen-out-type) -o tests -p "test-" $<, \
" GEN $@")
tests/test-string-output-visitor$(EXESUF): tests/test-string-output-visitor.o $(test-qapi-obj-y) libqemuutil.a libqemustub.a

View File

@ -107,3 +107,23 @@
'data': { '*a': 'int', '*b': 'UserDefOne', 'c': 'str' } }
{ 'event': 'EVENT_D',
'data': { 'a' : 'EventStructOne', 'b' : 'str', '*c': 'str', '*enum3': 'EnumOne' } }
# test that we correctly compile downstream extensions
{ 'enum': '__org.qemu_x-Enum', 'data': [ '__org.qemu_x-value' ] }
{ 'struct': '__org.qemu_x-Base',
'data': { '__org.qemu_x-member1': '__org.qemu_x-Enum' } }
{ 'struct': '__org.qemu_x-Struct', 'base': '__org.qemu_x-Base',
'data': { '__org.qemu_x-member2': 'str' } }
{ 'union': '__org.qemu_x-Union1', 'data': { '__org.qemu_x-branch': 'str' } }
{ 'struct': '__org.qemu_x-Struct2',
'data': { 'array': ['__org.qemu_x-Union1'] } }
{ 'union': '__org.qemu_x-Union2', 'base': '__org.qemu_x-Base',
'discriminator': '__org.qemu_x-member1',
'data': { '__org.qemu_x-value': '__org.qemu_x-Struct2' } }
{ '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' }
{ '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' },
'returns': '__org.qemu_x-Union1' }

View File

@ -22,10 +22,22 @@
OrderedDict([('event', 'EVENT_A')]),
OrderedDict([('event', 'EVENT_B'), ('data', OrderedDict())]),
OrderedDict([('event', 'EVENT_C'), ('data', OrderedDict([('*a', 'int'), ('*b', 'UserDefOne'), ('c', 'str')]))]),
OrderedDict([('event', 'EVENT_D'), ('data', OrderedDict([('a', 'EventStructOne'), ('b', 'str'), ('*c', 'str'), ('*enum3', 'EnumOne')]))])]
OrderedDict([('event', 'EVENT_D'), ('data', OrderedDict([('a', 'EventStructOne'), ('b', 'str'), ('*c', 'str'), ('*enum3', 'EnumOne')]))]),
OrderedDict([('enum', '__org.qemu_x-Enum'), ('data', ['__org.qemu_x-value'])]),
OrderedDict([('struct', '__org.qemu_x-Base'), ('data', OrderedDict([('__org.qemu_x-member1', '__org.qemu_x-Enum')]))]),
OrderedDict([('struct', '__org.qemu_x-Struct'), ('base', '__org.qemu_x-Base'), ('data', OrderedDict([('__org.qemu_x-member2', 'str')]))]),
OrderedDict([('union', '__org.qemu_x-Union1'), ('data', OrderedDict([('__org.qemu_x-branch', 'str')]))]),
OrderedDict([('struct', '__org.qemu_x-Struct2'), ('data', OrderedDict([('array', ['__org.qemu_x-Union1'])]))]),
OrderedDict([('union', '__org.qemu_x-Union2'), ('base', '__org.qemu_x-Base'), ('discriminator', '__org.qemu_x-member1'), ('data', OrderedDict([('__org.qemu_x-value', '__org.qemu_x-Struct2')]))]),
OrderedDict([('alternate', '__org.qemu_x-Alt'), ('data', OrderedDict([('__org.qemu_x-branch', 'str'), ('b', '__org.qemu_x-Base')]))]),
OrderedDict([('event', '__ORG.QEMU_X-EVENT'), ('data', '__org.qemu_x-Struct')]),
OrderedDict([('command', '__org.qemu_x-command'), ('data', OrderedDict([('a', ['__org.qemu_x-Enum']), ('b', ['__org.qemu_x-Struct']), ('c', '__org.qemu_x-Union2'), ('d', '__org.qemu_x-Alt')])), ('returns', '__org.qemu_x-Union1')])]
[{'enum_name': 'EnumOne', 'enum_values': ['value1', 'value2', 'value3']},
{'enum_name': '__org.qemu_x-Enum', 'enum_values': ['__org.qemu_x-value']},
{'enum_name': 'UserDefAlternateKind', 'enum_values': None},
{'enum_name': 'UserDefNativeListUnionKind', 'enum_values': None}]
{'enum_name': 'UserDefNativeListUnionKind', 'enum_values': None},
{'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')]))]),
@ -37,4 +49,7 @@
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', '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')]))]),
OrderedDict([('struct', '__org.qemu_x-Struct'), ('base', '__org.qemu_x-Base'), ('data', OrderedDict([('__org.qemu_x-member2', 'str')]))]),
OrderedDict([('struct', '__org.qemu_x-Struct2'), ('data', OrderedDict([('array', ['__org.qemu_x-Union1'])]))])]

View File

@ -51,6 +51,21 @@ int64_t qmp_user_def_cmd3(int64_t a, bool has_b, int64_t b, Error **errp)
return a + (has_b ? b : 0);
}
__org_qemu_x_Union1 *qmp___org_qemu_x_command(__org_qemu_x_EnumList *a,
__org_qemu_x_StructList *b,
__org_qemu_x_Union2 *c,
__org_qemu_x_Alt *d,
Error **errp)
{
__org_qemu_x_Union1 *ret = g_new0(__org_qemu_x_Union1, 1);
ret->kind = ORG_QEMU_X_UNION1_KIND___ORG_QEMU_X_BRANCH;
ret->__org_qemu_x_branch = strdup("blah1");
return ret;
}
/* test commands with no input and no return value */
static void test_dispatch_cmd(void)
{