We know have a way to parse runtime conditionals in QAPI json, and hide qlit elements at runtime. So we can combine both to hide elements in our schema based on a conditional specified in json.
Signed-off-by: Pierrick Bouvier <pierrick.bouv...@linaro.org> --- scripts/qapi/introspect.py | 28 +++++++++++++++++++--------- scripts/qapi/schema.py | 3 +++ 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/scripts/qapi/introspect.py b/scripts/qapi/introspect.py index e0269bef0ce..c70b97a455d 100644 --- a/scripts/qapi/introspect.py +++ b/scripts/qapi/introspect.py @@ -94,7 +94,8 @@ class Annotated(Generic[_ValueT]): def _tree_to_qlit(obj: JSONValue, level: int = 0, - dict_value: bool = False) -> str: + dict_value: bool = False, + hidden_cond: str = '') -> str: """ Convert the type tree into a QLIT C string, recursively. @@ -120,7 +121,11 @@ def indent(level: int) -> str: ret += indent(level) + f"/* {obj.comment} */\n" if obj.ifcond.is_present(): ret += obj.ifcond.gen_if() - ret += _tree_to_qlit(obj.value, level) + hidden_cond = obj.ifcond.get_runtime_cond() + # reverse runtime_if + if hidden_cond: + hidden_cond = '!(' + hidden_cond + ')' + ret += _tree_to_qlit(obj.value, level, hidden_cond=hidden_cond) if obj.ifcond.is_present(): ret += '\n' + obj.ifcond.gen_endif() return ret @@ -129,30 +134,35 @@ def indent(level: int) -> str: if not dict_value: ret += indent(level) + macro_suffix = '' + if hidden_cond: + macro_suffix = '_HIDDEN' + hidden_cond = ', (' + hidden_cond + ')' + # Scalars: if obj is None: ret += 'QLIT_QNULL' elif isinstance(obj, str): - ret += f"QLIT_QSTR({to_c_string(obj)})" + ret += f"QLIT_QSTR{macro_suffix}({to_c_string(obj)}{hidden_cond})" elif isinstance(obj, bool): - ret += f"QLIT_QBOOL({str(obj).lower()})" + ret += f"QLIT_QBOOL{macro_suffix}({str(obj).lower()}{hidden_cond})" # Non-scalars: elif isinstance(obj, list): - ret += 'QLIT_QLIST(((QLitObject[]) {\n' + ret += 'QLIT_QLIST' + macro_suffix + '(((QLitObject[]) {\n' for value in obj: ret += _tree_to_qlit(value, level + 1).strip('\n') + '\n' ret += indent(level + 1) + '{}\n' - ret += indent(level) + '}))' + ret += indent(level) + '})' + hidden_cond + ')' elif isinstance(obj, dict): - ret += 'QLIT_QDICT(((QLitDictEntry[]) {\n' + ret += 'QLIT_QDICT' + macro_suffix + '(((QLitDictEntry[]) {\n' for key, value in sorted(obj.items()): ret += indent(level + 1) + "{{ {:s}, {:s} }},\n".format( to_c_string(key), - _tree_to_qlit(value, level + 1, dict_value=True) + _tree_to_qlit(value, level + 1, dict_value=True), ) ret += indent(level + 1) + '{}\n' - ret += indent(level) + '}))' + ret += indent(level) + '})' + hidden_cond + ')' else: raise NotImplementedError( f"type '{type(obj).__name__}' not implemented" diff --git a/scripts/qapi/schema.py b/scripts/qapi/schema.py index 533d0dfe088..7767893f979 100644 --- a/scripts/qapi/schema.py +++ b/scripts/qapi/schema.py @@ -79,6 +79,9 @@ def gen_runtime_if(self) -> str: def gen_runtime_endif(self) -> str: return gen_runtime_endif(self._cgen_runtime()) + def get_runtime_cond(self) -> str: + return self._cgen_runtime() + def is_present(self) -> bool: return bool(self.ifcond) or bool(self.runtime_ifcond) -- 2.47.2