qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH V3 3/3] qapi: Create an include directive for use in


From: Benoît Canet
Subject: [Qemu-devel] [PATCH V3 3/3] qapi: Create an include directive for use in the JSON description files.
Date: Fri, 28 Mar 2014 17:25:32 +0100

The new directive in the form { 'include': 'path/to/file.json' } will trigger 
the
parsing of path/to/file.json.
The directive will be replaced by the result of the parsing.

This will allow for easy modularisation of qapi JSON descriptions files.

Signed-off-by: Benoit Canet <address@hidden>
---
 docs/qapi-code-gen.txt                             |   14 ++++++++
 scripts/qapi.py                                    |   38 +++++++++++++++++++-
 tests/Makefile                                     |    8 +++--
 .../qapi-schema/error_after_sucessful_include.err  |    1 +
 .../qapi-schema/error_after_sucessful_include.exit |    1 +
 .../qapi-schema/error_after_sucessful_include.json |    4 +++
 tests/qapi-schema/error_in_included_file.err       |    1 +
 tests/qapi-schema/error_in_included_file.exit      |    1 +
 tests/qapi-schema/error_in_included_file.json      |    4 +++
 tests/qapi-schema/include.exit                     |    1 +
 tests/qapi-schema/include.json                     |    4 +++
 tests/qapi-schema/include.out                      |    8 +++++
 tests/qapi-schema/include/error.json               |    6 ++++
 tests/qapi-schema/include/include.json             |    7 ++++
 tests/qapi-schema/include/multi.json               |    1 +
 tests/qapi-schema/include/multi_loop.json          |    1 +
 tests/qapi-schema/include_loop.exit                |    1 +
 tests/qapi-schema/include_loop.json                |    1 +
 tests/qapi-schema/include_loop.out                 |    3 ++
 tests/qapi-schema/include_non_filename.err         |    1 +
 tests/qapi-schema/include_non_filename.exit        |    1 +
 tests/qapi-schema/include_non_filename.json        |    4 +++
 tests/qapi-schema/multi_file_loop_include.exit     |    1 +
 tests/qapi-schema/multi_file_loop_include.json     |    4 +++
 tests/qapi-schema/multi_file_loop_include.out      |    4 +++
 .../multiple_relative_path_include.exit            |    1 +
 .../multiple_relative_path_include.json            |    4 +++
 .../qapi-schema/multiple_relative_path_include.out |    6 ++++
 28 files changed, 128 insertions(+), 3 deletions(-)
 create mode 100644 tests/qapi-schema/error_after_sucessful_include.err
 create mode 100644 tests/qapi-schema/error_after_sucessful_include.exit
 create mode 100644 tests/qapi-schema/error_after_sucessful_include.json
 create mode 100644 tests/qapi-schema/error_after_sucessful_include.out
 create mode 100644 tests/qapi-schema/error_in_included_file.err
 create mode 100644 tests/qapi-schema/error_in_included_file.exit
 create mode 100644 tests/qapi-schema/error_in_included_file.json
 create mode 100644 tests/qapi-schema/error_in_included_file.out
 create mode 100644 tests/qapi-schema/include.err
 create mode 100644 tests/qapi-schema/include.exit
 create mode 100644 tests/qapi-schema/include.json
 create mode 100644 tests/qapi-schema/include.out
 create mode 100644 tests/qapi-schema/include/error.json
 create mode 100644 tests/qapi-schema/include/include.json
 create mode 100644 tests/qapi-schema/include/multi.json
 create mode 100644 tests/qapi-schema/include/multi_loop.json
 create mode 100644 tests/qapi-schema/include_loop.err
 create mode 100644 tests/qapi-schema/include_loop.exit
 create mode 100644 tests/qapi-schema/include_loop.json
 create mode 100644 tests/qapi-schema/include_loop.out
 create mode 100644 tests/qapi-schema/include_non_filename.err
 create mode 100644 tests/qapi-schema/include_non_filename.exit
 create mode 100644 tests/qapi-schema/include_non_filename.json
 create mode 100644 tests/qapi-schema/include_non_filename.out
 create mode 100644 tests/qapi-schema/multi_file_loop_include.err
 create mode 100644 tests/qapi-schema/multi_file_loop_include.exit
 create mode 100644 tests/qapi-schema/multi_file_loop_include.json
 create mode 100644 tests/qapi-schema/multi_file_loop_include.out
 create mode 100644 tests/qapi-schema/multiple_relative_path_include.err
 create mode 100644 tests/qapi-schema/multiple_relative_path_include.exit
 create mode 100644 tests/qapi-schema/multiple_relative_path_include.json
 create mode 100644 tests/qapi-schema/multiple_relative_path_include.out

diff --git a/docs/qapi-code-gen.txt b/docs/qapi-code-gen.txt
index d78921f..a16aa47 100644
--- a/docs/qapi-code-gen.txt
+++ b/docs/qapi-code-gen.txt
@@ -180,6 +180,20 @@ An example command is:
    'data': { 'arg1': 'str', '*arg2': 'str' },
    'returns': 'str' }
 
+=== Includes ===
+
+A schema file can include other sub schema files with the include
+directive.
+
+An example of include directive is:
+
+{ 'include': 'path/to/sub_schema.json' }
+
+The include path is relative to the current schema file.
+The include parsing method is recursive.
+The expressions resulting from the parsing of the sub schema are injected
+in place of the include directive like a C #include would do.
+
 
 == Code generation ==
 
diff --git a/scripts/qapi.py b/scripts/qapi.py
index ae3f756..df624ce 100644
--- a/scripts/qapi.py
+++ b/scripts/qapi.py
@@ -273,14 +273,47 @@ def build_schema(filename):
             exit(1)
     return schema
 
+loop_stack = []
+
+def include_sub_file(filename, expr_elem):
+    expr = expr_elem['expr']
+    expr_info = expr_elem['info']
+
+    # is the include a string ?
+    include = expr['include']
+    if not isinstance(include, str):
+        raise QAPIExprError(expr_info,
+                            "filename to include must be a string")
+
+    # get sub filename
+    prefix = os.path.split(filename)[0]
+    sub_filename = os.path.join(prefix, include)
+
+    return parse_schema(sub_filename)
+
 def parse_schema(filename):
+    abspath = os.path.abspath(filename)
+
+    if abspath in loop_stack:
+        print "Inclusion loop detected with file: %s"% filename
+        print "Path to the broken include is:"
+        for i in loop_stack:
+            print "\t%s" % i
+        sys.exit(1)
+
+    # push the abspath of the current file in the stack
+    loop_stack.append(abspath)
+
     schema = build_schema(filename)
 
     exprs = []
 
     for expr_elem in schema.exprs:
         expr = expr_elem['expr']
-        if expr.has_key('enum'):
+        if expr.has_key('include'):
+            exprs += include_sub_file(filename, expr_elem)
+            continue
+        elif expr.has_key('enum'):
             add_enum(expr['enum'], expr['data'])
         elif expr.has_key('union'):
             add_union(expr)
@@ -301,6 +334,9 @@ def parse_schema(filename):
         print >>sys.stderr, e
         exit(1)
 
+    # pop the abspath of the current file from the stack
+    loop_stack.pop()
+
     return exprs
 
 def parse_args(typeinfo):
diff --git a/tests/Makefile b/tests/Makefile
index 0a3c439..7ad20d1 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -164,7 +164,10 @@ check-qapi-schema-y := $(addprefix tests/qapi-schema/, \
         duplicate-key.json union-invalid-base.json flat-union-no-base.json \
         flat-union-invalid-discriminator.json \
         flat-union-invalid-branch-key.json flat-union-reverse-define.json \
-        flat-union-string-discriminator.json)
+        flat-union-string-discriminator.json include.json include_loop.json \
+        include_non_filename.json error_in_included_file.json \
+        error_after_sucessful_include.json multi_file_loop_include.json \
+        multiple_relative_path_include.json)
 
 GENERATED_HEADERS += tests/test-qapi-types.h tests/test-qapi-visit.h 
