From abe1b49b4742aa21b4068b81ec22f82a8af93edf Mon Sep 17 00:00:00 2001 From: Zdenek Kabelac Date: Sun, 12 May 2024 01:14:14 +0200 Subject: [PATCH] command: refactor struct command_name Split struct command_name to the constant part (keep the name) and new 'struct command_name_args' which holds runtime computed info. To get to the _args part - we can easily use lvm_command_enum as equivalent index. Constified part 'struct command_name' is now fully stored in .data.rel.ro segment, while command_name_args part goes to .bss segment. Code will be further reduced with next refactoring. --- tools/command.c | 41 +++++++++++++++++++--------------- tools/command.h | 6 +++-- tools/lvm.c | 15 ++++++++----- tools/lvm2cmdline.h | 1 + tools/lvmcmdline.c | 36 +++++++++++++++++++----------- tools/man-generator.c | 51 ++++++++++++++++++++++++++++--------------- 6 files changed, 93 insertions(+), 57 deletions(-) diff --git a/tools/command.c b/tools/command.c index 91b50b81a..0a5ea1a50 100644 --- a/tools/command.c +++ b/tools/command.c @@ -83,7 +83,7 @@ static const struct cmd_name cmd_names[CMD_COUNT + 1] = { #ifdef MAN_PAGE_GENERATOR -static struct command_name command_names[] = { +static const struct command_name command_names[] = { #define xx(a, b, c...) { # a, b, c, NULL, a ## _COMMAND }, #include "commands.h" #undef xx @@ -92,11 +92,12 @@ static struct command commands[COMMAND_COUNT]; #else /* MAN_PAGE_GENERATOR */ -struct command_name command_names[] = { +const struct command_name command_names[] = { #define xx(a, b, c...) { # a, b, c, a, a ## _COMMAND }, #include "commands.h" #undef xx }; + extern struct command commands[COMMAND_COUNT]; /* defined in lvmcmdline.c */ const struct opt_name *get_opt_name(int opt) @@ -125,6 +126,8 @@ const struct lv_type *get_lv_type(int lvt_enum) #endif /* MAN_PAGE_GENERATOR */ +struct command_name_args command_names_args[LVM_COMMAND_COUNT] = { 0 }; + /* array of pointers into opt_names[] that is sorted alphabetically (by long opt name) */ static const struct opt_name *opt_names_alpha[ARG_COUNT + 1]; @@ -1182,7 +1185,7 @@ void factor_common_options(void) for (cn = 0; cn < LVM_COMMAND_COUNT; ++cn) { /* already factored */ - if (command_names[cn].variants) + if (command_names_args[cn].variants) continue; for (ci = 0; ci < COMMAND_COUNT; ci++) { @@ -1191,7 +1194,7 @@ void factor_common_options(void) if (strcmp(cmd->name, command_names[cn].name)) continue; - command_names[cn].variants++; + command_names_args[cn].variants++; } for (opt_enum = 0; opt_enum < ARG_COUNT; opt_enum++) { @@ -1203,22 +1206,22 @@ void factor_common_options(void) continue; if (cmd->ro_count || cmd->any_ro_count) - command_names[cn].variant_has_ro = 1; + command_names_args[cn].variant_has_ro = 1; if (cmd->rp_count) - command_names[cn].variant_has_rp = 1; + command_names_args[cn].variant_has_rp = 1; if (cmd->oo_count) - command_names[cn].variant_has_oo = 1; + command_names_args[cn].variant_has_oo = 1; if (cmd->op_count) - command_names[cn].variant_has_op = 1; + command_names_args[cn].variant_has_op = 1; for (ro = 0; ro < cmd->ro_count + cmd->any_ro_count; ro++) { - command_names[cn].all_options[cmd->required_opt_args[ro].opt] = 1; + command_names_args[cn].all_options[cmd->required_opt_args[ro].opt] = 1; if ((cmd->required_opt_args[ro].opt == size_ARG) && !strncmp(cmd->name, "lv", 2)) - command_names[cn].all_options[extents_ARG] = 1; + command_names_args[cn].all_options[extents_ARG] = 1; } for (oo = 0; oo < cmd->oo_count; oo++) - command_names[cn].all_options[cmd->optional_opt_args[oo].opt] = 1; + command_names_args[cn].all_options[cmd->optional_opt_args[oo].opt] = 1; found = 0; @@ -1234,7 +1237,7 @@ void factor_common_options(void) } /* all commands starting with this name use this option */ - command_names[cn].common_options[opt_enum] = 1; + command_names_args[cn].common_options[opt_enum] = 1; next_opt: ; } @@ -1723,6 +1726,7 @@ static void _print_usage_def(struct command *cmd, int opt_enum, struct arg_def * void print_usage(struct command *cmd, int longhelp, int desc_first) { const struct command_name *cname = _find_command_name(cmd->name); + const struct command_name_args *cna = (cname) ? &command_names_args[cname->lvm_command_enum] : NULL; int any_req = (cmd->cmd_flags & CMD_FLAG_ANY_REQUIRED_OPT) ? 1 : 0; int include_extents = 0; int ro, rp, oo, op, opt_enum, first; @@ -1875,7 +1879,7 @@ void print_usage(struct command *cmd, int longhelp, int desc_first) * see print_common_options_cmd() */ - if (cname && (cname->variants > 1) && cname->common_options[opt_enum]) + if (cna && (cna->variants > 1) && cna->common_options[opt_enum]) continue; printf("\n\t["); @@ -1915,7 +1919,7 @@ void print_usage(struct command *cmd, int longhelp, int desc_first) * see print_common_options_cmd() */ - if (cname && (cname->variants > 1) && cname->common_options[opt_enum]) + if (cna && (cna->variants > 1) && cna->common_options[opt_enum]) continue; printf("\n\t["); @@ -1999,6 +2003,7 @@ void print_usage_common_lvm(const struct command_name *cname, struct command *cm void print_usage_common_cmd(const struct command_name *cname, struct command *cmd) { + const struct command_name_args *cna = &command_names_args[cname->lvm_command_enum]; int oo, opt_enum; int found_common_command = 0; @@ -2007,11 +2012,11 @@ void print_usage_common_cmd(const struct command_name *cname, struct command *cm * are common to all commands with a common name. */ - if (cname->variants < 2) + if (cna->variants < 2) return; for (opt_enum = 0; opt_enum < ARG_COUNT; opt_enum++) { - if (!cname->common_options[opt_enum]) + if (!cna->common_options[opt_enum]) continue; if (_is_lvm_all_opt(opt_enum)) continue; @@ -2027,7 +2032,7 @@ void print_usage_common_cmd(const struct command_name *cname, struct command *cm /* print options with short opts */ for (opt_enum = 0; opt_enum < ARG_COUNT; opt_enum++) { - if (!cname->common_options[opt_enum]) + if (!cna->common_options[opt_enum]) continue; if (_is_lvm_all_opt(opt_enum)) @@ -2055,7 +2060,7 @@ void print_usage_common_cmd(const struct command_name *cname, struct command *cm /* print options without short opts */ for (opt_enum = 0; opt_enum < ARG_COUNT; opt_enum++) { - if (!cname->common_options[opt_enum]) + if (!cna->common_options[opt_enum]) continue; if (_is_lvm_all_opt(opt_enum)) diff --git a/tools/command.h b/tools/command.h index 5f9c9172c..b0492a316 100644 --- a/tools/command.h +++ b/tools/command.h @@ -36,7 +36,9 @@ struct command_name { unsigned int flags; command_fn fn; /* old style */ uint16_t lvm_command_enum; /* as declared in commands.h with _COMMAND */ +}; +struct command_name_args { uint16_t num_args; uint16_t variants; /* number of command defs with this command name */ /* union of {required,optional}_opt_args for all commands with this name */ @@ -184,8 +186,8 @@ struct command { const char *name; const char *desc; /* specific command description from command-lines.in */ const char *command_id; /* ID string in command-lines.in */ - int command_enum; /* _CMD */ - int command_index; /* position in commands[] */ + uint16_t command_enum; /* _CMD */ + uint16_t command_index; /* position in commands[] */ const struct command_function *functions; /* new style */ command_fn fn; /* old style */ diff --git a/tools/lvm.c b/tools/lvm.c index 1d001dbe9..2d7f1a516 100644 --- a/tools/lvm.c +++ b/tools/lvm.c @@ -63,6 +63,7 @@ static char *_list_args(const char *text, int state) static int match_no = 0; static size_t len = 0; static struct command_name *cname; + static struct command_name_args *cna; /* Initialise if this is a new completion attempt */ if (!state) { @@ -71,6 +72,7 @@ static char *_list_args(const char *text, int state) match_no = 0; cname = NULL; + cna = NULL; len = strlen(text); /* Find start of first word in line buffer */ @@ -89,6 +91,7 @@ static char *_list_args(const char *text, int state) } if ((!*p) && *q == ' ') { cname = _cmdline->command_names + j; + cna = _cmdline->command_names_args + j; break; } } @@ -99,11 +102,11 @@ static char *_list_args(const char *text, int state) /* Short form arguments */ if (len < 3) { - while (match_no < cname->num_args) { + while (match_no < cna->num_args) { char s[3]; char c; if (!(c = (_cmdline->opt_names + - cname->valid_args[match_no++])->short_opt)) + cna->valid_args[match_no++])->short_opt)) continue; sprintf(s, "-%c", c); @@ -113,13 +116,13 @@ static char *_list_args(const char *text, int state) } /* Long form arguments */ - if (match_no < cname->num_args) - match_no = cname->num_args; + if (match_no < cna->num_args) + match_no = cna->num_args; - while (match_no - cname->num_args < cname->num_args) { + while (match_no - cna->num_args < cna->num_args) { const char *l; l = (_cmdline->opt_names + - cname->valid_args[match_no++ - cname->num_args])->long_opt; + cna->valid_args[match_no++ - cna->num_args])->long_opt; if (*(l + 2) && !strncmp(text, l, len)) return strdup(l); } diff --git a/tools/lvm2cmdline.h b/tools/lvm2cmdline.h index a5d5e8f67..15df29ff6 100644 --- a/tools/lvm2cmdline.h +++ b/tools/lvm2cmdline.h @@ -23,6 +23,7 @@ struct cmdline_context { struct command *commands; int num_commands; struct command_name *command_names; + struct command_name_args *command_names_args; int num_command_names; }; diff --git a/tools/lvmcmdline.c b/tools/lvmcmdline.c index 35b368a1c..da69de6e7 100644 --- a/tools/lvmcmdline.c +++ b/tools/lvmcmdline.c @@ -53,6 +53,7 @@ extern char *optarg; * Table of command names */ extern struct command_name command_names[]; +extern struct command_name_args command_names_args[]; /* * Table of commands (as defined in command-lines.in) @@ -159,10 +160,11 @@ static const struct command_function _command_functions[CMD_COUNT] = { /* Command line args */ int arg_is_valid_for_command(const struct cmd_context *cmd, int a) { + const struct command_name_args *cna = &command_names_args[cmd->cname->lvm_command_enum]; int i; - for (i = 0; i < cmd->cname->num_args; i++) { - if (cmd->cname->valid_args[i] == a) + for (i = 0; i < cna->num_args; i++) { + if (cna->valid_args[i] == a) return 1; } @@ -1268,18 +1270,18 @@ static void _set_valid_args_for_command_name(int ci) if (all_args[i]) { opt_enum = _cmdline.opt_names[i].opt_enum; - command_names[ci].valid_args[num_args] = opt_enum; + command_names_args[ci].valid_args[num_args] = opt_enum; num_args++; /* Automatically recognize --extents in addition to --size. */ if (opt_enum == size_ARG) { - command_names[ci].valid_args[num_args] = extents_ARG; + command_names_args[ci].valid_args[num_args] = extents_ARG; num_args++; } /* Recognize synonyms */ if ((opt_syn = _opt_standard_to_synonym(command_names[ci].name, opt_enum))) { - command_names[ci].valid_args[num_args] = opt_syn; + command_names_args[ci].valid_args[num_args] = opt_syn; num_args++; } @@ -1290,13 +1292,13 @@ static void _set_valid_args_for_command_name(int ci) * so just add allocation whenever either is seen. */ if ((opt_enum == allocatable_ARG) || (opt_enum == resizeable_ARG)) { - command_names[ci].valid_args[num_args] = allocation_ARG; + command_names_args[ci].valid_args[num_args] = allocation_ARG; num_args++; } } } - command_names[ci].num_args = num_args; + command_names_args[ci].num_args = num_args; } static const struct command_function *_find_command_id_function(int command_enum) @@ -1318,6 +1320,7 @@ static void _unregister_commands(void) _cmdline.commands = NULL; _cmdline.num_commands = 0; _cmdline.command_names = NULL; + _cmdline.command_names_args = NULL; _cmdline.num_command_names = 0; } @@ -1385,6 +1388,7 @@ int lvm_register_commands(struct cmd_context *cmd, const char *run_name) _cmdline.num_command_names = i; /* Also counted how many command entries we have */ _cmdline.command_names = command_names; + _cmdline.command_names_args = command_names_args; return 1; } @@ -2012,6 +2016,7 @@ static void _short_usage(const char *name) static int _usage(const char *name, int longhelp, int skip_notes) { const struct command_name *cname = find_command_name(name); + const struct command_name_args *cna = &command_names_args[cname->lvm_command_enum]; struct command *cmd = NULL; int show_full = longhelp; int i; @@ -2031,7 +2036,7 @@ static int _usage(const char *name, int longhelp, int skip_notes) /* Reduce the default output when there are several variants. */ - if (cname->variants < 3) + if (cna->variants < 3) show_full = 1; for (i = 0; i < COMMAND_COUNT; i++) { @@ -2167,14 +2172,17 @@ static void _add_getopt_arg(int opt_enum, char **optstrp, struct option **longop static int _find_arg(const char *cmd_name, int goval) { const struct command_name *cname; + const struct command_name_args *cna; int arg_enum; int i; if (!(cname = find_command_name(cmd_name))) return -1; - for (i = 0; i < cname->num_args; i++) { - arg_enum = cname->valid_args[i]; + cna = &command_names_args[cname->lvm_command_enum]; + + for (i = 0; i < cna->num_args; i++) { + arg_enum = cna->valid_args[i]; /* assert arg_enum == _cmdline.opt_names[arg_enum].arg_enum */ @@ -2212,9 +2220,11 @@ static int _process_command_line(struct cmd_context *cmd, int *argc, char ***arg * array (opts) to pass to the getopt_long() function. IOW we generate * the arguments to pass to getopt_long() from the opt_names data. */ - if (cmd->cname) - for (i = 0; i < cmd->cname->num_args; i++) - _add_getopt_arg(cmd->cname->valid_args[i], &ptr, &o); + if (cmd->cname) { + struct command_name_args *cna = &command_names_args[cmd->cname->lvm_command_enum]; + for (i = 0; i < cna->num_args; i++) + _add_getopt_arg(cna->valid_args[i], &ptr, &o); + } *ptr = '\0'; memset(o, 0, sizeof(*o)); diff --git a/tools/man-generator.c b/tools/man-generator.c index 7be39a68b..32fbd9982 100644 --- a/tools/man-generator.c +++ b/tools/man-generator.c @@ -347,6 +347,7 @@ static const char *_man_long_opt_name(const char *cmdname, int opt_enum) static void _print_man_usage(char *lvmname, struct command *cmd) { const struct command_name *cname; + const struct command_name_args *cna; int any_req = (cmd->cmd_flags & CMD_FLAG_ANY_REQUIRED_OPT) ? 1 : 0; int sep, ro, rp, oo, op, opt_enum; int need_ro_indent_end = 0; @@ -358,6 +359,8 @@ static void _print_man_usage(char *lvmname, struct command *cmd) if (!(cname = _find_command_name(cmd->name))) return; + cna = &command_names_args[cname->lvm_command_enum]; + printf("\\fB%s\\fP", lvmname); if (!any_req) @@ -594,7 +597,7 @@ static void _print_man_usage(char *lvmname, struct command *cmd) if (_is_lvm_all_opt(opt_enum)) continue; - if ((cname->variants > 1) && cname->common_options[opt_enum]) + if ((cna->variants > 1) && cna->common_options[opt_enum]) continue; if (sep) @@ -623,7 +626,7 @@ static void _print_man_usage(char *lvmname, struct command *cmd) if (_is_lvm_all_opt(opt_enum)) continue; - if ((cname->variants > 1) && cname->common_options[opt_enum]) + if ((cna->variants > 1) && cna->common_options[opt_enum]) continue; if (sep) @@ -794,17 +797,20 @@ static void _print_man_usage_common_lvm(struct command *cmd) static void _print_man_usage_common_cmd(struct command *cmd) { const struct command_name *cname; + const struct command_name_args *cna; int i, sep, oo, opt_enum; int found_common_command = 0; if (!(cname = _find_command_name(cmd->name))) return; - if (cname->variants < 2) + cna = &command_names_args[cname->lvm_command_enum]; + + if (cna->variants < 2) return; for (opt_enum = 0; opt_enum < ARG_COUNT; opt_enum++) { - if (!cname->common_options[opt_enum]) + if (!cna->common_options[opt_enum]) continue; if (_is_lvm_all_opt(opt_enum)) continue; @@ -827,14 +833,14 @@ static void _print_man_usage_common_cmd(struct command *cmd) for (i = 0; i < ARG_COUNT; i++) { opt_enum = opt_names_alpha[i]->opt_enum; - if (!cname->common_options[opt_enum]) + if (!cna->common_options[opt_enum]) continue; if (!opt_names[opt_enum].short_opt) continue; /* common cmd options only used with variants */ - if (cname->variants < 2) + if (cna->variants < 2) continue; if (_is_lvm_all_opt(opt_enum)) @@ -865,14 +871,14 @@ static void _print_man_usage_common_cmd(struct command *cmd) for (i = 0; i < ARG_COUNT; i++) { opt_enum = opt_names_alpha[i]->opt_enum; - if (!cname->common_options[opt_enum]) + if (!cna->common_options[opt_enum]) continue; if (opt_names[opt_enum].short_opt) continue; /* common cmd options only used with variants */ - if (cname->variants < 2) + if (cna->variants < 2) continue; if (_is_lvm_all_opt(opt_enum)) @@ -992,15 +998,18 @@ static void _print_man_option_desc(const struct command_name *cname, int opt_enu static void _print_man_all_options_list(const struct command_name *cname) { + const struct command_name_args *cna; int opt_enum, val_enum; int sep = 0; int i; int adl = 0; + cna = &command_names_args[cname->lvm_command_enum]; + for (i = 0; i < ARG_COUNT; i++) { opt_enum = opt_names_alpha[i]->opt_enum; - if (!cname->all_options[opt_enum]) + if (!cna->all_options[opt_enum]) continue; if (sep) @@ -1046,14 +1055,17 @@ static void _print_man_all_options_list(const struct command_name *cname) static void _print_man_all_options_desc(const struct command_name *cname) { + const struct command_name_args *cna; int opt_enum, val_enum; int i; int adl; + cna = &command_names_args[cname->lvm_command_enum]; + for (i = 0; i < ARG_COUNT; i++) { opt_enum = opt_names_alpha[i]->opt_enum; - if (!cname->all_options[opt_enum]) + if (!cna->all_options[opt_enum]) continue; val_enum = _get_val_enum(cname, opt_enum); @@ -1347,6 +1359,7 @@ out_close: static int _print_man(char *name, char *des_file, int secondary) { const struct command_name *cname; + const struct command_name_args *cna; struct command *cmd, *prev_cmd = NULL; char *lvmname = name; int i; @@ -1399,29 +1412,31 @@ static int _print_man(char *name, char *des_file, int secondary) if (!(cname = _find_command_name(cmd->name))) return 0; - if (cname->variant_has_ro && cname->variant_has_rp) + cna = &command_names_args[cname->lvm_command_enum]; + + if (cna->variant_has_ro && cna->variant_has_rp) printf("\\fB%s\\fP \\fIoption_args\\fP \\fIposition_args\\fP\n", lvmname); - else if (cname->variant_has_ro && !cname->variant_has_rp) + else if (cna->variant_has_ro && !cna->variant_has_rp) printf("\\fB%s\\fP \\fIoption_args\\fP\n", lvmname); - else if (!cname->variant_has_ro && cname->variant_has_rp) + else if (!cna->variant_has_ro && cna->variant_has_rp) printf("\\fB%s\\fP \\fIposition_args\\fP\n", lvmname); - else if (!cname->variant_has_ro && !cname->variant_has_rp) + else if (!cna->variant_has_ro && !cna->variant_has_rp) printf("\\fB%s\\fP\n", lvmname); printf(".br\n"); - if (cname->variant_has_oo) { + if (cna->variant_has_oo) { printf(" [ \\fIoption_args\\fP ]\n"); printf(".br\n"); } - if (cname->variant_has_op) { + if (cna->variant_has_op) { printf(" [ \\fIposition_args\\fP ]\n"); printf(".br\n"); } /* listing them all when there's only 1 or 2 is just repetative */ - if (cname->variants > 2) { + if (cna->variants > 2) { printf(".P\n"); _print_man_all_options_list(cname); } @@ -1448,7 +1463,7 @@ static int _print_man(char *name, char *des_file, int secondary) printf(".\n.SH VARIABLES\n.\n"); _print_man_all_positions_desc(cname); } else { - if (cname->variants > 2) { + if (cna->variants > 2) { printf("\\(em\n"); printf(".P\n"); } -- 2.43.5