diff options
Diffstat (limited to 'lib9p/protogen/c.py')
-rw-r--r-- | lib9p/protogen/c.py | 100 |
1 files changed, 42 insertions, 58 deletions
diff --git a/lib9p/protogen/c.py b/lib9p/protogen/c.py index c487c03..b36e817 100644 --- a/lib9p/protogen/c.py +++ b/lib9p/protogen/c.py @@ -46,28 +46,6 @@ def gen_c(versions: set[str], typs: list[idl.UserType]) -> str: for msg in [msg for msg in typs if isinstance(msg, idl.Message)]: id2typ[msg.msgid] = msg - def msg_table(grp: str, meth: str, tentry: str, rng: tuple[int, int, int]) -> str: - ret = f"const {tentry} {c9util.ident(f'_table_{grp}_{meth}')}[{c9util.ver_enum('NUM')}][{hex(len(range(*rng)))}] = {{\n" - for ver in ["unknown", *sorted(versions)]: - if ver != "unknown": - ret += cutil.ifdef_push(1, c9util.ver_ifdef({ver})) - ret += f"\t[{c9util.ver_enum(ver)}] = {{\n" - for n in range(*rng): - xmsg: idl.Message | None = id2typ.get(n, None) - if xmsg: - if ver == "unknown": # SPECIAL (initialization) - if xmsg.typname not in ["Tversion", "Rversion", "Rerror"]: - xmsg = None - else: - if ver not in xmsg.in_versions: - xmsg = None - if xmsg: - ret += f"\t\t_MSG_{meth.upper()}({xmsg.typname}),\n" - ret += "\t},\n" - ret += cutil.ifdef_pop(0) - ret += "};\n" - return ret - for v in sorted(versions): ret += f"#if CONFIG_9P_ENABLE_{v.replace('.', '_')}\n" ret += ( @@ -85,23 +63,6 @@ def gen_c(versions: set[str], typs: list[idl.UserType]) -> str: ret += " */\n" ret += "#define is_ver(ctx, ver) _is_ver_##ver((ctx)->version)\n" - # strings ################################################################## - ret += f""" -/* strings ********************************************************************/ - -const char *const {c9util.ident('_table_ver_name')}[{c9util.ver_enum('NUM')}] = {{ -""" - for ver in ["unknown", *sorted(versions)]: - if ver in versions: - ret += cutil.ifdef_push(1, c9util.ver_ifdef({ver})) - ret += f'\t[{c9util.ver_enum(ver)}] = "{ver}",\n' - ret += cutil.ifdef_pop(0) - ret += "};\n" - - ret += "\n" - ret += f"#define _MSG_NAME(typ) [{c9util.Ident('TYP_')}##typ] = #typ\n" - ret += msg_table("msg", "name", "char *const", (0, 0x100, 1)) - # bitmasks ################################################################# ret += """ /* bitmasks *******************************************************************/ @@ -141,21 +102,52 @@ const char *const {c9util.ident('_table_ver_name')}[{c9util.ver_enum('NUM')}] = # marshal_* ################################################################ ret += c_marshal.gen_c_marshal(versions, typs) - # function tables ########################################################## + # tables.h ################################################################# ret += """ -/* function tables ************************************************************/ +/* tables.h *******************************************************************/ """ ret += "\n" - ret += f"const uint32_t {c9util.ident('_table_msg_min_size')}[{c9util.ver_enum('NUM')}] = {{\n" + ret += f"const struct {c9util.ident('_ver_tentry')} {c9util.ident('_table_ver')}[{c9util.ver_enum('NUM')}] = {{\n" rerror = next(typ for typ in typs if typ.typname == "Rerror") - ret += f"\t[{c9util.ver_enum('unknown')}] = {rerror.min_size('9P2000')},\n" # SPECIAL (initialization) - for ver in sorted(versions): - ret += cutil.ifdef_push(1, c9util.ver_ifdef({ver})) - ret += f"\t[{c9util.ver_enum(ver)}] = {rerror.min_size(ver)},\n" + for ver in ["unknown", *sorted(versions)]: + if ver == "unknown": + min_msg_size = rerror.min_size("9P2000") # SPECIAL (initialization) + else: + ret += cutil.ifdef_push(1, c9util.ver_ifdef({ver})) + min_msg_size = rerror.min_size(ver) + ret += f'\t[{c9util.ver_enum(ver)}] = {{.name="{ver}", .min_msg_size={min_msg_size}}},\n' ret += cutil.ifdef_pop(0) ret += "};\n" + def msg_table( + cstruct: str, cname: str, each: str, _range: tuple[int, int, int] + ) -> str: + ret = f"const struct {c9util.ident(cstruct)} {c9util.ident(cname)}[{c9util.ver_enum('NUM')}][{hex(len(range(*_range)))}] = {{\n" + for ver in ["unknown", *sorted(versions)]: + if ver != "unknown": + ret += cutil.ifdef_push(1, c9util.ver_ifdef({ver})) + ret += f"\t[{c9util.ver_enum(ver)}] = {{\n" + for n in range(*_range): + xmsg: idl.Message | None = id2typ.get(n, None) + if xmsg: + if ver == "unknown": # SPECIAL (initialization) + if xmsg.typname not in ["Tversion", "Rversion", "Rerror"]: + xmsg = None + else: + if ver not in xmsg.in_versions: + xmsg = None + if xmsg: + ret += f"\t\t{each}({xmsg.typname}),\n" + ret += "\t},\n" + ret += cutil.ifdef_pop(0) + ret += "};\n" + return ret + + ret += "\n" + ret += f"#define _MSG(typ) [{c9util.Ident('TYP_')}##typ] = {{.name=#typ}}\n" + ret += msg_table("_msg_tentry", "_table_msg", "_MSG", (0, 0x100, 1)) + ret += "\n" ret += cutil.macro( f"#define _MSG_RECV(typ) [{c9util.Ident('TYP_')}##typ/2] = {{\n" @@ -169,21 +161,13 @@ const char *const {c9util.ident('_table_ver_name')}[{c9util.ver_enum('NUM')}] = f"\t}}\n" ) ret += "\n" - ret += msg_table( - "Tmsg", "recv", f"struct {c9util.ident('_recv_tentry')}", (0, 0x100, 2) - ) + ret += msg_table("_recv_tentry", "_table_Tmsg_recv", "_MSG_RECV", (0, 0x100, 2)) ret += "\n" - ret += msg_table( - "Rmsg", "recv", f"struct {c9util.ident('_recv_tentry')}", (1, 0x100, 2) - ) + ret += msg_table("_recv_tentry", "_table_Rmsg_recv", "_MSG_RECV", (1, 0x100, 2)) ret += "\n" - ret += msg_table( - "Tmsg", "send", f"struct {c9util.ident('_send_tentry')}", (0, 0x100, 2) - ) + ret += msg_table("_send_tentry", "_table_Tmsg_send", "_MSG_SEND", (0, 0x100, 2)) ret += "\n" - ret += msg_table( - "Rmsg", "send", f"struct {c9util.ident('_send_tentry')}", (1, 0x100, 2) - ) + ret += msg_table("_send_tentry", "_table_Rmsg_send", "_MSG_SEND", (1, 0x100, 2)) ret += f""" LM_FLATTEN ssize_t {c9util.ident('_stat_validate')}(struct lib9p_ctx *ctx, uint32_t net_size, uint8_t *net_bytes, uint32_t *ret_net_size) {{ |