From patchwork Wed Jul 25 16:54:14 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luiz Capitulino X-Patchwork-Id: 173229 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 B52992C00A1 for ; Thu, 26 Jul 2012 03:49:47 +1000 (EST) Received: from localhost ([::1]:53113 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Su4qw-00031m-Lu for incoming@patchwork.ozlabs.org; Wed, 25 Jul 2012 12:54:26 -0400 Received: from eggs.gnu.org ([208.118.235.92]:41995) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Su4qY-0002Mj-Ke for qemu-devel@nongnu.org; Wed, 25 Jul 2012 12:54:04 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Su4qT-00019t-MB for qemu-devel@nongnu.org; Wed, 25 Jul 2012 12:54:02 -0400 Received: from mx1.redhat.com ([209.132.183.28]:55924) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Su4qT-00019g-EC for qemu-devel@nongnu.org; Wed, 25 Jul 2012 12:53:57 -0400 Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q6PGrtK5012617 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Wed, 25 Jul 2012 12:53:55 -0400 Received: from localhost (ovpn-113-89.phx2.redhat.com [10.3.113.89]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id q6PGrsgo011569; Wed, 25 Jul 2012 12:53:54 -0400 From: Luiz Capitulino To: qemu-devel@nongnu.org Date: Wed, 25 Jul 2012 13:54:14 -0300 Message-Id: <1343235256-26310-10-git-send-email-lcapitulino@redhat.com> In-Reply-To: <1343235256-26310-1-git-send-email-lcapitulino@redhat.com> References: <1343235256-26310-1-git-send-email-lcapitulino@redhat.com> X-Scanned-By: MIMEDefang 2.67 on 10.5.11.12 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.132.183.28 Cc: pbonzini@redhat.com, aliguori@us.ibm.com, armbru@redhat.com, mdroth@linux.vnet.ibm.com Subject: [Qemu-devel] [PATCH 09/11] qapi: add qapi-errors.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 This script generates two files from qapi-schema-errors.json: o qapi-errors.h: contains error macro definitions, eg. QERR_BASE_NOT_FOUND, corresponds to most of today's qerror.h o qapi-errors.c: contains the error table that currently exists in qerror.c Signed-off-by: Luiz Capitulino --- Makefile | 8 ++- scripts/qapi-errors.py | 177 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 183 insertions(+), 2 deletions(-) create mode 100644 scripts/qapi-errors.py diff --git a/Makefile b/Makefile index ab82ef3..2cdc732 100644 --- a/Makefile +++ b/Makefile @@ -22,8 +22,9 @@ GENERATED_HEADERS = config-host.h trace.h qemu-options.def ifeq ($(TRACE_BACKEND),dtrace) GENERATED_HEADERS += trace-dtrace.h endif -GENERATED_HEADERS += qmp-commands.h qapi-types.h qapi-visit.h -GENERATED_SOURCES += qmp-marshal.c qapi-types.c qapi-visit.c trace.c +GENERATED_HEADERS += qmp-commands.h qapi-types.h qapi-visit.h qapi-errors.h +GENERATED_SOURCES += qmp-marshal.c qapi-types.c qapi-visit.c qapi-errors.c \ + trace.c # Don't try to regenerate Makefile or configure # We don't generate any of them @@ -200,6 +201,9 @@ $(SRC_PATH)/qapi-schema.json $(SRC_PATH)/scripts/qapi-visit.py 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 $@") +qapi-errors.h qapi-errors.c :\ +$(SRC_PATH)/qapi-schema-errors.json $(SRC_PATH)/scripts/qapi-errors.py + $(call quiet-command,$(PYTHON) $(SRC_PATH)/scripts/qapi-errors.py -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-errors.py b/scripts/qapi-errors.py new file mode 100644 index 0000000..59cf426 --- /dev/null +++ b/scripts/qapi-errors.py @@ -0,0 +1,177 @@ +# +# QAPI errors generator +# +# Copyright (C) 2012 Red Hat, Inc. +# +# 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 +import getopt, sys, os, errno +from qapi import * + +def gen_error_decl_prologue(header, guard, prefix=""): + ret = mcgen(''' +/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */ + +/* + * schema-defined QAPI Errors + * + * Copyright (C) 2012 Red Hat, Inc. + * + * 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 + +''', + header=basename(header), guard=guardname(header), prefix=prefix) + return ret + +def gen_error_def_prologue(error_header, prefix=""): + ret = mcgen(''' +/* THIS FILE IS AUTOMATICALLY GENERATED, DO NOT MODIFY */ + +/* + * schema-defined QMP Error table + * + * Copyright (C) 2012 Red Hat, Inc. + * + * 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 "%(prefix)s%(error_header)s" + +''', + prefix=prefix, error_header=error_header) + return ret + +def gen_error_macro(err_domain): + string = '' + cur = err_domain[0] + for nxt in err_domain[1:]: + if string and cur.isupper() and nxt.islower(): + string += '_' + string += cur + cur = nxt + string += cur + return 'QERR_' + string.upper() + +def gen_error_def_table(exprs): + ret = mcgen(''' +static const QErrorStringTable qerror_table[] = { +''') + + for err in exprs: + macro = gen_error_macro(err['error']) + desc = err['description'] + ret += mcgen(''' + { + .error_fmt = %(error_macro)s, + .desc = "%(error_desc)s", + }, +''', + error_macro=macro, error_desc=desc) + + ret += mcgen(''' + {} +}; +''') + + return ret + +def gen_error_macro_data_str(data): + colon = '' + data_str = '' + for k, v in data.items(): + data_str += colon + "'%s': " % k + if v == 'str': + data_str += "%s" + elif v == 'int': + data_str += '%"PRId64"' + else: + sys.exit("unknown data type '%s' for error '%s'" % (v, name)) + colon = ', ' + return data_str + +def gen_error_decl_macros(exprs): + ret = '' + for err in exprs: + data = gen_error_macro_data_str({}) + if err.has_key('data'): + data = gen_error_macro_data_str(err['data']) + macro = gen_error_macro(err['error']) + name = err['error'] + + ret += mcgen(''' +#define %(error_macro)s \\ + "{ 'class': '%(error_class)s', 'data': { %(error_data)s } }" + +''', + error_macro=macro, error_class=name, error_data=data) + return ret + +def maybe_open(really, name, opt): + if really: + return open(name, opt) + else: + import StringIO + return StringIO.StringIO() + +if __name__ == '__main__': + try: + opts, args = getopt.gnu_getopt(sys.argv[1:], "chp:o:", + ["prefix=", "output-dir="]) + except getopt.GetoptError, err: + print str(err) + sys.exit(1) + + prefix = "" + output_dir = "" + do_c = True + do_h = True + c_file = 'qapi-errors.c' + h_file = 'qapi-errors.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 + + try: + os.makedirs(output_dir) + except os.error, e: + if e.errno != errno.EEXIST: + raise + + exprs = parse_schema(sys.stdin) + + fdecl = maybe_open(do_h, h_file, 'w') + ret = gen_error_decl_prologue(header=basename(h_file), guard=guardname(h_file), prefix=prefix) + fdecl.write(ret) + + ret = gen_error_decl_macros(exprs) + fdecl.write(ret) + + fdecl.write("#endif\n") + fdecl.flush() + fdecl.close() + + fdef = maybe_open(do_c, c_file, 'w') + ret = gen_error_def_prologue(error_header=h_file, prefix=prefix) + fdef.write(ret) + + ret = gen_error_def_table(exprs) + fdef.write(ret) + + fdef.flush() + fdef.close()