diff options
Diffstat (limited to 'lib9p/idl.gen')
-rwxr-xr-x | lib9p/idl.gen | 126 |
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) |