From 6cc2e4817ff5b33d6f67e0a5f27dbd1112d1ecd5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 4 Aug 2021 12:30:59 +0400 Subject: qapi: introduce QAPISchemaIfCond.cgen() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of building prepocessor conditions from a list of string, use the result generated from QAPISchemaIfCond.cgen() and hide the implementation details. Note: this patch introduces a minor regression, generating a redundant pair of parenthesis. This is mostly fixed in a later patch in this series ("qapi: replace if condition list with dict [..]") Signed-off-by: Marc-André Lureau Message-Id: <20210804083105.97531-5-marcandre.lureau@redhat.com> Reviewed-by: Markus Armbruster [Commit message tweaked] Signed-off-by: Markus Armbruster --- scripts/qapi/common.py | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) (limited to 'scripts/qapi/common.py') diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py index 6ad1eeb..ba9fe14 100644 --- a/scripts/qapi/common.py +++ b/scripts/qapi/common.py @@ -12,7 +12,12 @@ # See the COPYING file in the top-level directory. import re -from typing import Match, Optional, Sequence +from typing import ( + List, + Match, + Optional, + Union, +) #: Magic string that gets removed along with all space to its right. @@ -194,22 +199,26 @@ def guardend(name: str) -> str: name=c_fname(name).upper()) -def gen_if(ifcond: Sequence[str]) -> str: - ret = '' - for ifc in ifcond: - ret += mcgen(''' +def cgen_ifcond(ifcond: Union[str, List[str]]) -> str: + if not ifcond: + return '' + return '(' + ') && ('.join(ifcond) + ')' + + +def gen_if(cond: str) -> str: + if not cond: + return '' + return mcgen(''' #if %(cond)s -''', cond=ifc) - return ret +''', cond=cond) -def gen_endif(ifcond: Sequence[str]) -> str: - ret = '' - for ifc in reversed(ifcond): - ret += mcgen(''' +def gen_endif(cond: str) -> str: + if not cond: + return '' + return mcgen(''' #endif /* %(cond)s */ -''', cond=ifc) - return ret +''', cond=cond) def must_match(pattern: str, string: str) -> Match[str]: -- cgit v1.1 From d806f89f87152def5f422e946c84948831615236 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 4 Aug 2021 12:31:00 +0400 Subject: qapidoc: introduce QAPISchemaIfCond.docgen() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Instead of building the condition documentation from a list of string, use the result generated from QAPISchemaIfCond.docgen(). This changes the generated documentation from: - COND1, COND2... (where COND1, COND2 are Literal nodes, and ',' is Text) to: - COND1 and COND2 (the whole string as a Literal node) This will allow us to generate more complex conditions in the following patches, such as "(COND1 and COND2) or COND3". Adding back the differentiated formatting is left to the wish list. Signed-off-by: Marc-André Lureau Message-Id: <20210804083105.97531-6-marcandre.lureau@redhat.com> Reviewed-by: Markus Armbruster [TODO comment added] Signed-off-by: Markus Armbruster --- scripts/qapi/common.py | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'scripts/qapi/common.py') diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py index ba9fe14..ddc54e4 100644 --- a/scripts/qapi/common.py +++ b/scripts/qapi/common.py @@ -205,6 +205,13 @@ def cgen_ifcond(ifcond: Union[str, List[str]]) -> str: return '(' + ') && ('.join(ifcond) + ')' +def docgen_ifcond(ifcond: Union[str, List[str]]) -> str: + # TODO Doc generated for conditions needs polish + if not ifcond: + return '' + return ' and '.join(ifcond) + + def gen_if(cond: str) -> str: if not cond: return '' -- cgit v1.1 From 5d83b9a130690f879d5f33e991beabe69cb88bc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 4 Aug 2021 12:31:01 +0400 Subject: qapi: replace if condition list with dict {'all': [...]} MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Replace the simple list sugar form with a recursive structure that will accept other operators in the following commits (all, any or not). Signed-off-by: Marc-André Lureau Message-Id: <20210804083105.97531-7-marcandre.lureau@redhat.com> Reviewed-by: Markus Armbruster [Accidental code motion undone. Degenerate :forms: comment dropped. Helper _check_if() moved. Error messages tweaked. ui.json updated. Accidental changes to qapi-schema-test.json dropped.] Signed-off-by: Markus Armbruster --- scripts/qapi/common.py | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) (limited to 'scripts/qapi/common.py') diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py index ddc54e4..3d7272a 100644 --- a/scripts/qapi/common.py +++ b/scripts/qapi/common.py @@ -13,7 +13,8 @@ import re from typing import ( - List, + Any, + Dict, Match, Optional, Union, @@ -199,17 +200,29 @@ def guardend(name: str) -> str: name=c_fname(name).upper()) -def cgen_ifcond(ifcond: Union[str, List[str]]) -> str: +def cgen_ifcond(ifcond: Union[str, Dict[str, Any]]) -> str: if not ifcond: return '' - return '(' + ') && ('.join(ifcond) + ')' + if isinstance(ifcond, str): + return ifcond + oper, operands = next(iter(ifcond.items())) + oper = {'all': '&&'}[oper] + operands = [cgen_ifcond(o) for o in operands] + return '(' + (') ' + oper + ' (').join(operands) + ')' -def docgen_ifcond(ifcond: Union[str, List[str]]) -> str: + +def docgen_ifcond(ifcond: Union[str, Dict[str, Any]]) -> str: # TODO Doc generated for conditions needs polish if not ifcond: return '' - return ' and '.join(ifcond) + if isinstance(ifcond, str): + return ifcond + + oper, operands = next(iter(ifcond.items())) + oper = {'all': ' and '}[oper] + operands = [docgen_ifcond(o) for o in operands] + return '(' + oper.join(operands) + ')' def gen_if(cond: str) -> str: -- cgit v1.1 From 3ad64edfad2fa404e866c01f6d427ed4fe4f4f0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 4 Aug 2021 12:31:02 +0400 Subject: qapi: add 'any' condition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Marc-André Lureau Message-Id: <20210804083105.97531-8-marcandre.lureau@redhat.com> Reviewed-by: Markus Armbruster Signed-off-by: Markus Armbruster --- scripts/qapi/common.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'scripts/qapi/common.py') diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py index 3d7272a..63a2e50 100644 --- a/scripts/qapi/common.py +++ b/scripts/qapi/common.py @@ -207,7 +207,7 @@ def cgen_ifcond(ifcond: Union[str, Dict[str, Any]]) -> str: return ifcond oper, operands = next(iter(ifcond.items())) - oper = {'all': '&&'}[oper] + oper = {'all': '&&', 'any': '||'}[oper] operands = [cgen_ifcond(o) for o in operands] return '(' + (') ' + oper + ' (').join(operands) + ')' @@ -220,7 +220,7 @@ def docgen_ifcond(ifcond: Union[str, Dict[str, Any]]) -> str: return ifcond oper, operands = next(iter(ifcond.items())) - oper = {'all': ' and '}[oper] + oper = {'all': ' and ', 'any': ' or '}[oper] operands = [docgen_ifcond(o) for o in operands] return '(' + oper.join(operands) + ')' -- cgit v1.1 From 2b7d2145369f2ca55ded9045393bb860ee3f6745 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 4 Aug 2021 12:31:04 +0400 Subject: qapi: add 'not' condition operation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For the sake of completeness, introduce the 'not' condition. Signed-off-by: Marc-André Lureau Message-Id: <20210804083105.97531-10-marcandre.lureau@redhat.com> Reviewed-by: Markus Armbruster [Long line broken in tests/qapi-schema/qapi-schema-test.json] Signed-off-by: Markus Armbruster --- scripts/qapi/common.py | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'scripts/qapi/common.py') diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py index 63a2e50..3fb2fbe 100644 --- a/scripts/qapi/common.py +++ b/scripts/qapi/common.py @@ -207,6 +207,8 @@ def cgen_ifcond(ifcond: Union[str, Dict[str, Any]]) -> str: return ifcond oper, operands = next(iter(ifcond.items())) + if oper == 'not': + return '!' + cgen_ifcond(operands) oper = {'all': '&&', 'any': '||'}[oper] operands = [cgen_ifcond(o) for o in operands] return '(' + (') ' + oper + ' (').join(operands) + ')' @@ -220,6 +222,8 @@ def docgen_ifcond(ifcond: Union[str, Dict[str, Any]]) -> str: return ifcond oper, operands = next(iter(ifcond.items())) + if oper == 'not': + return '!' + docgen_ifcond(operands) oper = {'all': ' and ', 'any': ' or '}[oper] operands = [docgen_ifcond(o) for o in operands] return '(' + oper.join(operands) + ')' -- cgit v1.1 From 8a9f1e1d9cc55f5eb0946cbf8fd1ef9a0e7d3dac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Wed, 4 Aug 2021 12:31:05 +0400 Subject: qapi: make 'if' condition strings simple identifiers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change the 'if' condition strings to be C-agnostic. It will accept '[A-Z][A-Z0-9_]*' identifiers. This allows to express configuration conditions in other languages (Rust or Python for ex) or other more suitable forms. Signed-off-by: Marc-André Lureau Reviewed-by: Stefan Hajnoczi Tested-by: John Snow Message-Id: <20210804083105.97531-11-marcandre.lureau@redhat.com> Reviewed-by: Markus Armbruster [Rebased with semantic conflict in redefined-event.json] Signed-off-by: Markus Armbruster --- scripts/qapi/common.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'scripts/qapi/common.py') diff --git a/scripts/qapi/common.py b/scripts/qapi/common.py index 3fb2fbe..1724ac3 100644 --- a/scripts/qapi/common.py +++ b/scripts/qapi/common.py @@ -204,7 +204,7 @@ def cgen_ifcond(ifcond: Union[str, Dict[str, Any]]) -> str: if not ifcond: return '' if isinstance(ifcond, str): - return ifcond + return 'defined(' + ifcond + ')' oper, operands = next(iter(ifcond.items())) if oper == 'not': -- cgit v1.1