aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile14
-rw-r--r--cpus.c1
-rw-r--r--docs/qapi-code-gen.txt10
-rw-r--r--docs/qmp/qmp-events.txt4
-rw-r--r--qapi-schema.json8
-rw-r--r--qmp-commands.hx7
-rw-r--r--scripts/qapi-commands.py222
-rw-r--r--scripts/qapi-event.py125
-rw-r--r--scripts/qapi-types.py147
-rw-r--r--scripts/qapi-visit.py151
-rw-r--r--scripts/qapi.py244
-rw-r--r--tests/Makefile16
-rw-r--r--tests/qapi-schema/qapi-schema-test.json20
-rw-r--r--tests/qapi-schema/qapi-schema-test.out21
-rw-r--r--tests/test-qmp-commands.c15
15 files changed, 453 insertions, 552 deletions
diff --git a/Makefile b/Makefile
index f032158..d945804 100644
--- a/Makefile
+++ b/Makefile
@@ -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)
diff --git a/cpus.c b/cpus.c
index 62d157a..de6469f 100644
--- a/cpus.c
+++ b/cpus.c
@@ -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;
diff --git a/docs/qapi-code-gen.txt b/docs/qapi-code-gen.txt
index 269a1f3..3f0522e 100644
--- a/docs/qapi-code-gen.txt
+++ b/docs/qapi-code-gen.txt
@@ -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...]
diff --git a/docs/qmp/qmp-events.txt b/docs/qmp/qmp-events.txt
index 6dc2cca..4c13d48 100644
--- a/docs/qmp/qmp-events.txt
+++ b/docs/qmp/qmp-events.txt
@@ -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"
},
diff --git a/qapi-schema.json b/qapi-schema.json
index 9c92482..f97ffa1 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -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:
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 7506774..14e109e 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -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
}
]
diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py
index 93e43f0..1c1d3aa 100644
--- a/scripts/qapi-commands.py
+++ b/scripts/qapi-commands.py
@@ -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,12 +309,22 @@ 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
+
+(input_file, output_dir, do_c, do_h, prefix, opts) = \
+ parse_command_line("m", ["middle"])
+
+for o, a in opts:
+ if o in ("-m", "--middle"):
+ middle_mode = True
+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 QAPI function prototypes
+ * schema-defined QMP->QAPI command dispatch
*
* Copyright IBM, Corp. 2011
*
@@ -334,24 +335,10 @@ def gen_command_decl_prologue(header, guard, prefix=""):
* See the COPYING.LIB file in the top-level directory.
*
*/
-
-#ifndef %(guard)s
-#define %(guard)s
-
-#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 */
-
+'''
+h_comment = '''
/*
- * schema-defined QMP->QAPI command dispatch
+ * schema-defined QAPI function prototypes
*
* Copyright IBM, Corp. 2011
*
@@ -362,7 +349,13 @@ def gen_command_def_prologue(prefix="", proxy=False):
* 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,107 +367,40 @@ 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"
-
-
-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)
-
-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
+ prefix=prefix))
-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)
+fdecl.write(mcgen('''
+#include "%(prefix)sqapi-types.h"
+#include "qapi/qmp/qdict.h"
+#include "qapi/error.h"
-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)
+''',
+ prefix=prefix))
+
+for cmd in commands:
+ arglist = []
+ ret_type = None
+ if cmd.has_key('data'):
+ arglist = cmd['data']
+ if cmd.has_key('returns'):
+ ret_type = cmd['returns']
+ ret = generate_command_decl(cmd['command'], arglist, ret_type) + "\n"
fdecl.write(ret)
- ret = gen_command_def_prologue(prefix=prefix)
- fdef.write(ret)
-
- for cmd in commands:
- arglist = []
- ret_type = None
- if cmd.has_key('data'):
- arglist = cmd['data']
- if cmd.has_key('returns'):
- ret_type = cmd['returns']
- ret = generate_command_decl(cmd['command'], arglist, ret_type) + "\n"
- fdecl.write(ret)
- if ret_type:
- ret = gen_marshal_output(cmd['command'], arglist, ret_type, middle_mode) + "\n"
- fdef.write(ret)
-
- if middle_mode:
- fdecl.write('%s;\n' % gen_marshal_input_decl(cmd['command'], arglist, ret_type, middle_mode))
-
- ret = gen_marshal_input(cmd['command'], arglist, ret_type, middle_mode) + "\n"
+ if ret_type:
+ ret = gen_marshal_output(cmd['command'], arglist, ret_type, middle_mode) + "\n"
fdef.write(ret)
- fdecl.write("\n#endif\n");
+ if middle_mode:
+ fdecl.write('%s;\n' % gen_marshal_input_decl(cmd['command'], arglist, ret_type, middle_mode))
- if not middle_mode:
- ret = gen_registry(commands)
- fdef.write(ret)
+ ret = gen_marshal_input(cmd['command'], arglist, ret_type, middle_mode) + "\n"
+ fdef.write(ret)
+
+if not middle_mode:
+ ret = gen_registry(commands)
+ fdef.write(ret)
- fdef.flush()
- fdef.close()
- fdecl.flush()
- fdecl.close()
+close_output(fdef, fdecl)
diff --git a/scripts/qapi-event.py b/scripts/qapi-event.py
index 47dc041..56bc602 100644
--- a/scripts/qapi-event.py
+++ b/scripts/qapi-event.py
@@ -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,19 +227,8 @@ fdef.write(mcgen('''
* See the COPYING.LIB file in the top-level directory.
*
*/
-
-#include "qemu-common.h"
-#include "%(header)s"
-#include "%(prefix)sqapi-visit.h"
-#include "qapi/qmp-output-visitor.h"
-#include "qapi/qmp-event.h"
-
-''',
- prefix=prefix, header=basename(h_file)))
-
-fdecl.write(mcgen('''
-/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
-
+'''
+h_comment = '''
/*
* schema-defined QAPI event functions
*
@@ -314,16 +241,29 @@ 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-event.c', 'qapi-event.h',
+ c_comment, h_comment)
+fdef.write(mcgen('''
+#include "qemu-common.h"
+#include "%(prefix)sqapi-event.h"
+#include "%(prefix)sqapi-visit.h"
+#include "qapi/qmp-output-visitor.h"
+#include "qapi/qmp-event.h"
+
+''',
+ prefix=prefix))
+
+fdecl.write(mcgen('''
#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)
diff --git a/scripts/qapi-types.py b/scripts/qapi-types.py
index 2bf8145..6bd0b13 100644
--- a/scripts/qapi-types.py
+++ b/scripts/qapi-types.py
@@ -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())
+ qtype = qtype,
+ 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)
diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py
index 0e67b33..5b99336 100644
--- a/scripts/qapi-visit.py
+++ b/scripts/qapi-visit.py
@@ -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,66 +370,18 @@ def generate_decl_enum(name, members):
void visit_type_%(name)s(Visitor *m, %(name)s *obj, const char *name, Error **errp);
''',
- 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
+ name=c_name(name))
+
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('''
-/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
-
+c_comment = '''
/*
* schema-defined QAPI visitor functions
*
@@ -445,15 +394,8 @@ fdef.write(mcgen('''
* See the COPYING.LIB file in the top-level directory.
*
*/
-
-#include "qemu-common.h"
-#include "%(header)s"
-''',
- header=basename(h_file)))
-
-fdecl.write(mcgen('''
-/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */
-
+'''
+h_comment = '''
/*
* schema-defined QAPI visitor functions
*
@@ -466,15 +408,24 @@ fdecl.write(mcgen('''
* See the COPYING.LIB file in the top-level directory.
*
*/
+'''
+
+(fdef, fdecl) = open_output(output_dir, do_c, do_h, prefix,
+ 'qapi-visit.c', 'qapi-visit.h',
+ c_comment, h_comment)
-#ifndef %(guard)s
-#define %(guard)s
+fdef.write(mcgen('''
+#include "qemu-common.h"
+#include "%(prefix)sqapi-visit.h"
+''',
+ prefix = prefix))
+fdecl.write(mcgen('''
#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)
diff --git a/scripts/qapi.py b/scripts/qapi.py
index 166b74f..f96a777 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -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)
+
+ 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 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)
+def close_output(fdef, fdecl):
+ fdecl.write('''
+#endif
+''')
+ fdecl.close()
+ fdef.close()
diff --git a/tests/Makefile b/tests/Makefile
index 666aee2..729b969 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -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
diff --git a/tests/qapi-schema/qapi-schema-test.json b/tests/qapi-schema/qapi-schema-test.json
index 8193dc1..c7eaa86 100644
--- a/tests/qapi-schema/qapi-schema-test.json
+++ b/tests/qapi-schema/qapi-schema-test.json
@@ -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' }
diff --git a/tests/qapi-schema/qapi-schema-test.out b/tests/qapi-schema/qapi-schema-test.out
index 93c4963..cf0ccc4 100644
--- a/tests/qapi-schema/qapi-schema-test.out
+++ b/tests/qapi-schema/qapi-schema-test.out
@@ -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'])]))])]
diff --git a/tests/test-qmp-commands.c b/tests/test-qmp-commands.c
index ad2e403..9918f23 100644
--- a/tests/test-qmp-commands.c
+++ b/tests/test-qmp-commands.c
@@ -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)
{