summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib9p/include/lib9p/_types.h2
-rw-r--r--lib9p/types.c11
-rwxr-xr-xlib9p/types.gen64
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: