qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH V7 04/11] qapi script: check correctness of discrimi


From: Wenchao Xia
Subject: [Qemu-devel] [PATCH V7 04/11] qapi script: check correctness of discriminator values in union
Date: Thu, 20 Feb 2014 00:54:48 -0500

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 <address@hidden>
---
 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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]