diff options
author | Jakub Kicinski <kuba@kernel.org> | 2023-06-01 19:35:44 -0700 |
---|---|---|
committer | Jakub Kicinski <kuba@kernel.org> | 2023-06-02 22:10:47 -0700 |
commit | 21b6e302789c412bdde84439b9325c76e2a5c428 (patch) | |
tree | dfe24da2cb28675c559b0842b1bd98ccc9a75f86 /tools/net | |
parent | eef9b794eac87022464c28a3763f9030e1d53f80 (diff) | |
download | lwn-21b6e302789c412bdde84439b9325c76e2a5c428.tar.gz lwn-21b6e302789c412bdde84439b9325c76e2a5c428.zip |
tools: ynl-gen: generate enum-to-string helpers
It's sometimes useful to print the name of an enum value,
flag or name of the op. Python can do it, add C helper
code gen for getting names of things.
Example:
static const char * const netdev_xdp_act_strmap[] = {
[0] = "basic",
[1] = "redirect",
[2] = "ndo-xmit",
[3] = "xsk-zerocopy",
[4] = "hw-offload",
[5] = "rx-sg",
[6] = "ndo-xmit-sg",
};
const char *netdev_xdp_act_str(enum netdev_xdp_act value)
{
value = ffs(value) - 1;
if (value < 0 || value >= (int)MNL_ARRAY_SIZE(netdev_xdp_act_strmap))
return NULL;
return netdev_xdp_act_strmap[value];
}
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'tools/net')
-rwxr-xr-x | tools/net/ynl/ynl-gen-c.py | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/tools/net/ynl/ynl-gen-c.py b/tools/net/ynl/ynl-gen-c.py index 8bf4b70216d7..5318edfdb874 100755 --- a/tools/net/ynl/ynl-gen-c.py +++ b/tools/net/ynl/ynl-gen-c.py @@ -1168,6 +1168,56 @@ def put_typol(cw, struct): cw.nl() +def put_op_name_fwd(family, cw): + cw.write_func_prot('const char *', f'{family.name}_op_str', ['int op'], suffix=';') + + +def put_op_name(family, cw): + map_name = f'{family.name}_op_strmap' + cw.block_start(line=f"static const char * const {map_name}[] =") + for op_name, op in family.msgs.items(): + cw.p(f'[{op.enum_name}] = "{op_name}",') + cw.block_end(line=';') + cw.nl() + + cw.write_func_prot('const char *', f'{family.name}_op_str', ['int op']) + cw.block_start() + cw.p(f'if (op < 0 || op >= (int)MNL_ARRAY_SIZE({map_name}))') + cw.p('return NULL;') + cw.p(f'return {map_name}[op];') + cw.block_end() + cw.nl() + + +def put_enum_to_str_fwd(family, cw, enum): + args = [f'enum {enum.render_name} value'] + if 'enum-name' in enum and not enum['enum-name']: + args = ['int value'] + cw.write_func_prot('const char *', f'{enum.render_name}_str', args, suffix=';') + + +def put_enum_to_str(family, cw, enum): + map_name = f'{enum.render_name}_strmap' + cw.block_start(line=f"static const char * const {map_name}[] =") + for entry in enum.entries.values(): + cw.p(f'[{entry.value}] = "{entry.name}",') + cw.block_end(line=';') + cw.nl() + + args = [f'enum {enum.render_name} value'] + if 'enum-name' in enum and not enum['enum-name']: + args = ['int value'] + cw.write_func_prot('const char *', f'{enum.render_name}_str', args) + cw.block_start() + if enum.type == 'flags': + cw.p('value = ffs(value) - 1;') + cw.p(f'if (value < 0 || value >= (int)MNL_ARRAY_SIZE({map_name}))') + cw.p('return NULL;') + cw.p(f'return {map_name}[value];') + cw.block_end() + cw.nl() + + def put_req_nested(ri, struct): func_args = ['struct nlmsghdr *nlh', 'unsigned int attr_type', @@ -2210,6 +2260,14 @@ def main(): if args.mode == "user": has_ntf = False if args.header: + cw.p('/* Enums */') + put_op_name_fwd(parsed, cw) + + for name, const in parsed.consts.items(): + if isinstance(const, EnumSet): + put_enum_to_str_fwd(parsed, cw, const) + cw.nl() + cw.p('/* Common nested types */') for attr_set, struct in sorted(parsed.pure_nested_structs.items()): ri = RenderInfo(cw, parsed, args.mode, "", "", "", attr_set) @@ -2262,6 +2320,14 @@ def main(): print_ntf_parse_prototype(parsed, cw) cw.nl() else: + cw.p('/* Enums */') + put_op_name(parsed, cw) + + for name, const in parsed.consts.items(): + if isinstance(const, EnumSet): + put_enum_to_str(parsed, cw, const) + cw.nl() + cw.p('/* Policies */') for name, _ in parsed.attr_sets.items(): struct = Struct(parsed, name) |