diff options
Diffstat (limited to 'lib9p/types.gen')
-rwxr-xr-x | lib9p/types.gen | 64 |
1 files changed, 44 insertions, 20 deletions
diff --git a/lib9p/types.gen b/lib9p/types.gen index 0c9269d..c793d20 100755 --- a/lib9p/types.gen +++ b/lib9p/types.gen @@ -256,11 +256,11 @@ def parse_file( bf.bits[bit] = name assert version - _val = BitfieldVal() - _val.name = name - _val.val = f"1<<{bit}" - _val.ver.add(version) - bf.names[name] = _val + val = BitfieldVal() + val.name = name + val.val = f"1<<{bit}" + val.ver.add(version) + bf.names[name] = val elif m := re.fullmatch(re_bitfieldspec_alias, line): if m.group("bitfield"): if m.group("bitfield") not in env: @@ -276,16 +276,16 @@ def parse_file( ) bf = prev name = m.group("name") - val = m.group("val") + valstr = m.group("val") if name in bf.names: raise ValueError(f"{bf.name}: name {name} already assigned") assert version - _val = BitfieldVal() - _val.name = name - _val.val = val - _val.ver.add(version) - bf.names[name] = _val + val = BitfieldVal() + val.name = name + val.val = valstr + val.ver.add(version) + bf.names[name] = val else: raise SyntaxError(f"invalid line {repr(line)}") if not version: @@ -384,6 +384,7 @@ enum {idprefix}version {{ *[k for k in bf.names if k not in bf.bits], ] namewidth = max(len(name) for name in names) + for name in names: if name.startswith("_"): cname = f"_{idprefix.upper()}{bf.name.upper()}_{name[1:]}" @@ -394,7 +395,10 @@ enum {idprefix}version {{ else: assert name.startswith("_UNUSED_") val = f"1<<{name[len('_UNUSED_'):]}" - ret += f"#define {cname}{' '*(namewidth-len(name))} (({c_typename(idprefix, bf)})({val}))\n" + ret += f"#define {cname}{' '*(namewidth-len(name))} (({c_typename(idprefix, bf)})({val}))" + if (name in bf.names) and (comment := c_vercomment(bf.names[name].ver)): + ret += " " + comment + ret += "\n" for struct in just_structs_nonmsg(typs): all_the_same = len(struct.members) == 0 or all( @@ -585,20 +589,40 @@ static ALWAYS_INLINE bool _validate_list(struct _validate_ctx *ctx, match typ: case Bitfield(): ret += "\n" - if all(not bit for bit in typ.bits): + all_the_same = all( + val.ver == [*typ.names.values()][0].ver + for val in typ.names.values() + ) + if all_the_same and all(not bit for bit in typ.bits): ret += f"\treturn validate_{typ.static_size}(ctx));\n" else: ret += f"\t if (validate_{typ.static_size}(ctx))\n" ret += "\t\treturn true;\n" - ret += ( - f"\tconst {c_typename(idprefix, typ)} mask = 0b" - + ("".join("1" if b else "0" for b in reversed(typ.bits))) - + ";\n" - ) + if all_the_same: + ret += ( + f"\tstatic const {c_typename(idprefix, typ)} mask = 0b" + + ("".join("1" if b else "0" for b in reversed(typ.bits))) + + ";\n" + ) + else: + ret += f"\tstatic const {c_typename(idprefix, typ)} masks[{c_verenum(idprefix, 'NUM')}] = {{\n" + for ver in sorted(versions): + ret += ( + f"\t\t[{c_verenum(idprefix, ver)}] = 0b" + + ( + "".join( + "1" if (b and ver in typ.names[b].ver) else "0" + for b in reversed(typ.bits) + ) + ) + + ",\n" + ) + ret += "\t};\n" + ret += f"\t{c_typename(idprefix, typ)} mask = masks[ctx->ctx->version];\n" ret += f"\t{c_typename(idprefix, typ)} val = decode_u{typ.static_size*8}le(&ctx->net_bytes[ctx->net_offset-{typ.static_size}]);\n" ret += f"\tif (val & ~mask)\n" - ret += f'\t\treturn lib9p_error(ctx->ctx, LINUX_EBADMSG, "unknown bits in {typ.name} bitfield: %#0{typ.static_size}"PRIx{typ.static_size*8},\n' - ret += "\t\t val & ~mask);\n" + ret += f'\t\treturn lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "unknown bits in {typ.name} bitfield: %#0{typ.static_size}"PRIx{typ.static_size*8},\n' + ret += "\t\t val & ~mask);\n" ret += "\treturn false;\n" case Struct(): if len(typ.members) == 0: |