From patchwork Tue Jul 24 17:20:35 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Roth X-Patchwork-Id: 172976 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 021802C0088 for ; Wed, 25 Jul 2012 03:22:01 +1000 (EST) Received: from localhost ([::1]:36078 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Stio2-0003Zz-V3 for incoming@patchwork.ozlabs.org; Tue, 24 Jul 2012 13:21:59 -0400 Received: from eggs.gnu.org ([208.118.235.92]:49421) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Stinc-0003EY-Pm for qemu-devel@nongnu.org; Tue, 24 Jul 2012 13:21:37 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1StinW-0000Pt-9h for qemu-devel@nongnu.org; Tue, 24 Jul 2012 13:21:32 -0400 Received: from mail-yx0-f173.google.com ([209.85.213.173]:60081) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1StinW-0000Pm-4E for qemu-devel@nongnu.org; Tue, 24 Jul 2012 13:21:26 -0400 Received: by yenl1 with SMTP id l1so7029819yen.4 for ; Tue, 24 Jul 2012 10:21:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:x-mailer:in-reply-to :references; bh=QLM5sT1Ysfkh/+avmHNQUpgbGEKYSmaF2e39SIeElVg=; b=lyjDA56Sa1lzhVslp3v8VH/cwjny0uZ/0OXCJkeGiESQmwQDcxNhu0D/kuBY40vT5b qogWeKqU3ssgTrRnKHStzF5pbBiS/bzS47FTSbhcNPn4XHQ9AqZ3TSoF7kbPfj+Ifce3 xBGKqDtjBoypkRzYLhnNlim4zjN5vQ/f06UNIwlZLuw4se4EtXVZ4y8dUWeJBSD7iFyB 8+40PCNI6JW+LBipmF9Fc5S9g0zD5svPJlspq9+nxT8o3myDkhAVuqQMHid6dqf5U33G K1Gz8bATUwBVuureGheBNW15iDPoa5chgnw2z+dfs87V+9eUj1HbBA4m9MRKTneat/Iy I4XQ== Received: by 10.66.74.69 with SMTP id r5mr6180546pav.56.1343150485331; Tue, 24 Jul 2012 10:21:25 -0700 (PDT) Received: from loki.morrigu.org (cpe-72-179-62-111.austin.res.rr.com. [72.179.62.111]) by mx.google.com with ESMTPS id nh8sm12522083pbc.60.2012.07.24.10.21.22 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 24 Jul 2012 10:21:24 -0700 (PDT) From: Michael Roth To: qemu-devel@nongnu.org Date: Tue, 24 Jul 2012 12:20:35 -0500 Message-Id: <1343150454-4677-4-git-send-email-mdroth@linux.vnet.ibm.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1343150454-4677-1-git-send-email-mdroth@linux.vnet.ibm.com> References: <1343150454-4677-1-git-send-email-mdroth@linux.vnet.ibm.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.85.213.173 Cc: aliguori@us.ibm.com, quintela@redhat.com, owasserm@redhat.com, yamahata@valinux.co.jp, pbonzini@redhat.com, akong@redhat.com, afaerber@suse.de Subject: [Qemu-devel] [PATCH 03/22] qapi: qapi-commands.py -> qapi_commands.py X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Python doesn't allow "-" in module names, so we need to rename the file so we can re-use bits of the codegen. Signed-off-by: Michael Roth --- Makefile | 8 +- scripts/qapi-commands.py | 476 ---------------------------------------------- scripts/qapi_commands.py | 476 ++++++++++++++++++++++++++++++++++++++++++++++ tests/Makefile | 4 +- 4 files changed, 482 insertions(+), 482 deletions(-) delete mode 100644 scripts/qapi-commands.py create mode 100644 scripts/qapi_commands.py diff --git a/Makefile b/Makefile index 894ff2f..ea9537e 100644 --- a/Makefile +++ b/Makefile @@ -188,8 +188,8 @@ qapi-generated/qga-qapi-visit.c qapi-generated/qga-qapi-visit.h :\ $(SRC_PATH)/qapi-schema-guest.json $(SRC_PATH)/scripts/qapi-visit.py $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-visit.py $(gen-out-type) -o qapi-generated -p "qga-" < $<, " GEN $@") qapi-generated/qga-qmp-commands.h qapi-generated/qga-qmp-marshal.c :\ -$(SRC_PATH)/qapi-schema-guest.json $(SRC_PATH)/scripts/qapi-commands.py - $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py $(gen-out-type) -o qapi-generated -p "qga-" < $<, " GEN $@") +$(SRC_PATH)/qapi-schema-guest.json $(SRC_PATH)/scripts/qapi_commands.py + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi_commands.py $(gen-out-type) -o qapi-generated -p "qga-" < $<, " GEN $@") qapi-types.c qapi-types.h :\ $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi_types.py @@ -198,8 +198,8 @@ qapi-visit.c qapi-visit.h :\ $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi_visit.py $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi_visit.py $(gen-out-type) -o "." < $<, " GEN $@") qmp-commands.h qmp-marshal.c :\ -$(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-commands.py - $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py $(gen-out-type) -m -o "." < $<, " GEN $@") +$(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi_commands.py + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi_commands.py $(gen-out-type) -m -o "." < $<, " GEN $@") QGALIB_OBJ=$(addprefix qapi-generated/, qga-qapi-types.o qga-qapi-visit.o qga-qmp-marshal.o) QGALIB_GEN=$(addprefix qapi-generated/, qga-qapi-types.h qga-qapi-visit.h qga-qmp-commands.h) diff --git a/scripts/qapi-commands.py b/scripts/qapi-commands.py deleted file mode 100644 index 9eed40e..0000000 --- a/scripts/qapi-commands.py +++ /dev/null @@ -1,476 +0,0 @@ -# -# QAPI command marshaller generator -# -# Copyright IBM, Corp. 2011 -# -# Authors: -# Anthony Liguori -# Michael Roth -# -# This work is licensed under the terms of the GNU GPLv2. -# See the COPYING.LIB file in the top-level directory. - -from ordereddict import OrderedDict -from qapi import * -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_decl_enum(name, members, genlist=True): - return mcgen(''' - -void %(visitor)s(Visitor *m, %(name)s * obj, const char *name, Error **errp); -''', - visitor=type_visitor(name)) - -def generate_command_decl(name, args, ret_type): - arglist="" - for argname, argtype, optional, structured in parse_args(args): - argtype = c_type(argtype) - if argtype == "char *": - argtype = "const char *" - if optional: - arglist += "bool has_%s, " % c_var(argname) - arglist += "%s %s, " % (argtype, c_var(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() - -def gen_sync_call(name, args, ret_type, indent=0): - ret = "" - arglist="" - retval="" - if ret_type: - retval = "retval = " - for argname, argtype, optional, structured in parse_args(args): - if optional: - arglist += "has_%s, " % c_var(argname) - arglist += "%s, " % (c_var(argname)) - push_indent(indent) - ret = mcgen(''' -%(retval)sqmp_%(name)s(%(args)serrp); - -''', - name=c_fun(name), args=arglist, retval=retval).rstrip() - if ret_type: - ret += "\n" + mcgen('''' -if (!error_is_set(errp)) { - %(marshal_output_call)s -} -''', - marshal_output_call=gen_marshal_output_call(name, ret_type)).rstrip() - pop_indent(indent) - return ret.rstrip() - - -def gen_marshal_output_call(name, ret_type): - if not ret_type: - return "" - return "qmp_marshal_output_%s(retval, ret, errp);" % c_fun(name) - -def gen_visitor_output_containers_decl(ret_type): - ret = "" - push_indent() - if ret_type: - ret += mcgen(''' -QmpOutputVisitor *mo; -QapiDeallocVisitor *md; -Visitor *v; -''') - pop_indent() - - return ret - -def gen_visitor_input_containers_decl(args): - ret = "" - - push_indent() - if len(args) > 0: - ret += mcgen(''' -QmpInputVisitor *mi; -QapiDeallocVisitor *md; -Visitor *v; -''') - pop_indent() - - return ret.rstrip() - -def gen_visitor_input_vars_decl(args): - ret = "" - push_indent() - for argname, argtype, optional, structured in parse_args(args): - if optional: - ret += mcgen(''' -bool has_%(argname)s = false; -''', - argname=c_var(argname)) - if c_type(argtype).endswith("*"): - ret += mcgen(''' -%(argtype)s %(argname)s = NULL; -''', - argname=c_var(argname), argtype=c_type(argtype)) - else: - ret += mcgen(''' -%(argtype)s %(argname)s; -''', - argname=c_var(argname), argtype=c_type(argtype)) - - pop_indent() - return ret.rstrip() - -def gen_visitor_input_block(args, obj, dealloc=False): - ret = "" - if len(args) == 0: - return ret - - push_indent() - - if dealloc: - ret += mcgen(''' -md = qapi_dealloc_visitor_new(); -v = qapi_dealloc_get_visitor(md); -''') - else: - ret += mcgen(''' -mi = qmp_input_visitor_new_strict(%(obj)s); -v = qmp_input_get_visitor(mi); -''', - obj=obj) - - for argname, argtype, optional, structured in parse_args(args): - if optional: - ret += mcgen(''' -visit_start_optional(v, &has_%(c_name)s, "%(name)s", errp); -if (has_%(c_name)s) { -''', - c_name=c_var(argname), name=argname) - push_indent() - ret += mcgen(''' -%(visitor)s(v, &%(c_name)s, "%(name)s", errp); -''', - c_name=c_var(argname), name=argname, argtype=argtype, - visitor=type_visitor(argtype)) - if optional: - pop_indent() - ret += mcgen(''' -} -visit_end_optional(v, errp); -''') - - if dealloc: - ret += mcgen(''' -qapi_dealloc_visitor_cleanup(md); -''') - else: - ret += mcgen(''' -qmp_input_visitor_cleanup(mi); -''') - pop_indent() - return ret.rstrip() - -def gen_marshal_output(name, args, ret_type, middle_mode): - if not ret_type: - return "" - - ret = mcgen(''' -static void qmp_marshal_output_%(c_name)s(%(c_ret_type)s ret_in, QObject **ret_out, Error **errp) -{ - QapiDeallocVisitor *md = qapi_dealloc_visitor_new(); - QmpOutputVisitor *mo = qmp_output_visitor_new(); - Visitor *v; - - v = qmp_output_get_visitor(mo); - %(visitor)s(v, &ret_in, "unused", errp); - if (!error_is_set(errp)) { - *ret_out = qmp_output_get_qobject(mo); - } - qmp_output_visitor_cleanup(mo); - v = qapi_dealloc_get_visitor(md); - %(visitor)s(v, &ret_in, "unused", errp); - qapi_dealloc_visitor_cleanup(md); -} -''', - c_ret_type=c_type(ret_type), c_name=c_fun(name), - visitor=type_visitor(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) - else: - return 'static void qmp_marshal_input_%s(QDict *args, QObject **ret, Error **errp)' % c_fun(name) - - - -def gen_marshal_input(name, args, ret_type, middle_mode): - hdr = gen_marshal_input_decl(name, args, ret_type, middle_mode) - - ret = mcgen(''' -%(header)s -{ -''', - header=hdr) - - if middle_mode: - ret += mcgen(''' - Error *local_err = NULL; - Error **errp = &local_err; - QDict *args = (QDict *)qdict; -''') - - if ret_type: - if c_type(ret_type).endswith("*"): - retval = " %s retval = NULL;" % c_type(ret_type) - else: - retval = " %s retval;" % c_type(ret_type) - ret += mcgen(''' -%(retval)s -''', - retval=retval) - - if len(args) > 0: - ret += mcgen(''' -%(visitor_input_containers_decl)s -%(visitor_input_vars_decl)s - -%(visitor_input_block)s - -''', - visitor_input_containers_decl=gen_visitor_input_containers_decl(args), - visitor_input_vars_decl=gen_visitor_input_vars_decl(args), - visitor_input_block=gen_visitor_input_block(args, "QOBJECT(args)")) - else: - ret += mcgen(''' - (void)args; -''') - - ret += mcgen(''' - if (error_is_set(errp)) { - goto out; - } -%(sync_call)s -''', - sync_call=gen_sync_call(name, args, ret_type, indent=4)) - ret += mcgen(''' - -out: -''') - ret += mcgen(''' -%(visitor_input_block_cleanup)s -''', - visitor_input_block_cleanup=gen_visitor_input_block(args, None, - dealloc=True)) - - if middle_mode: - ret += mcgen(''' - - if (local_err) { - qerror_report_err(local_err); - error_free(local_err); - return -1; - } - return 0; -''') - else: - ret += mcgen(''' - return; -''') - - ret += mcgen(''' -} -''') - - return ret - -def option_value_matches(opt, val, cmd): - if opt in cmd and cmd[opt] == val: - return True - return False - -def gen_registry(commands): - registry="" - push_indent() - for cmd in commands: - options = 'QCO_NO_OPTIONS' - if option_value_matches('success-response', 'no', cmd): - options = 'QCO_NO_SUCCESS_RESP' - - registry += mcgen(''' -qmp_register_command("%(name)s", qmp_marshal_input_%(c_name)s, %(opts)s); -''', - name=cmd['command'], c_name=c_fun(cmd['command']), - opts=options) - pop_indent() - ret = mcgen(''' -static void qmp_init_marshal(void) -{ -%(registry)s -} - -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 */ - -/* - * schema-defined QAPI function prototypes - * - * Copyright IBM, Corp. 2011 - * - * Authors: - * Anthony Liguori - * - * 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 "%(prefix)sqapi-types.h" -#include "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 */ - -/* - * schema-defined QMP->QAPI command dispatch - * - * Copyright IBM, Corp. 2011 - * - * Authors: - * Anthony Liguori - * - * 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-objects.h" -#include "qapi/qmp-core.h" -#include "qapi/qapi-visit-core.h" -#include "qapi/qmp-output-visitor.h" -#include "qapi/qmp-input-visitor.h" -#include "qapi/qapi-dealloc-visitor.h" -#include "%(prefix)sqapi-types.h" -#include "%(prefix)sqapi-visit.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:o:m", - ["source", "header", "prefix=", - "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 ("-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(sys.stdin) -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: - 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" - fdef.write(ret) - - fdecl.write("\n#endif\n"); - - if not middle_mode: - ret = gen_registry(commands) - fdef.write(ret) - - fdef.flush() - fdef.close() - fdecl.flush() - fdecl.close() diff --git a/scripts/qapi_commands.py b/scripts/qapi_commands.py new file mode 100644 index 0000000..9eed40e --- /dev/null +++ b/scripts/qapi_commands.py @@ -0,0 +1,476 @@ +# +# QAPI command marshaller generator +# +# Copyright IBM, Corp. 2011 +# +# Authors: +# Anthony Liguori +# Michael Roth +# +# This work is licensed under the terms of the GNU GPLv2. +# See the COPYING.LIB file in the top-level directory. + +from ordereddict import OrderedDict +from qapi import * +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_decl_enum(name, members, genlist=True): + return mcgen(''' + +void %(visitor)s(Visitor *m, %(name)s * obj, const char *name, Error **errp); +''', + visitor=type_visitor(name)) + +def generate_command_decl(name, args, ret_type): + arglist="" + for argname, argtype, optional, structured in parse_args(args): + argtype = c_type(argtype) + if argtype == "char *": + argtype = "const char *" + if optional: + arglist += "bool has_%s, " % c_var(argname) + arglist += "%s %s, " % (argtype, c_var(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() + +def gen_sync_call(name, args, ret_type, indent=0): + ret = "" + arglist="" + retval="" + if ret_type: + retval = "retval = " + for argname, argtype, optional, structured in parse_args(args): + if optional: + arglist += "has_%s, " % c_var(argname) + arglist += "%s, " % (c_var(argname)) + push_indent(indent) + ret = mcgen(''' +%(retval)sqmp_%(name)s(%(args)serrp); + +''', + name=c_fun(name), args=arglist, retval=retval).rstrip() + if ret_type: + ret += "\n" + mcgen('''' +if (!error_is_set(errp)) { + %(marshal_output_call)s +} +''', + marshal_output_call=gen_marshal_output_call(name, ret_type)).rstrip() + pop_indent(indent) + return ret.rstrip() + + +def gen_marshal_output_call(name, ret_type): + if not ret_type: + return "" + return "qmp_marshal_output_%s(retval, ret, errp);" % c_fun(name) + +def gen_visitor_output_containers_decl(ret_type): + ret = "" + push_indent() + if ret_type: + ret += mcgen(''' +QmpOutputVisitor *mo; +QapiDeallocVisitor *md; +Visitor *v; +''') + pop_indent() + + return ret + +def gen_visitor_input_containers_decl(args): + ret = "" + + push_indent() + if len(args) > 0: + ret += mcgen(''' +QmpInputVisitor *mi; +QapiDeallocVisitor *md; +Visitor *v; +''') + pop_indent() + + return ret.rstrip() + +def gen_visitor_input_vars_decl(args): + ret = "" + push_indent() + for argname, argtype, optional, structured in parse_args(args): + if optional: + ret += mcgen(''' +bool has_%(argname)s = false; +''', + argname=c_var(argname)) + if c_type(argtype).endswith("*"): + ret += mcgen(''' +%(argtype)s %(argname)s = NULL; +''', + argname=c_var(argname), argtype=c_type(argtype)) + else: + ret += mcgen(''' +%(argtype)s %(argname)s; +''', + argname=c_var(argname), argtype=c_type(argtype)) + + pop_indent() + return ret.rstrip() + +def gen_visitor_input_block(args, obj, dealloc=False): + ret = "" + if len(args) == 0: + return ret + + push_indent() + + if dealloc: + ret += mcgen(''' +md = qapi_dealloc_visitor_new(); +v = qapi_dealloc_get_visitor(md); +''') + else: + ret += mcgen(''' +mi = qmp_input_visitor_new_strict(%(obj)s); +v = qmp_input_get_visitor(mi); +''', + obj=obj) + + for argname, argtype, optional, structured in parse_args(args): + if optional: + ret += mcgen(''' +visit_start_optional(v, &has_%(c_name)s, "%(name)s", errp); +if (has_%(c_name)s) { +''', + c_name=c_var(argname), name=argname) + push_indent() + ret += mcgen(''' +%(visitor)s(v, &%(c_name)s, "%(name)s", errp); +''', + c_name=c_var(argname), name=argname, argtype=argtype, + visitor=type_visitor(argtype)) + if optional: + pop_indent() + ret += mcgen(''' +} +visit_end_optional(v, errp); +''') + + if dealloc: + ret += mcgen(''' +qapi_dealloc_visitor_cleanup(md); +''') + else: + ret += mcgen(''' +qmp_input_visitor_cleanup(mi); +''') + pop_indent() + return ret.rstrip() + +def gen_marshal_output(name, args, ret_type, middle_mode): + if not ret_type: + return "" + + ret = mcgen(''' +static void qmp_marshal_output_%(c_name)s(%(c_ret_type)s ret_in, QObject **ret_out, Error **errp) +{ + QapiDeallocVisitor *md = qapi_dealloc_visitor_new(); + QmpOutputVisitor *mo = qmp_output_visitor_new(); + Visitor *v; + + v = qmp_output_get_visitor(mo); + %(visitor)s(v, &ret_in, "unused", errp); + if (!error_is_set(errp)) { + *ret_out = qmp_output_get_qobject(mo); + } + qmp_output_visitor_cleanup(mo); + v = qapi_dealloc_get_visitor(md); + %(visitor)s(v, &ret_in, "unused", errp); + qapi_dealloc_visitor_cleanup(md); +} +''', + c_ret_type=c_type(ret_type), c_name=c_fun(name), + visitor=type_visitor(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) + else: + return 'static void qmp_marshal_input_%s(QDict *args, QObject **ret, Error **errp)' % c_fun(name) + + + +def gen_marshal_input(name, args, ret_type, middle_mode): + hdr = gen_marshal_input_decl(name, args, ret_type, middle_mode) + + ret = mcgen(''' +%(header)s +{ +''', + header=hdr) + + if middle_mode: + ret += mcgen(''' + Error *local_err = NULL; + Error **errp = &local_err; + QDict *args = (QDict *)qdict; +''') + + if ret_type: + if c_type(ret_type).endswith("*"): + retval = " %s retval = NULL;" % c_type(ret_type) + else: + retval = " %s retval;" % c_type(ret_type) + ret += mcgen(''' +%(retval)s +''', + retval=retval) + + if len(args) > 0: + ret += mcgen(''' +%(visitor_input_containers_decl)s +%(visitor_input_vars_decl)s + +%(visitor_input_block)s + +''', + visitor_input_containers_decl=gen_visitor_input_containers_decl(args), + visitor_input_vars_decl=gen_visitor_input_vars_decl(args), + visitor_input_block=gen_visitor_input_block(args, "QOBJECT(args)")) + else: + ret += mcgen(''' + (void)args; +''') + + ret += mcgen(''' + if (error_is_set(errp)) { + goto out; + } +%(sync_call)s +''', + sync_call=gen_sync_call(name, args, ret_type, indent=4)) + ret += mcgen(''' + +out: +''') + ret += mcgen(''' +%(visitor_input_block_cleanup)s +''', + visitor_input_block_cleanup=gen_visitor_input_block(args, None, + dealloc=True)) + + if middle_mode: + ret += mcgen(''' + + if (local_err) { + qerror_report_err(local_err); + error_free(local_err); + return -1; + } + return 0; +''') + else: + ret += mcgen(''' + return; +''') + + ret += mcgen(''' +} +''') + + return ret + +def option_value_matches(opt, val, cmd): + if opt in cmd and cmd[opt] == val: + return True + return False + +def gen_registry(commands): + registry="" + push_indent() + for cmd in commands: + options = 'QCO_NO_OPTIONS' + if option_value_matches('success-response', 'no', cmd): + options = 'QCO_NO_SUCCESS_RESP' + + registry += mcgen(''' +qmp_register_command("%(name)s", qmp_marshal_input_%(c_name)s, %(opts)s); +''', + name=cmd['command'], c_name=c_fun(cmd['command']), + opts=options) + pop_indent() + ret = mcgen(''' +static void qmp_init_marshal(void) +{ +%(registry)s +} + +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 */ + +/* + * schema-defined QAPI function prototypes + * + * Copyright IBM, Corp. 2011 + * + * Authors: + * Anthony Liguori + * + * 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 "%(prefix)sqapi-types.h" +#include "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 */ + +/* + * schema-defined QMP->QAPI command dispatch + * + * Copyright IBM, Corp. 2011 + * + * Authors: + * Anthony Liguori + * + * 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-objects.h" +#include "qapi/qmp-core.h" +#include "qapi/qapi-visit-core.h" +#include "qapi/qmp-output-visitor.h" +#include "qapi/qmp-input-visitor.h" +#include "qapi/qapi-dealloc-visitor.h" +#include "%(prefix)sqapi-types.h" +#include "%(prefix)sqapi-visit.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:o:m", + ["source", "header", "prefix=", + "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 ("-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(sys.stdin) +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: + 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" + fdef.write(ret) + + fdecl.write("\n#endif\n"); + + if not middle_mode: + ret = gen_registry(commands) + fdef.write(ret) + + fdef.flush() + fdef.close() + fdecl.flush() + fdecl.close() diff --git a/tests/Makefile b/tests/Makefile index 45b9334..7cfd3d8 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -58,8 +58,8 @@ tests/test-qapi-visit.c tests/test-qapi-visit.h :\ $(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi_visit.py $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi_visit.py $(gen-out-type) -o tests -p "test-" < $<, " GEN $@") tests/test-qmp-commands.h tests/test-qmp-marshal.c :\ -$(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi-commands.py - $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-commands.py $(gen-out-type) -o tests -p "test-" < $<, " GEN $@") +$(SRC_PATH)/qapi-schema-test.json $(SRC_PATH)/scripts/qapi_commands.py + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi_commands.py $(gen-out-type) -o tests -p "test-" < $<, " GEN $@") tests/test-string-output-visitor$(EXESUF): tests/test-string-output-visitor.o $(test-qapi-obj-y)