summaryrefslogtreecommitdiff
path: root/lib9p/types.gen
diff options
context:
space:
mode:
Diffstat (limited to 'lib9p/types.gen')
-rwxr-xr-xlib9p/types.gen60
1 files changed, 31 insertions, 29 deletions
diff --git a/lib9p/types.gen b/lib9p/types.gen
index 48f8107..44eebbe 100755
--- a/lib9p/types.gen
+++ b/lib9p/types.gen
@@ -205,14 +205,22 @@ def c_typename(idprefix: str, typ: Atom | Struct) -> str:
raise ValueError(f"not a type: {typ.__class__.__name__}")
+def c_verenum(idprefix: str, ver: str) -> str:
+ return f"{idprefix.upper()}VER_{ver.replace('.', '_')}"
+
+
def c_vercomment(versions: set[str]) -> str | None:
if "9P2000" in versions:
return None
return "/* " + (", ".join(sorted(versions))) + " */"
-def c_ver(idprefix: str, ver: str) -> str:
- return f"{idprefix.upper()}VER_{ver.replace('.', '_')}"
+def c_vercond(idprefix: str, versions: set[str]) -> str:
+ if len(versions) == 1:
+ return f"(ctx->ctx->version=={c_verenum(idprefix, next(v for v in versions))})"
+ return (
+ "( " + (" || ".join(c_vercond(idprefix, {v}) for v in sorted(versions))) + " )"
+ )
def gen_h(idprefix: str, versions: set[str], structs: list[Struct]) -> str:
@@ -233,7 +241,7 @@ enum {idprefix}version {{
"""
verwidth = max(len(v) for v in versions)
for ver in sorted(versions):
- ret += f"\t{c_ver(idprefix, ver)},"
+ ret += f"\t{c_verenum(idprefix, ver)},"
ret += (" " * (verwidth - len(ver))) + ' /* "' + ver + '" */\n'
ret += f"\t{idprefix.upper()}VER_NUM,\n"
ret += "};\n"
@@ -396,7 +404,9 @@ static inline bool _checksize_list(struct _checksize_ctx *ctx,
ret += "\tif (checksize_4(ctx))\n"
ret += "\t\treturn true;\n"
ret += "\tuint32_t len = decode_u32le(&ctx->net_bytes[base_offset]);\n"
- ret += "\treturn _checksize_net(ctx, len) || _checksize_host(ctx, len);\n"
+ ret += (
+ "\treturn _checksize_net(ctx, len) || _checksize_host(ctx, len);\n"
+ )
ret += "}\n"
case "s":
# Add an extra nul-byte on the host, and validate
@@ -414,22 +424,12 @@ static inline bool _checksize_list(struct _checksize_ctx *ctx,
ret += "}\n"
case _:
struct_versions = struct.members[0].ver
-
prefix = prefix0
prev_size: int | None = None
for member in struct.members:
ret += f"\n{prefix}"
if member.ver != struct_versions:
- ret += (
- "( ( "
- + (
- " || ".join(
- f"(ctx->ctx->version=={c_ver(idprefix, v)})"
- for v in sorted(member.ver)
- )
- )
- + " ) && "
- )
+ ret += "( " + c_vercond(idprefix, member.ver) + " && "
if member.cnt is not None:
assert prev_size
ret += f"_checksize_list(ctx, decode_u{prev_size*8}le(&ctx->net_bytes[ctx->net_offset-{prev_size}]), checksize_{member.typ.name}, sizeof({c_typename(idprefix, member.typ)}))"
@@ -478,16 +478,7 @@ static inline void unmarshal_8(struct _unmarshal_ctx *ctx, uint64_t *out) {
ret += "\t"
prefix = "\t"
if member.ver != struct_versions:
- ret += (
- "if ( "
- + (
- " || ".join(
- f"(ctx->ctx->version=={c_ver(idprefix, v)})"
- for v in sorted(member.ver)
- )
- )
- + " ) "
- )
+ ret += "if ( " + c_vercond(idprefix, member.ver) + " ) "
prefix = "\t\t"
if member.cnt:
if member.ver != struct_versions:
@@ -507,7 +498,7 @@ static inline void unmarshal_8(struct _unmarshal_ctx *ctx, uint64_t *out) {
/* marshal_* ******************************************************************/
static inline bool _marshal_too_large(struct _marshal_ctx *ctx) {
- lib9p_errorf(ctx->ctx, LINUX_EMSGSIZE, "%s too large to marshal into %s limit (limit=%"PRIu32")",
+ lib9p_errorf(ctx->ctx, LINUX_ERANGE, "%s too large to marshal into %s limit (limit=%"PRIu32")",
(ctx->net_bytes[4] % 2 == 0) ? "T-message" : "R-message",
ctx->ctx->version ? "negotiated" : ((ctx->net_bytes[4] % 2 == 0) ? "client" : "server"),
ctx->ctx->max_msg_size);
@@ -556,21 +547,32 @@ static inline bool marshal_8(struct _marshal_ctx *ctx, uint64_t *val) {
ret += "}\n"
continue
+ if struct.name == "Rerror":
+ ret += "\n\t/* Truncate the error-string if necessary to avoid returning ERANGE. */"
+ ret += "\n\tif (((uint32_t)val->ename.len) + ctx->ctx->Rerror_overhead > ctx->ctx->max_msg_size)"
+ ret += "\n\t\tval->ename.len = ctx->ctx->max_msg_size - ctx->ctx->Rerror_overhead;"
+
prefix0 = "\treturn "
prefix1 = "\t || "
prefix2 = "\t "
+ struct_versions = struct.members[0].ver
prefix = prefix0
for member in struct.members:
+ ret += f"\n{prefix}"
+ if member.ver != struct_versions:
+ ret += "( " + c_vercond(idprefix, member.ver) + " && "
if member.cnt:
- ret += f"\n{prefix }({{"
+ ret += "({"
ret += f"\n{prefix2}\tbool err = false;"
ret += f"\n{prefix2}\tfor (typeof(val->{member.cnt}) i = 0; i < val->{member.cnt} && !err; i++)"
ret += f"\n{prefix2}\t\terr = marshal_{member.typ.name}(ctx, &val->{member.name}[i]);"
ret += f"\n{prefix2}\terr;"
ret += f"\n{prefix2}}})"
else:
- ret += f"\n{prefix}marshal_{member.typ.name}(ctx, &val->{member.name})"
+ ret += f"marshal_{member.typ.name}(ctx, &val->{member.name})"
+ if member.ver != struct_versions:
+ ret += " )"
prefix = prefix1
ret += ";\n}\n"
@@ -595,7 +597,7 @@ struct _vtable_version _{idprefix}vtables[LIB9P_VER_NUM] = {{
}}}},
"""
for ver in sorted(versions):
- ret += f"\t[{c_ver(idprefix, ver)}] = {{ .msgs = {{\n"
+ ret += f"\t[{c_verenum(idprefix, ver)}] = {{ .msgs = {{\n"
for msg in structs:
if ver not in msg.msgver:
continue