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