From patchwork Tue Jul 19 19:50:39 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Roth X-Patchwork-Id: 105520 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 1E9A3B6F7A for ; Wed, 20 Jul 2011 06:17:29 +1000 (EST) Received: from localhost ([::1]:41399 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QjGjM-0003Q6-KC for incoming@patchwork.ozlabs.org; Tue, 19 Jul 2011 16:17:25 -0400 Received: from eggs.gnu.org ([140.186.70.92]:47529) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QjGLB-000661-6e for qemu-devel@nongnu.org; Tue, 19 Jul 2011 15:52:28 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1QjGL8-00071L-EQ for qemu-devel@nongnu.org; Tue, 19 Jul 2011 15:52:24 -0400 Received: from mout.perfora.net ([74.208.4.194]:64495) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QjGL7-00071C-V8 for qemu-devel@nongnu.org; Tue, 19 Jul 2011 15:52:22 -0400 Received: from localhost.localdomain ([32.97.110.59]) by mrelay.perfora.net (node=mrus2) with ESMTP (Nemesis) id 0Lu7qw-1RQTYQ3NyQ-011HXd; Tue, 19 Jul 2011 15:52:19 -0400 From: Michael Roth To: qemu-devel@nongnu.org Date: Tue, 19 Jul 2011 14:50:39 -0500 Message-Id: <1311105046-29458-12-git-send-email-mdroth@linux.vnet.ibm.com> X-Mailer: git-send-email 1.7.0.4 In-Reply-To: <1311105046-29458-1-git-send-email-mdroth@linux.vnet.ibm.com> References: <1311105046-29458-1-git-send-email-mdroth@linux.vnet.ibm.com> X-Provags-ID: V02:K0:mnHY1JRHf2j0Tsz1XnRrpRBLzfKa0jsr3vyt+nYMQSh LKXFZHHkuTyxbGG7uKVKrg8VnjKmuA59fKc5Tw7vlEw4101HvB AlCSBZfQJBvpIBxL7iMCm+A1T01b7n2RjKU1pc3UdZ8SnR4BRs Vu0oiQ2Ilgn9PpIAU2lN9J26vqO4EWG5rBt0MoGJCp8QJQdyhx cdjI3+cXrSiOxLGCmHvLiyeUo/5Zy+4OQeR+NogGIg= X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 74.208.4.194 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 v7 11/18] qapi: add qapi.py helper libraries 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 Signed-off-by: Michael Roth --- scripts/qapi.py | 203 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 203 insertions(+), 0 deletions(-) create mode 100644 scripts/qapi.py diff --git a/scripts/qapi.py b/scripts/qapi.py new file mode 100644 index 0000000..56af232 --- /dev/null +++ b/scripts/qapi.py @@ -0,0 +1,203 @@ +# +# QAPI helper library +# +# Copyright IBM, Corp. 2011 +# +# Authors: +# Anthony Liguori +# +# 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 + +def tokenize(data): + while len(data): + if data[0] in ['{', '}', ':', ',', '[', ']']: + yield data[0] + data = data[1:] + elif data[0] in ' \n': + data = data[1:] + elif data[0] == "'": + data = data[1:] + string = '' + while data[0] != "'": + string += data[0] + data = data[1:] + data = data[1:] + yield string + +def parse(tokens): + if tokens[0] == '{': + ret = OrderedDict() + tokens = tokens[1:] + while tokens[0] != '}': + key = tokens[0] + tokens = tokens[1:] + + tokens = tokens[1:] # : + + value, tokens = parse(tokens) + + if tokens[0] == ',': + tokens = tokens[1:] + + ret[key] = value + tokens = tokens[1:] + return ret, tokens + elif tokens[0] == '[': + ret = [] + tokens = tokens[1:] + while tokens[0] != ']': + value, tokens = parse(tokens) + if tokens[0] == ',': + tokens = tokens[1:] + ret.append(value) + tokens = tokens[1:] + return ret, tokens + else: + return tokens[0], tokens[1:] + +def evaluate(string): + return parse(map(lambda x: x, tokenize(string)))[0] + +def parse_schema(fp): + exprs = [] + expr = '' + expr_eval = None + + for line in fp: + if line.startswith('#') or line == '\n': + continue + + if line.startswith(' '): + expr += line + elif expr: + expr_eval = evaluate(expr) + if expr_eval.has_key('enum'): + add_enum(expr_eval['enum']) + elif expr_eval.has_key('union'): + add_enum('%sKind' % expr_eval['union']) + exprs.append(expr_eval) + expr = line + else: + expr += line + + if expr: + expr_eval = evaluate(expr) + if expr_eval.has_key('enum'): + add_enum(expr_eval['enum']) + elif expr_eval.has_key('union'): + add_enum('%sKind' % expr_eval['union']) + exprs.append(expr_eval) + + return exprs + +def parse_args(typeinfo): + for member in typeinfo: + argname = member + argentry = typeinfo[member] + optional = False + structured = False + if member.startswith('*'): + argname = member[1:] + optional = True + if isinstance(argentry, OrderedDict): + structured = True + yield (argname, argentry, optional, structured) + +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 + for ch in name: + if ch in ['_', '-']: + first = True + elif first: + new_name += ch.upper() + first = False + else: + new_name += ch.lower() + return new_name + +def c_var(name): + return '_'.join(name.split('-')).lstrip("*") + +def c_list_type(name): + return '%sList' % name + +def type_name(name): + if type(name) == list: + return c_list_type(name[0]) + return name + +enum_types = [] + +def add_enum(name): + global enum_types + enum_types.append(name) + +def is_enum(name): + global enum_types + return (name in enum_types) + +def c_type(name): + if name == 'str': + return 'char *' + elif name == 'int': + return 'int64_t' + elif name == 'bool': + return 'bool' + elif name == 'number': + return 'double' + elif type(name) == list: + return '%s *' % c_list_type(name[0]) + elif is_enum(name): + return name + elif name == None or len(name) == 0: + return 'void' + elif name == name.upper(): + return '%sEvent *' % camel_case(name) + else: + return '%s *' % name + +def genindent(count): + ret = "" + for i in range(count): + ret += " " + return ret + +indent_level = 0 + +def push_indent(indent_amount=4): + global indent_level + indent_level += indent_amount + +def pop_indent(indent_amount=4): + global indent_level + indent_level -= indent_amount + +def cgen(code, **kwds): + indent = genindent(indent_level) + lines = code.split('\n') + lines = map(lambda x: indent + x, lines) + return '\n'.join(lines) % kwds + '\n' + +def mcgen(code, **kwds): + return cgen('\n'.join(code.split('\n')[1:-1]), **kwds) + +def basename(filename): + return filename.split("/")[-1] + +def guardname(filename): + return filename.replace("/", "_").replace("-", "_").split(".")[0].upper()