# lib9p/protogen/cutil.py - Utilities for generating C code # # Copyright (C) 2024-2025 Luke T. Shumaker # SPDX-License-Identifier: AGPL-3.0-or-later # pylint: disable=unused-variable __all__ = [ "UINT32_MAX", "UINT64_MAX", "macro", "ifdef_init", "ifdef_push", "ifdef_pop", "ifdef_leaf_is_noop", ] UINT32_MAX = (1 << 32) - 1 UINT64_MAX = (1 << 64) - 1 def tab_ljust(s: str, width: int) -> str: cur = len(s.expandtabs(tabsize=8)) if cur >= width: return s return s + " " * (width - cur) def macro(full: str) -> str: full = full.rstrip() assert "\n" in full lines = [l.rstrip() for l in full.split("\n")] width = max(len(l.expandtabs(tabsize=8)) for l in lines[:-1]) lines = [tab_ljust(l, width) for l in lines] return " \\\n".join(lines).rstrip() + "\n" _ifdef_stack: list[str | None] = [] def ifdef_init() -> None: global _ifdef_stack _ifdef_stack = [] def ifdef_push(n: int, _newval: str) -> str: # Grow the stack as needed while len(_ifdef_stack) < n: _ifdef_stack.append(None) # Set some variables parentval: str | None = None for x in _ifdef_stack[:-1]: if x is not None: parentval = x oldval = _ifdef_stack[-1] newval: str | None = _newval if newval == parentval: newval = None # Put newval on the stack. _ifdef_stack[-1] = newval # Build output. ret = "" if newval != oldval: if oldval is not None: ret += f"#endif /* {oldval} */\n" if newval is not None: ret += f"#if {newval}\n" return ret def ifdef_pop(n: int) -> str: global _ifdef_stack ret = "" while len(_ifdef_stack) > n: if _ifdef_stack[-1] is not None: ret += f"#endif /* {_ifdef_stack[-1]} */\n" _ifdef_stack = _ifdef_stack[:-1] return ret def ifdef_leaf_is_noop() -> bool: return not _ifdef_stack[-1]