summaryrefslogtreecommitdiff
path: root/lib9p/protogen/c.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib9p/protogen/c.py')
-rw-r--r--lib9p/protogen/c.py125
1 files changed, 63 insertions, 62 deletions
diff --git a/lib9p/protogen/c.py b/lib9p/protogen/c.py
index 5e67939..a6824ce 100644
--- a/lib9p/protogen/c.py
+++ b/lib9p/protogen/c.py
@@ -7,7 +7,7 @@ import sys
import idl
-from . import c9util, c_marshal, c_unmarshal, c_validate, cutil
+from . import c9util, c_format, c_marshal, c_unmarshal, c_validate, cutil
# This strives to be "general-purpose" in that it just acts on the
# *.9p inputs; but (unfortunately?) there are a few special-cases in
@@ -29,11 +29,21 @@ def gen_c(versions: set[str], typs: list[idl.UserType]) -> str:
#include <string.h> /* for memset() */
#include <libmisc/assert.h>
+#include <libmisc/endian.h>
#include <lib9p/9p.h>
-#include "internal.h"
+#include "tables.h"
+#include "utf8.h"
"""
+ # libobj vtables ###########################################################
+ ret += """
+/* libobj vtables *************************************************************/
+"""
+ for typ in typs:
+ ret += cutil.ifdef_push(1, c9util.ver_ifdef(typ.in_versions))
+ ret += f"LO_IMPLEMENTATION_C(fmt_formatter, {c9util.typename(typ)}, {c9util.basename(typ)}, static);\n"
+ ret += cutil.ifdef_pop(0)
# utilities ################################################################
ret += """
@@ -44,28 +54,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 += (
@@ -83,23 +71,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 *******************************************************************/
@@ -118,7 +89,7 @@ const char *const {c9util.ident('_table_ver_name')}[{c9util.ver_enum('NUM')}] =
+ "".join(
(
"1"
- if bit.cat in (idl.BitCat.USED, idl.BitCat.SUBFIELD)
+ if (bit.cat == "USED" or isinstance(bit.cat, idl.BitNum))
and ver in bit.in_versions
else "0"
)
@@ -139,25 +110,63 @@ const char *const {c9util.ident('_table_ver_name')}[{c9util.ver_enum('NUM')}] =
# marshal_* ################################################################
ret += c_marshal.gen_c_marshal(versions, typs)
- # function tables ##########################################################
+ # *_format #################################################################
+ ret += c_format.gen_c_format(versions, typs)
+
+ # 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 += cutil.macro(
+ f"#define _MSG(typ) [{c9util.Ident('TYP_')}##typ] = {{\n"
+ f"\t\t.name = #typ,\n"
+ f"\t\t.box_as_fmt_formatter = (_box_as_fmt_formatter_fn_t)lo_box_{c9util.ident('msg_')}##typ##_as_fmt_formatter,\n"
+ f"\t}}\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"
- f"\t\t.basesize = sizeof(struct {c9util.ident('msg_')}##typ),\n"
f"\t\t.validate = validate_##typ,\n"
f"\t\t.unmarshal = (_unmarshal_fn_t)unmarshal_##typ,\n"
f"\t}}\n"
@@ -168,21 +177,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) {{