summaryrefslogtreecommitdiff
path: root/lib9p/protogen/cutil.py
blob: a78cd1721c257bf3698f6ff933adbf8dcb732228 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# lib9p/protogen/cutil.py - Utilities for generating C code
#
# Copyright (C) 2024-2025  Luke T. Shumaker <lukeshu@lukeshu.com>
# 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]