diff options
author | Luke T. Shumaker <lukeshu@lukeshu.com> | 2024-10-02 14:51:13 -0600 |
---|---|---|
committer | Luke T. Shumaker <lukeshu@lukeshu.com> | 2024-10-02 14:51:13 -0600 |
commit | 79480e66113b7654d1ed89b940222b6eee84c8b0 (patch) | |
tree | 65e9b76969aebd88fb45e974e9569d27630ab027 | |
parent | 79e6cb0f6f7627284a7614b70a25e976b426d82e (diff) |
bitfield versions
-rw-r--r-- | lib9p/include/lib9p/_types.h | 2 | ||||
-rw-r--r-- | lib9p/types.c | 11 | ||||
-rwxr-xr-x | lib9p/types.gen | 64 |
3 files changed, 53 insertions, 24 deletions
diff --git a/lib9p/include/lib9p/_types.h b/lib9p/include/lib9p/_types.h index 8a47102..8f9595e 100644 --- a/lib9p/include/lib9p/_types.h +++ b/lib9p/include/lib9p/_types.h @@ -26,7 +26,7 @@ typedef uint8_t lib9p_qt_t; #define _LIB9P_QT_PLAN9_MOUNT ((lib9p_qt_t)(1<<4)) #define LIB9P_QT_AUTH ((lib9p_qt_t)(1<<3)) #define LIB9P_QT_TMP ((lib9p_qt_t)(1<<2)) -#define LIB9P_QT_SYMLINK ((lib9p_qt_t)(1<<1)) +#define LIB9P_QT_SYMLINK ((lib9p_qt_t)(1<<1)) /* 9P2000.u */ #define _LIB9P_QT_UNUSED_0 ((lib9p_qt_t)(1<<0)) #define LIB9P_QT_FILE ((lib9p_qt_t)(0)) diff --git a/lib9p/types.c b/lib9p/types.c index 3505a4a..18dcbfe 100644 --- a/lib9p/types.c +++ b/lib9p/types.c @@ -346,11 +346,16 @@ static ALWAYS_INLINE bool validate_s(struct _validate_ctx *ctx) { static ALWAYS_INLINE bool validate_qt(struct _validate_ctx *ctx) { if (validate_1(ctx)) return true; - const lib9p_qt_t mask = 0b11111110; + static const lib9p_qt_t masks[LIB9P_VER_NUM] = { + [LIB9P_VER_9P2000] = 0b11111100, + [LIB9P_VER_9P2000_e] = 0b11111100, + [LIB9P_VER_9P2000_u] = 0b11111110, + }; + lib9p_qt_t mask = masks[ctx->ctx->version]; lib9p_qt_t val = decode_u8le(&ctx->net_bytes[ctx->net_offset-1]); if (val & ~mask) - return lib9p_error(ctx->ctx, LINUX_EBADMSG, "unknown bits in qt bitfield: %#01"PRIx8, - val & ~mask); + return lib9p_errorf(ctx->ctx, LINUX_EBADMSG, "unknown bits in qt bitfield: %#01"PRIx8, + val & ~mask); return false; } 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: |