summaryrefslogtreecommitdiff
path: root/lib9p/protogen/h.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib9p/protogen/h.py')
-rw-r--r--lib9p/protogen/h.py270
1 files changed, 179 insertions, 91 deletions
diff --git a/lib9p/protogen/h.py b/lib9p/protogen/h.py
index 7785ca1..3b33419 100644
--- a/lib9p/protogen/h.py
+++ b/lib9p/protogen/h.py
@@ -165,6 +165,7 @@ def gen_h(versions: set[str], typs: list[idl.UserType]) -> str:
#include <stdint.h> /* for uint{{n}}_t types */
+#include <libfmt/fmt.h> /* for fmt_formatter */
#include <libhw/generic/net.h> /* for struct iovec */
"""
@@ -206,6 +207,7 @@ enum {c9util.ident('version')} {{
ret += cutil.ifdef_pop(0)
ret += f"\t{c9util.ver_enum('NUM')},\n"
ret += "};\n"
+ ret += f"LO_IMPLEMENTATION_H(fmt_formatter, enum {c9util.ident('version')}, {c9util.ident('version')});\n"
ret += """
/* enum msg_type **************************************************************/
@@ -221,6 +223,7 @@ enum {c9util.ident('version')} {{
ret += f"\t{c9util.Ident(f'TYP_{msg.typname:<{namewidth}}')} = {msg.msgid},\n"
ret += cutil.ifdef_pop(0)
ret += "};\n"
+ ret += f"LO_IMPLEMENTATION_H(fmt_formatter, enum {c9util.ident('msg_type')}, {c9util.ident('msg_type')});\n"
ret += """
/* payload types **************************************************************/
@@ -268,99 +271,11 @@ enum {c9util.ident('version')} {{
match typ:
case idl.Number():
- ret += f"typedef {c9util.typename(typ.prim)} {c9util.typename(typ)};\n"
- prefix = f"{c9util.IDENT(typ.typname)}_"
- namewidth = max(len(name) for name in typ.vals)
- for name, val in typ.vals.items():
- ret += f"#define {prefix}{name:<{namewidth}} (({c9util.typename(typ)})UINT{typ.static_size*8}_C({val}))\n"
+ ret += gen_number(typ)
case idl.Bitfield():
- ret += f"typedef {c9util.typename(typ.prim)} {c9util.typename(typ)};\n"
-
- def bitname(val: idl.Bit | idl.BitAlias) -> str:
- s = val.bitname
- match val:
- case idl.Bit(cat=idl.BitCat.RESERVED):
- s = "_RESERVED_" + s
- case idl.Bit(cat=idl.BitCat.SUBFIELD):
- assert isinstance(typ, idl.Bitfield)
- n = sum(
- 1
- for b in typ.bits[: val.num]
- if b.cat == idl.BitCat.SUBFIELD
- and b.bitname == val.bitname
- )
- s = f"_{s}_{n}"
- case idl.Bit(cat=idl.BitCat.UNUSED):
- return ""
- return c9util.Ident(c9util.add_prefix(typ.typname.upper() + "_", s))
-
- namewidth = max(
- len(bitname(val)) for val in [*typ.bits, *typ.names.values()]
- )
-
- ret += "\n"
- for bit in reversed(typ.bits):
- vers = bit.in_versions
- if bit.cat == idl.BitCat.UNUSED:
- vers = typ.in_versions
- ret += cutil.ifdef_push(2, c9util.ver_ifdef(vers))
-
- # It is important all of the `beg` strings have
- # the same length.
- end = ""
- match bit.cat:
- case (
- idl.BitCat.USED | idl.BitCat.RESERVED | idl.BitCat.SUBFIELD
- ):
- if cutil.ifdef_leaf_is_noop():
- beg = "#define "
- else:
- beg = "# define"
- case idl.BitCat.UNUSED:
- beg = "/* unused"
- end = " */"
-
- c_name = bitname(bit)
- c_val = f"1<<{bit.num}"
- ret += f"{beg} {c_name:<{namewidth}} (({c9util.typename(typ)})({c_val})){end}\n"
- if aliases := [
- alias
- for alias in typ.names.values()
- if isinstance(alias, idl.BitAlias)
- ]:
- ret += "\n"
-
- for alias in aliases:
- ret += cutil.ifdef_push(2, c9util.ver_ifdef(alias.in_versions))
-
- end = ""
- if cutil.ifdef_leaf_is_noop():
- beg = "#define "
- else:
- beg = "# define"
-
- c_name = bitname(alias)
- c_val = alias.val
- ret += f"{beg} {c_name:<{namewidth}} (({c9util.typename(typ)})({c_val})){end}\n"
- ret += cutil.ifdef_pop(1)
- del bitname
+ ret += gen_bitfield(typ)
case idl.Struct(): # and idl.Message():
- ret += c9util.typename(typ) + " {"
- if not typ.members:
- ret += "};\n"
- continue
- ret += "\n"
-
- typewidth = max(len(c9util.typename(m.typ, m)) for m in typ.members)
-
- for member in typ.members:
- if member.val:
- continue
- ret += cutil.ifdef_push(2, c9util.ver_ifdef(member.in_versions))
- ret += f"\t{c9util.typename(member.typ, member):<{typewidth}} {'*' if member.cnt else ' '}{member.membname};\n"
- ret += cutil.ifdef_pop(1)
- ret += "};\n"
- del typ
+ ret += gen_struct(typ)
ret += cutil.ifdef_pop(0)
ret += """
@@ -445,3 +360,176 @@ enum {c9util.ident('version')} {{
ret += "};\n"
return ret
+
+
+def gen_number(typ: idl.Number) -> str:
+ ret = f"typedef {c9util.typename(typ.prim)} {c9util.typename(typ)};\n"
+ ret += f"LO_IMPLEMENTATION_H(fmt_formatter, {c9util.typename(typ)}, {c9util.basename(typ)});\n"
+
+ def lookup_sym(sym: str) -> str:
+ assert False
+
+ def cname(base: str) -> str:
+ prefix = f"{typ.typname}_".upper()
+ return c9util.Ident(c9util.add_prefix(prefix, base))
+
+ namewidth = max(len(cname(name)) for name in typ.vals)
+ for name, val in typ.vals.items():
+ c_name = cname(name)
+ c_val = c9util.idl_expr(val, lookup_sym)
+ ret += f"#define {c_name:<{namewidth}} (({c9util.typename(typ)})({c_val}))\n"
+ return ret
+
+
+def gen_bitfield(typ: idl.Bitfield) -> str:
+ ret = f"typedef {c9util.typename(typ.prim)} {c9util.typename(typ)};\n"
+ ret += f"LO_IMPLEMENTATION_H(fmt_formatter, {c9util.typename(typ)}, {c9util.basename(typ)});\n"
+
+ def lookup_sym(sym: str) -> str:
+ assert False
+
+ # There are 4 parts here: bits, aliases, masks, and numbers.
+
+ # 1. bits
+
+ def bitname(bit: idl.Bit) -> str:
+ prefix = f"{typ.typname}_".upper()
+ base = bit.bitname
+ match bit:
+ case idl.Bit(cat="RESERVED"):
+ base = "_RESERVED_" + base
+ case idl.Bit(cat=idl.BitNum()):
+ base += "_*"
+ case idl.Bit(cat="UNUSED"):
+ base = f"_UNUSED_{bit.num}"
+ return c9util.Ident(c9util.add_prefix(prefix, base))
+
+ namewidth = max(len(bitname(bit)) for bit in typ.bits)
+
+ ret += "/* bits */\n"
+ for bit in reversed(typ.bits):
+ vers = bit.in_versions
+ if bit.cat == "UNUSED":
+ vers = typ.in_versions
+ ret += cutil.ifdef_push(2, c9util.ver_ifdef(vers))
+
+ # It is important all of the `beg` strings have
+ # the same length.
+ end = ""
+ match bit.cat:
+ case "USED" | "RESERVED" | "UNUSED":
+ if cutil.ifdef_leaf_is_noop():
+ beg = "#define "
+ else:
+ beg = "# define"
+ case idl.BitNum():
+ beg = "/* number"
+ end = " */"
+
+ c_name = bitname(bit)
+ c_val = f"UINT{typ.static_size*8}_C(1)<<{bit.num}"
+ ret += (
+ f"{beg} {c_name:<{namewidth}} (({c9util.typename(typ)})({c_val})){end}\n"
+ )
+ ret += cutil.ifdef_pop(1)
+
+ # 2. aliases
+ if typ.aliases:
+
+ def aliasname(alias: idl.BitAlias) -> str:
+ prefix = f"{typ.typname}_".upper()
+ base = alias.bitname
+ return c9util.Ident(c9util.add_prefix(prefix, base))
+
+ ret += "/* aliases */\n"
+ for alias in typ.aliases.values():
+ ret += cutil.ifdef_push(2, c9util.ver_ifdef(alias.in_versions))
+
+ end = ""
+ if cutil.ifdef_leaf_is_noop():
+ beg = "#define "
+ else:
+ beg = "# define"
+
+ c_name = aliasname(alias)
+ c_val = c9util.idl_expr(alias.val, lookup_sym)
+ ret += f"{beg} {c_name:<{namewidth}} (({c9util.typename(typ)})({c_val})){end}\n"
+
+ ret += cutil.ifdef_pop(1)
+
+ # 3. masks
+ if typ.masks:
+
+ def maskname(mask: idl.BitAlias) -> str:
+ prefix = f"{typ.typname}_".upper()
+ base = mask.bitname
+ return c9util.Ident(c9util.add_prefix(prefix, base) + "_MASK")
+
+ ret += "/* masks */\n"
+ for mask in typ.masks.values():
+ ret += cutil.ifdef_push(2, c9util.ver_ifdef(mask.in_versions))
+
+ end = ""
+ if cutil.ifdef_leaf_is_noop():
+ beg = "#define "
+ else:
+ beg = "# define"
+
+ c_name = maskname(mask)
+ c_val = c9util.idl_expr(mask.val, lookup_sym, bitwidth=typ.static_size * 8)
+ ret += f"{beg} {c_name:<{namewidth}} (({c9util.typename(typ)})({c_val})){end}\n"
+
+ ret += cutil.ifdef_pop(1)
+
+ # 4. numbers
+ def numname(num: idl.BitNum, base: str) -> str:
+ prefix = f"{typ.typname}_{num.numname}_".upper()
+ return c9util.Ident(c9util.add_prefix(prefix, base))
+
+ for num in typ.nums.values():
+ namewidth = max(
+ len(numname(num, base))
+ for base in [
+ *[alias.bitname for alias in num.vals.values()],
+ "MASK",
+ ]
+ )
+ ret += f"/* number: {num.numname} */\n"
+ for alias in num.vals.values():
+ ret += cutil.ifdef_push(2, c9util.ver_ifdef(alias.in_versions))
+
+ end = ""
+ if cutil.ifdef_leaf_is_noop():
+ beg = "#define "
+ else:
+ beg = "# define"
+
+ c_name = numname(num, alias.bitname)
+ c_val = c9util.idl_expr(alias.val, lookup_sym)
+ ret += f"{beg} {c_name:<{namewidth}} (({c9util.typename(typ)})({c_val})){end}\n"
+ ret += cutil.ifdef_pop(1)
+ c_name = numname(num, "MASK")
+ c_val = f"{num.mask:#0{typ.static_size*8}b}"
+ ret += (
+ f"{beg} {c_name:<{namewidth}} (({c9util.typename(typ)})({c_val})){end}\n"
+ )
+
+ return ret
+
+
+def gen_struct(typ: idl.Struct) -> str: # and idl.Message
+ ret = c9util.typename(typ) + " {"
+ if typ.members:
+ ret += "\n"
+
+ typewidth = max(len(c9util.typename(m.typ, m)) for m in typ.members)
+
+ for member in typ.members:
+ if member.val:
+ continue
+ ret += cutil.ifdef_push(2, c9util.ver_ifdef(member.in_versions))
+ ret += f"\t{c9util.typename(member.typ, member):<{typewidth}} {'*' if member.cnt else ' '}{member.membname};\n"
+ ret += cutil.ifdef_pop(1)
+ ret += "};\n"
+ ret += f"LO_IMPLEMENTATION_H(fmt_formatter, {c9util.typename(typ)}, {c9util.basename(typ)});\n"
+ return ret