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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
# lib9p/protogen/c9util.py - Utilities for generating lib9p-specific C
#
# Copyright (C) 2024-2025 Luke T. Shumaker <lukeshu@lukeshu.com>
# SPDX-License-Identifier: AGPL-3.0-or-later
import typing
import idl
# This strives to be "general-purpose" in that it just acts on the
# *.9p inputs; but (unfortunately?) there are a few special-cases in
# this script, marked with "SPECIAL".
# pylint: disable=unused-variable
__all__ = [
"add_prefix",
"ident",
"Ident",
"IDENT",
"ver_enum",
"ver_ifdef",
"ver_cond",
"typename",
"idl_expr",
]
# idents #######################################################################
def add_prefix(p: str, s: str) -> str:
if s.startswith("_"):
return "_" + p + s[1:]
return p + s
def _ident(p: str, s: str) -> str:
return add_prefix(p, s.replace(".", "_"))
def ident(s: str) -> str:
return _ident("lib9p_", s)
def Ident(s: str) -> str:
return _ident("lib9p_".upper(), s)
def IDENT(s: str) -> str:
return _ident("lib9p_", s).upper()
# versions #####################################################################
def ver_enum(ver: str) -> str:
return Ident("VER_" + ver)
def ver_ifdef(versions: typing.Collection[str]) -> str:
return " || ".join(
f"CONFIG_9P_ENABLE_{v.replace('.', '_')}" for v in sorted(versions)
)
def ver_cond(versions: typing.Collection[str]) -> str:
if len(versions) == 1:
v = next(v for v in versions)
return f"is_ver(ctx, {v.replace('.', '_')})"
return "( " + (" || ".join(ver_cond({v}) for v in sorted(versions))) + " )"
# misc #########################################################################
def typename(typ: idl.Type, parent: idl.StructMember | None = None) -> str:
match typ:
case idl.Primitive():
if typ.value == 1 and parent and parent.cnt: # SPECIAL (string)
return "[[gnu::nonstring]] char"
return f"uint{typ.value*8}_t"
case idl.Number():
return ident(f"{typ.typname}_t")
case idl.Bitfield():
return ident(f"{typ.typname}_t")
case idl.Message():
return f"struct {ident(f'msg_{typ.typname}')}"
case idl.Struct():
return f"struct {ident(typ.typname)}"
case _:
raise ValueError(f"not a type: {typ.__class__.__name__}")
def idl_expr(expr: idl.Expr, lookup_sym: typing.Callable[[str], str]) -> str:
ret: list[str] = []
for tok in expr.tokens:
match tok:
case idl.ExprOp():
ret.append(tok.op)
case idl.ExprLit():
ret.append(str(tok.val))
case idl.ExprSym(symname="s32_max"):
ret.append("INT32_MAX")
case idl.ExprSym(symname="s64_max"):
ret.append("INT64_MAX")
case idl.ExprSym():
ret.append(lookup_sym(tok.symname))
case _:
assert False
return " ".join(ret)
def arg_used(arg: str) -> str:
return arg
def arg_unused(arg: str) -> str:
return f"LM_UNUSED({arg})"
|