tests/test-qmp-commands.h
 
@@ -363,8 +366,9 @@ check-tests/test-qapi.py: tests/test-qapi.py
 .PHONY: $(patsubst %, check-%, $(check-qapi-schema-y))
 $(patsubst %, check-%, $(check-qapi-schema-y)): check-%.json: 
$(SRC_PATH)/%.json
        $(call quiet-command, PYTHONPATH=$(SRC_PATH)/scripts $(PYTHON) 
$(SRC_PATH)/tests/qapi-schema/test-qapi.py $^ >$*.test.out 2>$*.test.err; echo 
$$? >$*.test.exit, "  TEST  $*.out")
-# filter in a second step to avoid redirection madness
+# filter abspaths
        @sed -i s=.*/== $*.test.err
+       @sed -i s="/.*/"==  $*.test.out
        @diff -q $(SRC_PATH)/$*.out $*.test.out
        @diff -q $(SRC_PATH)/$*.err $*.test.err
        @diff -q $(SRC_PATH)/$*.exit $*.test.exit
diff --git a/tests/qapi-schema/error_after_sucessful_include.err 
b/tests/qapi-schema/error_after_sucessful_include.err
new file mode 100644
index 0000000..d562a83
--- /dev/null
+++ b/tests/qapi-schema/error_after_sucessful_include.err
@@ -0,0 +1 @@
+error_after_sucessful_include.json:4:10: Stray "T"
diff --git a/tests/qapi-schema/error_after_sucessful_include.exit 
b/tests/qapi-schema/error_after_sucessful_include.exit
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/tests/qapi-schema/error_after_sucessful_include.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/error_after_sucessful_include.json 
b/tests/qapi-schema/error_after_sucessful_include.json
new file mode 100644
index 0000000..c6cf313
--- /dev/null
+++ b/tests/qapi-schema/error_after_sucessful_include.json
@@ -0,0 +1,4 @@
+{ 'enum': 'Status',
+  'data': [ 'good', 'bad', 'ugly' ] }
+{ 'include': './include/include.json' }
+{ 'foo': True }
diff --git a/tests/qapi-schema/error_after_sucessful_include.out 
b/tests/qapi-schema/error_after_sucessful_include.out
new file mode 100644
index 0000000..e69de29
diff --git a/tests/qapi-schema/error_in_included_file.err 
b/tests/qapi-schema/error_in_included_file.err
new file mode 100644
index 0000000..c011fee
--- /dev/null
+++ b/tests/qapi-schema/error_in_included_file.err
@@ -0,0 +1 @@
+error.json:4:12: Stray "T"
diff --git a/tests/qapi-schema/error_in_included_file.exit 
b/tests/qapi-schema/error_in_included_file.exit
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/tests/qapi-schema/error_in_included_file.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/error_in_included_file.json 
b/tests/qapi-schema/error_in_included_file.json
new file mode 100644
index 0000000..ae8c732
--- /dev/null
+++ b/tests/qapi-schema/error_in_included_file.json
@@ -0,0 +1,4 @@
+{ 'enum': 'Status',
+  'data': [ 'good', 'bad', 'ugly' ] }
+{ 'include': 'include/error.json' }
+{ 'foo': '42' }
diff --git a/tests/qapi-schema/error_in_included_file.out 
b/tests/qapi-schema/error_in_included_file.out
new file mode 100644
index 0000000..e69de29
diff --git a/tests/qapi-schema/include.err b/tests/qapi-schema/include.err
new file mode 100644
index 0000000..e69de29
diff --git a/tests/qapi-schema/include.exit b/tests/qapi-schema/include.exit
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/tests/qapi-schema/include.exit
@@ -0,0 +1 @@
+0
diff --git a/tests/qapi-schema/include.json b/tests/qapi-schema/include.json
new file mode 100644
index 0000000..ffece21
--- /dev/null
+++ b/tests/qapi-schema/include.json
@@ -0,0 +1,4 @@
+{ 'enum': 'Status',
+  'data': [ 'good', 'bad', 'ugly' ] }
+{ 'include': './include/include.json' }
+{ 'foo': '42' }
diff --git a/tests/qapi-schema/include.out b/tests/qapi-schema/include.out
new file mode 100644
index 0000000..89e43e8
--- /dev/null
+++ b/tests/qapi-schema/include.out
@@ -0,0 +1,8 @@
+[OrderedDict([('enum', 'Status'), ('data', ['good', 'bad', 'ugly'])]),
+ OrderedDict([('bar', '33')]),
+ OrderedDict([('enum', 'Fruits'), ('data', ['orange', 'apple', 
'gooseberry'])]),
+ OrderedDict([('baz', '54')]),
+ OrderedDict([('foo', '42')])]
+[{'enum_name': 'Status', 'enum_values': ['good', 'bad', 'ugly']},
+ {'enum_name': 'Fruits', 'enum_values': ['orange', 'apple', 'gooseberry']}]
+[]
diff --git a/tests/qapi-schema/include/error.json 
b/tests/qapi-schema/include/error.json
new file mode 100644
index 0000000..33ac12c
--- /dev/null
+++ b/tests/qapi-schema/include/error.json
@@ -0,0 +1,6 @@
+
+{ 'foo': '43' }
+
+{ 'zerg' : True }
+
+{ 'bar' : '65' }
diff --git a/tests/qapi-schema/include/include.json 
b/tests/qapi-schema/include/include.json
new file mode 100644
index 0000000..f445eee
--- /dev/null
+++ b/tests/qapi-schema/include/include.json
@@ -0,0 +1,7 @@
+
+{ 'bar': '33' }
+
+{ 'enum': 'Fruits',
+  'data': [ 'orange', 'apple', 'gooseberry' ] }
+
+{ 'baz': '54' }
diff --git a/tests/qapi-schema/include/multi.json 
b/tests/qapi-schema/include/multi.json
new file mode 100644
index 0000000..692480c
--- /dev/null
+++ b/tests/qapi-schema/include/multi.json
@@ -0,0 +1 @@
+{ 'include': '../comments.json' }
diff --git a/tests/qapi-schema/include/multi_loop.json 
b/tests/qapi-schema/include/multi_loop.json
new file mode 100644
index 0000000..7c187b8
--- /dev/null
+++ b/tests/qapi-schema/include/multi_loop.json
@@ -0,0 +1 @@
+{ 'include': '../multi_file_loop_include.json' }
diff --git a/tests/qapi-schema/include_loop.err 
b/tests/qapi-schema/include_loop.err
new file mode 100644
index 0000000..e69de29
diff --git a/tests/qapi-schema/include_loop.exit 
b/tests/qapi-schema/include_loop.exit
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/tests/qapi-schema/include_loop.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/include_loop.json 
b/tests/qapi-schema/include_loop.json
new file mode 100644
index 0000000..cb8ff03
--- /dev/null
+++ b/tests/qapi-schema/include_loop.json
@@ -0,0 +1 @@
+{ 'include': 'include_loop.json' }
diff --git a/tests/qapi-schema/include_loop.out 
b/tests/qapi-schema/include_loop.out
new file mode 100644
index 0000000..eaecfd3
--- /dev/null
+++ b/tests/qapi-schema/include_loop.out
@@ -0,0 +1,3 @@
+Inclusion loop detected with file: include_loop.json
+Path to the broken include is:
+       include_loop.json
diff --git a/tests/qapi-schema/include_non_filename.err 
b/tests/qapi-schema/include_non_filename.err
new file mode 100644
index 0000000..9b02b3a
--- /dev/null
+++ b/tests/qapi-schema/include_non_filename.err
@@ -0,0 +1 @@
+include_non_filename.json:3: filename to include must be a string
diff --git a/tests/qapi-schema/include_non_filename.exit 
b/tests/qapi-schema/include_non_filename.exit
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/tests/qapi-schema/include_non_filename.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/include_non_filename.json 
b/tests/qapi-schema/include_non_filename.json
new file mode 100644
index 0000000..6042b12
--- /dev/null
+++ b/tests/qapi-schema/include_non_filename.json
@@ -0,0 +1,4 @@
+{ 'enum': 'Status',
+  'data': [ 'good', 'bad', 'ugly' ] }
+{ 'include': [ 'foo', 'bar'] }
+{ 'foo': '42' }
diff --git a/tests/qapi-schema/include_non_filename.out 
b/tests/qapi-schema/include_non_filename.out
new file mode 100644
index 0000000..e69de29
diff --git a/tests/qapi-schema/multi_file_loop_include.err 
b/tests/qapi-schema/multi_file_loop_include.err
new file mode 100644
index 0000000..e69de29
diff --git a/tests/qapi-schema/multi_file_loop_include.exit 
b/tests/qapi-schema/multi_file_loop_include.exit
new file mode 100644
index 0000000..d00491f
--- /dev/null
+++ b/tests/qapi-schema/multi_file_loop_include.exit
@@ -0,0 +1 @@
+1
diff --git a/tests/qapi-schema/multi_file_loop_include.json 
b/tests/qapi-schema/multi_file_loop_include.json
new file mode 100644
index 0000000..0b11f27
--- /dev/null
+++ b/tests/qapi-schema/multi_file_loop_include.json
@@ -0,0 +1,4 @@
+{ 'enum': 'Status',
+  'data': [ 'good', 'bad', 'ugly' ] }
+{ 'include': './include/multi_loop.json' }
+{ 'foo': '42' }
diff --git a/tests/qapi-schema/multi_file_loop_include.out 
b/tests/qapi-schema/multi_file_loop_include.out
new file mode 100644
index 0000000..9af609b
--- /dev/null
+++ b/tests/qapi-schema/multi_file_loop_include.out
@@ -0,0 +1,4 @@
+Inclusion loop detected with file: multi_file_loop_include.json
+Path to the broken include is:
+       multi_file_loop_include.json
+       multi_loop.json
diff --git a/tests/qapi-schema/multiple_relative_path_include.err 
b/tests/qapi-schema/multiple_relative_path_include.err
new file mode 100644
index 0000000..e69de29
diff --git a/tests/qapi-schema/multiple_relative_path_include.exit 
b/tests/qapi-schema/multiple_relative_path_include.exit
new file mode 100644
index 0000000..573541a
--- /dev/null
+++ b/tests/qapi-schema/multiple_relative_path_include.exit
@@ -0,0 +1 @@
+0
diff --git a/tests/qapi-schema/multiple_relative_path_include.json 
b/tests/qapi-schema/multiple_relative_path_include.json
new file mode 100644
index 0000000..3afd95b
--- /dev/null
+++ b/tests/qapi-schema/multiple_relative_path_include.json
@@ -0,0 +1,4 @@
+{ 'enum': 'Failure',
+  'data': [ 'orange', 'apple', 'apricot' ] }
+{ 'include': './include/multi.json' }
+{ 'foo': '42' }
diff --git a/tests/qapi-schema/multiple_relative_path_include.out 
b/tests/qapi-schema/multiple_relative_path_include.out
new file mode 100644
index 0000000..e75c817
--- /dev/null
+++ b/tests/qapi-schema/multiple_relative_path_include.out
@@ -0,0 +1,6 @@
+[OrderedDict([('enum', 'Failure'), ('data', ['orange', 'apple', 'apricot'])]),
+ OrderedDict([('enum', 'Status'), ('data', ['good', 'bad', 'ugly'])]),
+ OrderedDict([('foo', '42')])]
+[{'enum_name': 'Failure', 'enum_values': ['orange', 'apple', 'apricot']},
+ {'enum_name': 'Status', 'enum_values': ['good', 'bad', 'ugly']}]
+[]
-- 
1.7.10.4




reply via email to

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