summaryrefslogtreecommitdiff
path: root/lib9p/idl.gen
diff options
context:
space:
mode:
Diffstat (limited to 'lib9p/idl.gen')
-rwxr-xr-xlib9p/idl.gen126
1 files changed, 81 insertions, 45 deletions
diff --git a/lib9p/idl.gen b/lib9p/idl.gen
index 779b6d5..eaeca49 100755
--- a/lib9p/idl.gen
+++ b/lib9p/idl.gen
@@ -147,8 +147,8 @@ def ifdef_pop(n: int) -> str:
# topo_sorted() ################################################################
-def topo_sorted(typs: list[idl.Type]) -> typing.Iterable[idl.Type]:
- ts: graphlib.TopologicalSorter[idl.Type] = graphlib.TopologicalSorter()
+def topo_sorted(typs: list[idl.UserType]) -> typing.Iterable[idl.UserType]:
+ ts: graphlib.TopologicalSorter[idl.UserType] = graphlib.TopologicalSorter()
for typ in typs:
match typ:
case idl.Number():
@@ -375,7 +375,7 @@ def get_buffer_size(typ: idl.Type, version: str) -> BufferSize:
# Generate .h ##################################################################
-def gen_h(versions: set[str], typs: list[idl.Type]) -> str:
+def gen_h(versions: set[str], typs: list[idl.UserType]) -> str:
global _ifdef_stack
_ifdef_stack = []
@@ -440,9 +440,7 @@ enum {idprefix}version {{
continue
msg = id2typ[n]
ret += ifdef_push(1, c_ver_ifdef(msg.in_versions))
- ret += (
- f"\t{idprefix.upper()}TYP_{msg.typname.ljust(namewidth)} = {msg.msgid},\n"
- )
+ ret += f"\t{idprefix.upper()}TYP_{msg.typname:<{namewidth}} = {msg.msgid},\n"
ret += ifdef_pop(0)
ret += "};\n"
@@ -451,7 +449,7 @@ enum {idprefix}version {{
"""
def per_version_comment(
- typ: idl.Type, fn: typing.Callable[[idl.Type, str], str]
+ typ: idl.UserType, fn: typing.Callable[[idl.UserType, str], str]
) -> str:
lines: dict[str, str] = {}
for version in sorted(typ.in_versions):
@@ -464,14 +462,14 @@ enum {idprefix}version {{
ret = ""
v_width = max(len(c_ver_enum(v)) for v in typ.in_versions)
for version, line in lines.items():
- ret += f"/* {c_ver_enum(version).ljust(v_width)}: {line} */\n"
+ ret += f"/* {c_ver_enum(version):<{v_width}}: {line} */\n"
return ret
for typ in topo_sorted(typs):
ret += "\n"
ret += ifdef_push(1, c_ver_ifdef(typ.in_versions))
- def sum_size(typ: idl.Type, version: str) -> str:
+ def sum_size(typ: idl.UserType, version: str) -> str:
sz = get_buffer_size(typ, version)
assert (
sz.min_size <= sz.exp_size
@@ -496,48 +494,78 @@ enum {idprefix}version {{
prefix = f"{idprefix.upper()}{typ.typname.upper()}_"
namewidth = max(len(name) for name in typ.vals)
for name, val in typ.vals.items():
- ret += f"#define {prefix}{name.ljust(namewidth)} (({c_typename(typ)})UINT{typ.static_size*8}_C({val}))\n"
+ ret += f"#define {prefix}{name:<{namewidth}} (({c_typename(typ)})UINT{typ.static_size*8}_C({val}))\n"
case idl.Bitfield():
ret += f"typedef {c_typename(typ.prim)} {c_typename(typ)};\n"
- names = [
- typ.bits[n] or f" {n}" for n in reversed(range(0, len(typ.bits)))
- ]
- if aliases := [k for k in typ.names if k not in typ.bits]:
- names.append("")
- names.extend(aliases)
- prefix = f"{idprefix.upper()}{typ.typname.upper()}_"
- namewidth = max(len(add_prefix(prefix, name)) for name in names)
- ret += "\n"
- for name in names:
- if name == "":
- ret += "\n"
- continue
+ def bitname(val: idl.Bit | idl.BitAlias) -> str:
+ s = val.bitname
+ match val:
+ case idl.Bit(cat=idl.BitCat.RESERVED):
+ s = "_RESERVED_" + s
+ case idl.Bit(cat=idl.BitCat.SUBFIELD):
+ assert isinstance(typ, idl.Bitfield)
+ n = sum(
+ 1
+ for b in typ.bits[: val.num]
+ if b.cat == idl.BitCat.SUBFIELD
+ and b.bitname == val.bitname
+ )
+ s = f"_{s}_{n}"
+ case idl.Bit(cat=idl.BitCat.UNUSED):
+ return ""
+ return add_prefix(f"{idprefix.upper()}{typ.typname.upper()}_", s)
- if name.startswith(" "):
- vers = typ.in_versions
- c_name = ""
- c_val = f"1<<{name[1:]}"
- else:
- vers = typ.names[name].in_versions
- c_name = add_prefix(prefix, name)
- c_val = f"{typ.names[name].val}"
+ namewidth = max(
+ len(bitname(val)) for val in [*typ.bits, *typ.names.values()]
+ )
+ ret += "\n"
+ for bit in reversed(typ.bits):
+ vers = bit.in_versions
+ if bit.cat == idl.BitCat.UNUSED:
+ vers = typ.in_versions
ret += ifdef_push(2, c_ver_ifdef(vers))
# It is important all of the `beg` strings have
# the same length.
end = ""
- if name.startswith(" "):
- beg = "/* unused"
- end = " */"
- elif _ifdef_stack[-1]:
- beg = "# define"
- else:
- beg = "#define "
+ match bit.cat:
+ case (
+ idl.BitCat.USED | idl.BitCat.RESERVED | idl.BitCat.SUBFIELD
+ ):
+ if _ifdef_stack[-1]:
+ beg = "# define"
+ else:
+ beg = "#define "
+ case idl.BitCat.UNUSED:
+ beg = "/* unused"
+ end = " */"
+
+ c_name = bitname(bit)
+ c_val = f"1<<{bit.num}"
+ ret += f"{beg} {c_name:<{namewidth}} (({c_typename(typ)})({c_val})){end}\n"
+ if aliases := [
+ alias
+ for alias in typ.names.values()
+ if isinstance(alias, idl.BitAlias)
+ ]:
+ ret += "\n"
- ret += f"{beg} {c_name.ljust(namewidth)} (({c_typename(typ)})({c_val})){end}\n"
+ for alias in aliases:
+ ret += ifdef_push(2, c_ver_ifdef(alias.in_versions))
+
+ end = ""
+ if _ifdef_stack[-1]:
+ beg = "# define"
+ else:
+ beg = "#define "
+
+ c_name = bitname(alias)
+ c_val = alias.val
+ ret += f"{beg} {c_name:<{namewidth}} (({c_typename(typ)})({c_val})){end}\n"
ret += ifdef_pop(1)
+ del bitname
case idl.Struct(): # and idl.Message():
ret += c_typename(typ) + " {"
if not typ.members:
@@ -551,9 +579,10 @@ enum {idprefix}version {{
if member.val:
continue
ret += ifdef_push(2, c_ver_ifdef(member.in_versions))
- ret += f"\t{c_typename(member.typ, member).ljust(typewidth)} {'*' if member.cnt else ' '}{member.membname};\n"
+ ret += f"\t{c_typename(member.typ, member):<{typewidth}} {'*' if member.cnt else ' '}{member.membname};\n"
ret += ifdef_pop(1)
ret += "};\n"
+ del typ
ret += ifdef_pop(0)
ret += """
@@ -643,7 +672,7 @@ enum {idprefix}version {{
# Generate .c ##################################################################
-def gen_c(versions: set[str], typs: list[idl.Type]) -> str:
+def gen_c(versions: set[str], typs: list[idl.UserType]) -> str:
global _ifdef_stack
_ifdef_stack = []
@@ -746,8 +775,13 @@ const char *const _{idprefix}table_ver_name[{c_ver_enum('NUM')}] = {{
ret += (
f"\t[{c_ver_enum(ver)}]{' '*(verwidth-len(ver))} = 0b"
+ "".join(
- "1" if typ.bit_is_valid(bitname, ver) else "0"
- for bitname in reversed(typ.bits)
+ (
+ "1"
+ if bit.cat in (idl.BitCat.USED, idl.BitCat.SUBFIELD)
+ and ver in bit.in_versions
+ else "0"
+ )
+ for bit in reversed(typ.bits)
)
+ ",\n"
)
@@ -1088,7 +1122,7 @@ LM_ALWAYS_INLINE static void unmarshal_8(struct _unmarshal_ctx *ctx, uint64_t *o
type OffsetExprRecursion = typing.Callable[[Path], WalkCmd]
- def get_offset_expr(typ: idl.Type, recurse: OffsetExprRecursion) -> OffsetExpr:
+ def get_offset_expr(typ: idl.UserType, recurse: OffsetExprRecursion) -> OffsetExpr:
if not isinstance(typ, idl.Struct):
assert typ.static_size
ret = OffsetExpr()
@@ -1384,8 +1418,10 @@ def main() -> None:
)
assert e.text
print(f"\t{e.text}", file=sys.stderr)
+ text_suffix = e.text.lstrip()
+ text_prefix = e.text[: -len(text_suffix)]
print(
- f"\t{ANSIColors.RED}{'~'*len(e.text)}{ANSIColors.RESET}",
+ f"\t{text_prefix}{ANSIColors.RED}{'~'*len(text_suffix)}{ANSIColors.RESET}",
file=sys.stderr,
)
sys.exit(2)