From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:50376) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WGMba-000581-IJ for qemu-devel@nongnu.org; Thu, 20 Feb 2014 00:55:38 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1WGMbP-00017D-Jk for qemu-devel@nongnu.org; Thu, 20 Feb 2014 00:55:30 -0500 Received: from e28smtp02.in.ibm.com ([122.248.162.2]:39111) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1WGMbO-00016R-WA for qemu-devel@nongnu.org; Thu, 20 Feb 2014 00:55:19 -0500 Received: from /spool/local by e28smtp02.in.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Thu, 20 Feb 2014 11:25:11 +0530 Received: from d28relay03.in.ibm.com (d28relay03.in.ibm.com [9.184.220.60]) by d28dlp02.in.ibm.com (Postfix) with ESMTP id 0CFC93940023 for ; Thu, 20 Feb 2014 11:25:10 +0530 (IST) Received: from d28av02.in.ibm.com (d28av02.in.ibm.com [9.184.220.64]) by d28relay03.in.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id s1K5t2uJ60424226 for ; Thu, 20 Feb 2014 11:25:02 +0530 Received: from d28av02.in.ibm.com (localhost [127.0.0.1]) by d28av02.in.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id s1K5t9DP001985 for ; Thu, 20 Feb 2014 11:25:09 +0530 From: Wenchao Xia Date: Thu, 20 Feb 2014 00:54:48 -0500 Message-Id: <1392875695-15627-5-git-send-email-xiawenc@linux.vnet.ibm.com> In-Reply-To: <1392875695-15627-1-git-send-email-xiawenc@linux.vnet.ibm.com> References: <1392875695-15627-1-git-send-email-xiawenc@linux.vnet.ibm.com> Subject: [Qemu-devel] [PATCH V7 04/11] qapi script: check correctness of discriminator values in union List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: kwolf@redhat.com, mdroth@linux.vnet.ibm.com, armbru@redhat.com, lcapitulino@redhat.com, Wenchao Xia It will check whether base is set, whether discriminator is found in base, whether the values specified are written correctly, and whether all enum values are covered, when discriminator is a pre-defined enum type. Exprs now have addtional info inside qapi.py to form better error message. Signed-off-by: Wenchao Xia --- scripts/qapi.py | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 82 insertions(+), 2 deletions(-) diff --git a/scripts/qapi.py b/scripts/qapi.py index c504eb4..8af8cfd 100644 --- a/scripts/qapi.py +++ b/scripts/qapi.py @@ -50,6 +50,15 @@ class QAPISchemaError(Exception): def __str__(self): return "%s:%s:%s: %s" % (self.fp.name, self.line, self.col, self.msg) +class QAPIExprError(Exception): + def __init__(self, expr_elem, msg): + self.fp = expr_elem['fp'] + self.line = expr_elem['line'] + self.msg = msg + + def __str__(self): + return "%s:%s: %s" % (self.fp.name, self.line, self.msg) + class QAPISchema: def __init__(self, fp): @@ -64,7 +73,11 @@ class QAPISchema: self.accept() while self.tok != None: - self.exprs.append(self.get_expr(False)) + line = self.line + expr_elem = {'expr': self.get_expr(False), + 'fp': fp, + 'line': line} + self.exprs.append(expr_elem) def accept(self): while True: @@ -162,6 +175,66 @@ class QAPISchema: raise QAPISchemaError(self, 'Expected "{", "[" or string') return expr +# This function can be used to check whether "base" is valid +def find_base_fields(base): + base_struct_define = find_struct(base) + if not base_struct_define: + return None + return base_struct_define.get('data') + +# Return the discriminator enum define, if discriminator is specified in +# @expr_elem["expr"] and it is a pre-defined enum type +def discriminator_find_enum_define(expr_elem): + expr = expr_elem['expr'] + discriminator = expr.get('discriminator') + base = expr.get('base') + + # Only support discriminator when base present + if not (discriminator and base): + return None + + base_fields = find_base_fields(base) + + if not base_fields: + raise QAPIExprError(expr_elem, + "Base '%s' is not a valid type" + % base) + + discriminator_type = base_fields.get(discriminator) + + if not discriminator_type: + raise QAPIExprError(expr_elem, + "Discriminator '%s' not found in schema" + % discriminator) + + return find_enum(discriminator_type) + +def check_union(expr_elem): + # If discriminator is specified and it is a pre-defined enum in schema, + # check its correctness + enum_define = discriminator_find_enum_define(expr_elem) + name = expr_elem['expr']['union'] + members = expr_elem['expr']['data'] + if enum_define: + for key in members: + if not key in enum_define['enum_values']: + raise QAPIExprError(expr_elem, + "Discriminator value '%s' is not found in " + "enum '%s'" % + (key, enum_define["enum_name"])) + for key in enum_define['enum_values']: + if not key in members: + raise QAPIExprError(expr_elem, + "Enum value '%s' is not covered by a " + "branch of union '%s'" % + (key, name)) + +def check_exprs(schema): + for expr_elem in schema.exprs: + expr = expr_elem['expr'] + if expr.has_key('union'): + check_union(expr_elem) + def parse_schema(fp): try: schema = QAPISchema(fp) @@ -171,7 +244,8 @@ def parse_schema(fp): exprs = [] - for expr in schema.exprs: + for expr_elem in schema.exprs: + expr = expr_elem['expr'] if expr.has_key('enum'): add_enum(expr['enum'], expr['data']) elif expr.has_key('union'): @@ -181,6 +255,12 @@ def parse_schema(fp): add_struct(expr) exprs.append(expr) + try: + check_exprs(schema) + except QAPIExprError, e: + print >>sys.stderr, e + exit(1) + return exprs def parse_args(typeinfo): -- 1.7.1