From patchwork Tue Jul 5 13:02:40 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Roth X-Patchwork-Id: 103312 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [140.186.70.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id B6EE7B6F6B for ; Wed, 6 Jul 2011 00:38:35 +1000 (EST) Received: from localhost ([::1]:37450 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Qe6ki-0004af-0M for incoming@patchwork.ozlabs.org; Tue, 05 Jul 2011 10:37:28 -0400 Received: from eggs.gnu.org ([140.186.70.92]:46479) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Qe5JE-0005Ob-Gi for qemu-devel@nongnu.org; Tue, 05 Jul 2011 09:05:02 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Qe5JC-00021j-BF for qemu-devel@nongnu.org; Tue, 05 Jul 2011 09:05:00 -0400 Received: from mout.perfora.net ([74.208.4.195]:57415) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Qe5JC-00021f-3m for qemu-devel@nongnu.org; Tue, 05 Jul 2011 09:04:58 -0400 Received: from localhost.localdomain (cpe-70-112-165-205.austin.res.rr.com [70.112.165.205]) by mrelay.perfora.net (node=mrus3) with ESMTP (Nemesis) id 0MAQc6-1QoYck2kV0-00BoRp; Tue, 05 Jul 2011 09:04:56 -0400 From: Michael Roth To: qemu-devel@nongnu.org Date: Tue, 5 Jul 2011 08:02:40 -0500 Message-Id: <1309870965-27066-14-git-send-email-mdroth@linux.vnet.ibm.com> X-Mailer: git-send-email 1.7.0.4 In-Reply-To: <1309870965-27066-1-git-send-email-mdroth@linux.vnet.ibm.com> References: <1309870965-27066-1-git-send-email-mdroth@linux.vnet.ibm.com> X-Provags-ID: V02:K0:waWNjgt64dbmLtiBPE/BtECCnm3j1XoOGXBAI2yhQkb AzyG1uCJ0HYc0a145lH7QsBj3zDcXZB85llBszFxF88n/r1FpV HSG5RaZsNXofXb6zinkjoyFWwUs3XDzHFiQlcN1/qflq4z74hP GoWqCU0EshVlpjotXz7RiQoqXMkp0pSqNjxceZtReH1ubPHOh4 QhtUPsNj89ONHZUlU6nI0wStxo/iwOEzcZhh37ArlY= X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 74.208.4.195 Cc: aliguori@linux.vnet.ibm.com, Jes.Sorensen@redhat.com, agl@linux.vnet.ibm.com, mdroth@linux.vnet.ibm.com, lcapitulino@redhat.com Subject: [Qemu-devel] [PATCH v5 13/18] qapi: add qapi-visit.py code generator 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 This is the code generator for qapi visiter functions used to marshal/unmarshal/dealloc qapi types. It generates the following 2 files: $(prefix)qapi-visit.c: visiter function for a particular c type, used to automagically convert qobjects into the corresponding C type and vice-versa, and well as for deallocation memory for an existing C type $(prefix)qapi-visit.h: declarations for previously mentioned visiter functions $(prefix) is used as decribed for qapi-types.py Signed-off-by: Michael Roth --- scripts/qapi-visit.py | 261 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 261 insertions(+), 0 deletions(-) create mode 100644 scripts/qapi-visit.py diff --git a/scripts/qapi-visit.py b/scripts/qapi-visit.py new file mode 100644 index 0000000..a1a2d33 --- /dev/null +++ b/scripts/qapi-visit.py @@ -0,0 +1,261 @@ +# +# QAPI visitor 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 + +def generate_visit_struct_body(field_prefix, members): + ret = "" + if len(field_prefix): + field_prefix = field_prefix + "." + for argname, argentry, optional, structured in parse_args(members): + if optional: + ret += mcgen(''' +visit_start_optional(m, (obj && *obj) ? &(*obj)->%(c_prefix)shas_%(c_name)s : NULL, "%(name)s", errp); +if ((*obj)->%(prefix)shas_%(c_name)s) { +''', + c_prefix=c_var(field_prefix), prefix=field_prefix, + c_name=c_var(argname), name=argname) + push_indent() + + if structured: + ret += mcgen(''' +visit_start_struct(m, NULL, "", "%(name)s", 0, errp); +''', + name=argname) + ret += generate_visit_struct_body(field_prefix + argname, argentry) + ret += mcgen(''' +visit_end_struct(m, errp); +''') + else: + ret += mcgen(''' +visit_type_%(type)s(m, (obj && *obj) ? &(*obj)->%(c_prefix)s%(c_name)s : NULL, "%(name)s", errp); +''', + c_prefix=c_var(field_prefix), prefix=field_prefix, + type=type_name(argentry), c_name=c_var(argname), + name=argname) + + if optional: + pop_indent() + ret += mcgen(''' +} +visit_end_optional(m, errp); +''') + return ret + +def generate_visit_struct(name, members): + ret = mcgen(''' + +void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **errp) +{ + visit_start_struct(m, (void **)obj, "%(name)s", name, sizeof(%(name)s), errp); +''', + name=name) + push_indent() + ret += generate_visit_struct_body("", members) + pop_indent() + + ret += mcgen(''' + visit_end_struct(m, errp); +} +''') + return ret + +def generate_visit_list(name, members): + return mcgen(''' + +void visit_type_%(name)sList(Visitor *m, %(name)sList ** obj, const char *name, Error **errp) +{ + GenericList *i; + + visit_start_list(m, name, errp); + + for (i = visit_next_list(m, (GenericList **)obj, errp); i; i = visit_next_list(m, &i, errp)) { + %(name)sList *native_i = (%(name)sList *)i; + visit_type_%(name)s(m, &native_i->value, NULL, errp); + } + + visit_end_list(m, errp); +} +''', + name=name) + +def generate_visit_handle(name, typeinfo): + return mcgen(''' + +void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **errp) +{ + visit_start_handle(m, (void **)obj, "%(name)s", name, errp); + visit_type_%(type_name)s(m, &(*obj)->handle, "handle", errp); + visit_end_handle(m, errp); +} +''', + name=name, type_name=type_name(typeinfo)) + +def generate_visit_enum(name, members): + return mcgen(''' + +void visit_type_%(name)s(Visitor *m, %(name)s * obj, const char *name, Error **errp) +{ + visit_type_enum(m, (int *)obj, "%(name)s", name, errp); +} +''', + name=name) + +def generate_visit_union(name, members): + ret = generate_visit_enum('%sKind' % name, members.keys()) + + ret += mcgen(''' + +void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **errp) +{ +} +''', + name=name) + + return ret + +def generate_declaration(name, members, genlist=True): + ret = mcgen(''' + +void visit_type_%(name)s(Visitor *m, %(name)s ** obj, const char *name, Error **errp); +''', + name=name) + + if genlist: + ret += mcgen(''' +void visit_type_%(name)sList(Visitor *m, %(name)sList ** obj, const char *name, Error **errp); +''', + name=name) + + return ret + +def generate_decl_enum(name, members, genlist=True): + return mcgen(''' + +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:], "p:o:", ["prefix=", "output-dir="]) +except getopt.GetoptError, err: + print str(err) + sys.exit(1) + +output_dir = "" +prefix = "" +c_file = 'qapi-visit.c' +h_file = 'qapi-visit.h' + +for o, a in opts: + if o in ("-p", "--prefix"): + prefix = a + elif o in ("-o", "--output-dir"): + output_dir = a + "/" + +c_file = output_dir + prefix + c_file +h_file = output_dir + prefix + h_file + +if os.path.isdir(output_dir) == False: + os.makedirs(output_dir) + +fdef = open(c_file, 'w') +fdecl = open(h_file, 'w') + +fdef.write(mcgen(''' +/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */ + +/* + * schema-defined QAPI visitor functions + * + * 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 "%(header)s" +''', + header=basename(h_file))) + +fdecl.write(mcgen(''' +/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */ + +/* + * schema-defined QAPI visitor function + * + * 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 "qapi/qapi-visit-core.h" +#include "%(prefix)sqapi-types.h" +''', + prefix=prefix, guard=guardname(h_file))) + +exprs = parse_schema(sys.stdin) + +for expr in exprs: + if expr.has_key('type'): + ret = generate_visit_struct(expr['type'], expr['data']) + ret += generate_visit_list(expr['type'], expr['data']) + fdef.write(ret) + + ret = generate_declaration(expr['type'], expr['data']) + fdecl.write(ret) + elif expr.has_key('union'): + ret = generate_visit_union(expr['union'], expr['data']) + fdef.write(ret) + + ret = generate_decl_enum('%sKind' % expr['union'], expr['data'].keys()) + ret += generate_declaration(expr['union'], expr['data']) + fdecl.write(ret) + elif expr.has_key('enum'): + ret = generate_visit_enum(expr['enum'], expr['data']) + fdef.write(ret) + + ret = generate_decl_enum(expr['enum'], expr['data']) + fdecl.write(ret) + elif expr.has_key('handle'): + ret = generate_visit_handle(expr['handle'], expr['data']) + fdef.write(ret) + + ret = generate_declaration(expr['handle'], expr['data'], False) + fdecl.write(ret) + +fdecl.write(''' +#endif +''') + +fdecl.flush() +fdecl.close() + +fdef.flush() +fdef.close() +