diff options
author | Luke T. Shumaker <lukeshu@lukeshu.com> | 2024-09-20 16:08:12 -0600 |
---|---|---|
committer | Luke T. Shumaker <lukeshu@lukeshu.com> | 2024-09-20 16:08:12 -0600 |
commit | b13be233849bfec6277638f6bf7261a4b709cedf (patch) | |
tree | 7dd6023e74ce0152dcb376e223a16158ff92c6c1 | |
parent | e236836a97cea92ec463ce60cd45ca50856ce56d (diff) |
finish(?) net9p_defs.gen
-rwxr-xr-x | net9p_defs.gen | 239 |
1 files changed, 184 insertions, 55 deletions
diff --git a/net9p_defs.gen b/net9p_defs.gen index dcfb33b..53235df 100755 --- a/net9p_defs.gen +++ b/net9p_defs.gen @@ -175,21 +175,25 @@ def gen_h(structs: list[Struct], msgs: list[Message]) -> str: ret += "#ifndef _NET9P_DEFS_H_\n" ret += "#define _NET9P_DEFS_H_\n" ret += "\n" + ret += "#define V9FS_EWRONGSIZE 7\n" + ret += "#define V9FS_EBADTYPE 4\n" + ret += "\n" for struct in structs: ret += c_typename(struct) + " {\n" typewidth = max(len(c_typename(member.typ)) for member in struct.members) for member in struct.members: ret += f"\t{c_typename(member.typ).ljust(typewidth)} {member.name};\n" ret += "};\n" - ret += "\n" + ret += "\n" ret += "enum v9fs_msg_type {\n" namewidth = max(len(msg.name) for msg in msgs) for msg in msgs: ret += f"\tV9FS_TYP_{msg.name.ljust(namewidth)} = {msg.id},\n" ret += "};\n" + ret += "\n" for msg in msgs: if not msg.members: ret += c_typename(msg) + " {};\n" @@ -199,8 +203,34 @@ def gen_h(structs: list[Struct], msgs: list[Message]) -> str: for member in msg.members: ret += f"\t{c_typename(member.typ).ljust(typewidth)} {member.name};\n" ret += "};\n" - ret += "\n" + ret += """ +/** + * @param net_bytes : the complete request, starting with the "size[4]" + * @param out_tag : the message-ID tag + * @param out_body : a pointer that get set to the parsed body, whose + * type is known by the return value, will need to + * be free()d + * @return -V9FS_E{error} on errors, V9FS_TYP_{type} on success + */ +int v9fs_unmarshal_msg(uint8_t *net_bytes, uint16_t *out_tag, void **out_body); +""" + + ret += """ +/** + * @param uint16_t in_msgid : the message-ID tag + * @param struct v9fs_msg_{type} in_msg : the message to encode + * @param uint8_t *out_buf : the buffer to encode to + * @return uint32_t : the encoded length + */ +#define v9fs_marshal_msg(in_msgid, in_msg, out_buf) _Generic((in_msg)""" + for msg in msgs: + ret += f", \\\n\t\t{c_typename(msg)}: _v9fs_marshal_{shortname(msg)}(in_msgid, in_msg, out_buf)" + ret += "\\\n\t)(in_msg)\n" + for msg in msgs: + ret += f"uint32_t _v9fs_marshal_{shortname(msg)}(uint16_t in_msgid, {c_typename(msg)} in_msg, uint8_t *out_buf);\n" + + ret += "\n" ret += "#endif /* _NET9P_DEFS_H_ */\n" return ret @@ -209,7 +239,8 @@ def gen_c(structs: list[Struct], msgs: list[Message]) -> str: ret = """ /* Generated by ./net9p_defs.gen. DO NOT EDIT! */ -#include <stdint.h> /* for size_t, uint{n}_t */ +#include <stdbool.h> +#include <stdint.h> #include <stdlib.h> /* for malloc() */ #include "net9p_defs.h" @@ -221,58 +252,64 @@ def gen_c(structs: list[Struct], msgs: list[Message]) -> str: #define UNUSED __attribute__ ((unused)) -static inline uint16_t decode_u16le(uint8_t *bytes) { - return (((uint16_t)(bytes[0])) << 0) - | (((uint16_t)(bytes[1])) << 8) - ; +static inline uint8_t decode_u8le(uint8_t *in) { + return in[0]; +} +static inline uint16_t decode_u16le(uint8_t *in) { + return (((uint16_t)(in[0])) << 0) + | (((uint16_t)(in[1])) << 8) + ; } -static inline uint32_t decode_u32le(uint8_t *bytes) { - return (((uint16_t)(bytes[0])) << 0) - | (((uint16_t)(bytes[1])) << 8) - | (((uint16_t)(bytes[2])) << 16) - | (((uint16_t)(bytes[3])) << 24) - ; +static inline uint32_t decode_u32le(uint8_t *in) { + return (((uint32_t)(in[0])) << 0) + | (((uint32_t)(in[1])) << 8) + | (((uint32_t)(in[2])) << 16) + | (((uint32_t)(in[3])) << 24) + ; } -static inline uint64_t decode_u64le(uint8_t *bytes) { - return (((uint16_t)(bytes[0])) << 0) - | (((uint16_t)(bytes[1])) << 8) - | (((uint16_t)(bytes[2])) << 16) - | (((uint16_t)(bytes[3])) << 24) - | (((uint16_t)(bytes[4])) << 32) - | (((uint16_t)(bytes[5])) << 40) - | (((uint16_t)(bytes[6])) << 48) - | (((uint16_t)(bytes[7])) << 56) - ; +static inline uint64_t decode_u64le(uint8_t *in) { + return (((uint64_t)(in[0])) << 0) + | (((uint64_t)(in[1])) << 8) + | (((uint64_t)(in[2])) << 16) + | (((uint64_t)(in[3])) << 24) + | (((uint64_t)(in[4])) << 32) + | (((uint64_t)(in[5])) << 40) + | (((uint64_t)(in[6])) << 48) + | (((uint64_t)(in[7])) << 56) + ; } -static inline void decode_u16le(val uint16_t, uint8_t *bytes) { - bytes[0] = (uint8_t)((val >> 0) & 0xFF); - bytes[1] = (uint8_t)((val >> 8) & 0xFF); +static inline void encode_u8le(uint8_t in, uint8_t *out) { + out[0] = in; } -static inline void decode_u32le(val uint32_t, uint8_t *bytes) { - bytes[0] = (uint8_t)((val >> 0) & 0xFF); - bytes[1] = (uint8_t)((val >> 8) & 0xFF); - bytes[2] = (uint8_t)((val >> 16) & 0xFF); - bytes[3] = (uint8_t)((val >> 24) & 0xFF); +static inline void encode_u16le(uint16_t in, uint8_t *out) { + out[0] = (uint8_t)((in >> 0) & 0xFF); + out[1] = (uint8_t)((in >> 8) & 0xFF); } -static inline void decode_u64le(val uint64_t, uint8_t *bytes) { - bytes[0] = (uint8_t)((val >> 0) & 0xFF); - bytes[1] = (uint8_t)((val >> 8) & 0xFF); - bytes[2] = (uint8_t)((val >> 16) & 0xFF); - bytes[3] = (uint8_t)((val >> 24) & 0xFF); - bytes[4] = (uint8_t)((val >> 32) & 0xFF); - bytes[5] = (uint8_t)((val >> 40) & 0xFF); - bytes[6] = (uint8_t)((val >> 48) & 0xFF); - bytes[7] = (uint8_t)((val >> 56) & 0xFF); +static inline void encode_u32le(uint32_t in, uint8_t *out) { + out[0] = (uint8_t)((in >> 0) & 0xFF); + out[1] = (uint8_t)((in >> 8) & 0xFF); + out[2] = (uint8_t)((in >> 16) & 0xFF); + out[3] = (uint8_t)((in >> 24) & 0xFF); +} +static inline void encode_u64le(uint64_t in, uint8_t *out) { + out[0] = (uint8_t)((in >> 0) & 0xFF); + out[1] = (uint8_t)((in >> 8) & 0xFF); + out[2] = (uint8_t)((in >> 16) & 0xFF); + out[3] = (uint8_t)((in >> 24) & 0xFF); + out[4] = (uint8_t)((in >> 32) & 0xFF); + out[5] = (uint8_t)((in >> 40) & 0xFF); + out[6] = (uint8_t)((in >> 48) & 0xFF); + out[7] = (uint8_t)((in >> 56) & 0xFF); } """ - # checksize ################################################################ + # checksize_* ############################################################## ret += """ -/* checksize ******************************************************************/ +/* checksize_* ****************************************************************/ typedef bool (*_checksize_fn_t)(uint32_t net_len, uint8_t *net_bytes, uint32_t *mut_net_offset, size_t *mut_host_extra); -static inline bool _checksize_list(size_t cnt, checksize_fn_t fn, size_t host_size, +static inline bool _checksize_list(size_t cnt, _checksize_fn_t fn, size_t host_size, uint32_t net_len, uint8_t *net_bytes, uint32_t *mut_net_offset, size_t *mut_host_extra) { for (size_t i = 0; i < cnt; i++) if (__builtin_add_overflow(*mut_host_extra, host_size, mut_host_extra) @@ -295,15 +332,16 @@ static inline bool checksize_8(uint32_t net_len, uint8_t *net_bytes UNUSED, uint """ for struct in structs + msgs: argattr = ' UNUSED' if len(struct.members) == 0 else '' - ret += f"static inline bool checksize_{shortname(struct)}(uint32_t net_len{argattr}, uint8_t *net_bytes{argattr}, uint32_t *mut_net_offset{argattr}, size_t mut_host_extra{argattr}) {{" + ret += f"static inline bool checksize_{shortname(struct)}(uint32_t net_len{argattr}, uint8_t *net_bytes{argattr}, uint32_t *mut_net_offset{argattr}, size_t *mut_host_extra{argattr}) {{\n" if len(struct.members) == 0: + ret += "\treturn false;\n" ret += "}\n" continue prefix0 = "\treturn " prefix1 = "\t || " prefix2 = "\t " prefix = prefix0 - prev_size = 0 + prev_size: int|None = None for member in struct.members: if isinstance(member.typ, List): ret += f"\n{prefix }_checksize_list(decode_u{prev_size*8}le(&net_bytes[(*mut_net_offset)-{prev_size}]), checksize_{shortname(member.typ.typ)}, sizeof({c_typename(member.typ.typ)})," @@ -311,48 +349,139 @@ static inline bool checksize_8(uint32_t net_len, uint8_t *net_bytes UNUSED, uint else: ret += f"\n{prefix}checksize_{shortname(member.typ)}(net_len, net_bytes, mut_net_offset, mut_host_extra)" prefix = prefix1 + prev_size = static_size(member.typ) if struct.name == 's': ret += f"\n{prefix}__builtin_add_overflow(*mut_host_extra, 1, mut_host_extra)" ret += ";\n}\n" - # unmarshal ################################################################ + # unmarshal_* ############################################################## ret += """ -/* unmarshal ******************************************************************/ +/* unmarshal_* ****************************************************************/ /* checksize_XXX() should be called before unmarshal_XXX(). */ -static inline void unmarshal_1(uint32_t net_len, uint8_t *net_bytes UNUSED, uint32_t *mut_net_offset, void *mut_host_extra UNUSED, uint8_t *out) { +static inline void unmarshal_1(uint8_t *net_bytes, uint32_t *mut_net_offset, void **mut_host_extra UNUSED, uint8_t *out) { *out = decode_u8le(&net_bytes[*mut_net_offset]); *mut_net_offset += 1; } -static inline void unmarshal_2(uint32_t net_len, uint8_t *net_bytes UNUSED, uint32_t *mut_net_offset, void *mut_host_extra UNUSED, uint16_t *out) { +static inline void unmarshal_2(uint8_t *net_bytes, uint32_t *mut_net_offset, void **mut_host_extra UNUSED, uint16_t *out) { *out = decode_u16le(&net_bytes[*mut_net_offset]); *mut_net_offset += 2; } -static inline void unmarshal_4(uint32_t net_len, uint8_t *net_bytes UNUSED, uint32_t *mut_net_offset, void *mut_host_extra UNUSED, uint32_t *out) { +static inline void unmarshal_4(uint8_t *net_bytes, uint32_t *mut_net_offset, void **mut_host_extra UNUSED, uint32_t *out) { *out = decode_u32le(&net_bytes[*mut_net_offset]); *mut_net_offset += 4; } -static inline void unmarshal_8(uint32_t net_len, uint8_t *net_bytes UNUSED, uint32_t *mut_net_offset, void *mut_host_extra UNUSED, uint64_t *out) { +static inline void unmarshal_8(uint8_t *net_bytes, uint32_t *mut_net_offset, void **mut_host_extra UNUSED, uint64_t *out) { *out = decode_u64le(&net_bytes[*mut_net_offset]); *mut_net_offset += 8; } """ for struct in structs + msgs: - ret += f"static inline void unmarshal_{shortname(struct)}(uint32_t net_len, uint8_t *net_bytes, uint32_t *mut_net_offset, void *mut_host_extra, {c_typename(struct)} *out) {{" + argattr = ' UNUSED' if len(struct.members) == 0 else '' + ret += f"static inline void unmarshal_{shortname(struct)}(uint8_t *net_bytes{argattr}, uint32_t *mut_net_offset{argattr}, void **mut_host_extra{argattr}, {c_typename(struct)} *out{argattr}) {{" if len(struct.members) == 0: ret += "}\n" continue ret += "\n" for member in struct.members: if isinstance(member.typ, List): - ret += f"\tout->{member.name} = mut_host_extra;\n" + ret += f"\tout->{member.name} = *mut_host_extra;\n" ret += f"\t*mut_host_extra += sizeof(out->{member.name}) * out->{member.typ.cnt};\n" ret += f"\tfor (typeof(out->{member.typ.cnt}) i = 0; i < out->{member.typ.cnt}; i++)\n" - ret += f"\t\tunmarshal_{shortname(member.typ.typ)}(net_len, net_bytes, mut_net_offset, mut_host_extra, &(out->{member.name}[i]));\n" + ret += f"\t\tunmarshal_{shortname(member.typ.typ)}(net_bytes, mut_net_offset, mut_host_extra, &(out->{member.name}[i]));\n" else: - ret += f"\tunmarshal_{shortname(member.typ)}(net_len, net_bytes, mut_net_offset, mut_host_extra, &(out->{member.name}));\n" + ret += f"\tunmarshal_{shortname(member.typ)}(net_bytes, mut_net_offset, mut_host_extra, &(out->{member.name}));\n" ret += "}\n" + # v9fs_unmarshal_msg ####################################################### + ret += """ +/* v9fs_unmarshal_msg *********************************************************/ + +int v9fs_unmarshal_msg(uint8_t *net_bytes, uint16_t *out_tag, void **out_body) { + uint32_t net_len = decode_u32le(net_bytes); + if (net_len < 7) + return -V9FS_EWRONGSIZE; + uint8_t typ = net_bytes[4]; + *out_tag = decode_u16le(&net_bytes[5]); + + uint32_t net_offset = 7; + size_t host_size; + void *host_extra; + switch (typ) { +""" + for msg in msgs: + ret += f"\tcase V9FS_TYP_{msg.name}:\n" + ret += f"\t\thost_size = sizeof({c_typename(msg)});\n" + ret += f"\t\tif (checksize_{shortname(msg)}(net_len, net_bytes, &net_offset, &host_size))\n" + ret += "\t\t\treturn -V9FS_EWRONGSIZE;\n" + ret += "\n" + ret += "\t\t*out_body = malloc(host_size);" + ret += "\n" + ret += "\t\tnet_offset = 7;\n" + ret += f"\t\thost_extra = *out_body + sizeof({c_typename(msg)});\n" + ret += f"\t\tunmarshal_{shortname(msg)}(net_bytes, &net_offset, &host_extra, *out_body);\n" + ret += "\n" + ret += "\t\tbreak;\n" + ret += """ + default: + return -V9FS_EBADTYPE; + } + return typ; +} +""" + + # marshal_* ################################################################ + ret += """ +/* marshal_* ******************************************************************/ + +static inline void marshal_1(uint8_t val, uint8_t *out_net_bytes, uint32_t *mut_net_offset) { + out_net_bytes[*mut_net_offset] = val; + *mut_net_offset += 1; +} +static inline void marshal_2(uint16_t val, uint8_t *out_net_bytes, uint32_t *mut_net_offset) { + encode_u16le(val, &out_net_bytes[*mut_net_offset]); + *mut_net_offset += 2; +} +static inline void marshal_4(uint32_t val, uint8_t *out_net_bytes, uint32_t *mut_net_offset) { + encode_u32le(val, &out_net_bytes[*mut_net_offset]); + *mut_net_offset += 4; +} +static inline void marshal_8(uint64_t val, uint8_t *out_net_bytes, uint32_t *mut_net_offset) { + encode_u64le(val, &out_net_bytes[*mut_net_offset]); + *mut_net_offset += 8; +} +""" + for struct in structs + msgs: + argattr = ' UNUSED' if len(struct.members) == 0 else '' + ret += f"static inline void marshal_{shortname(struct)}({c_typename(struct)} val{argattr}, uint8_t *out_net_bytes{argattr}, uint32_t *mut_net_offset{argattr}) {{" + if len(struct.members) == 0: + ret += "}\n" + continue + ret += "\n" + for member in struct.members: + if isinstance(member.typ, List): + ret += f"\tfor (typeof(val.{member.typ.cnt}) i = 0; i < val.{member.typ.cnt}; i++)\n" + ret += f"\t\tmarshal_{shortname(member.typ.typ)}(val.{member.name}[i], out_net_bytes, mut_net_offset);\n" + else: + ret += f"\tmarshal_{shortname(member.typ)}(val.{member.name}, out_net_bytes, mut_net_offset);\n" + ret += "}\n" + + # _v9fs_marshal_msg_* ###################################################### + ret += """ +/* _v9fs_marshal_msg_* ********************************************************/ + +""" + for msg in msgs: + ret += f"uint32_t _v9fs_marshal_{shortname(msg)}(uint16_t in_msgid, {c_typename(msg)} in_msg, uint8_t *out_buf) {{\n" + ret += "\tuint32_t offset = 4;\n" + ret += f"\tmarshal_1(V9FS_TYP_{msg.name}, out_buf, &offset);\n" + ret += "\tmarshal_2(in_msgid, out_buf, &offset);\n" + ret += f"\tmarshal_{shortname(msg)}(in_msg, out_buf, &offset);\n" + ret += "\tencode_u32le(offset, out_buf);\n" + ret += "\treturn offset;\n" + ret += "}\n" + ret += "\n" + ############################################################################ return ret |