]> sourceware.org Git - lvm2.git/commitdiff
commands: move command def parsing into lvm binary
authorDavid Teigland <teigland@redhat.com>
Fri, 10 Feb 2017 17:36:11 +0000 (11:36 -0600)
committerDavid Teigland <teigland@redhat.com>
Mon, 13 Feb 2017 14:20:10 +0000 (08:20 -0600)
It was previously done at build time by the ccmd binary.

13 files changed:
tools/Makefile.in
tools/ccmd-main.c [deleted file]
tools/ccmd-man.c [deleted file]
tools/ccmd-util.c [deleted file]
tools/ccmd.h [deleted file]
tools/command-lines.in
tools/command.c [new file with mode: 0644]
tools/command.h
tools/lvchange.c
tools/lvconvert.c
tools/lvmcmdline.c
tools/toollib.c
tools/tools.h

index 8f53851c3e455ffbce5aada8d858ed094bc99ac0..1761be409d304ed37985a69f2fb30d56ef88cd9a 100644 (file)
@@ -18,6 +18,7 @@ top_srcdir = @top_srcdir@
 top_builddir = @top_builddir@
 
 SOURCES =\
+       command.c \
        dumpconfig.c \
        formats.c \
        lvchange.c \
@@ -77,7 +78,6 @@ SOURCES2 =\
 
 TARGETS =\
        .commands \
-       command-lines.h \
        liblvm2cmd.a \
        lvm
 
@@ -102,7 +102,7 @@ CLEAN_TARGETS = liblvm2cmd.$(LIB_SUFFIX) $(TARGETS_DM) \
        liblvm2cmd.$(LIB_SUFFIX).$(LIB_VERSION) lvm-static.o \
        liblvm2cmd-static.a dmsetup.static lvm.static \
        $(LDDEPS) .exported_symbols_generated \
-       ccmd command-lines.h command-lines-count.h
+       cmds.h command-lines-input.h command-count.h
 
 ifeq ("@CMDLIB@", "yes")
        TARGETS += liblvm2cmd.$(LIB_SUFFIX).$(LIB_VERSION)
@@ -176,35 +176,40 @@ liblvm2cmd.$(LIB_SUFFIX).$(LIB_VERSION): liblvm2cmd.$(LIB_SUFFIX)
        $(CC) -E -P $(srcdir)/cmdnames.h 2> /dev/null | \
                egrep -v '^ *(|#.*|config|devtypes|dumpconfig|formats|fullreport|help|lastlog|lvpoll|pvdata|segtypes|systemid|tags|version) *$$' > .commands
 
-ccmd: $(srcdir)/ccmd-main.c $(srcdir)/ccmd-util.c $(srcdir)/ccmd-man.c
-       $(CC) $(srcdir)/ccmd-main.c $(srcdir)/ccmd-util.c $(srcdir)/ccmd-man.c -o ccmd
-
 .DELETE_ON_ERROR:
 
-command-lines.h: $(srcdir)/command-lines.in ccmd
-       $(top_builddir)/tools/ccmd --output struct $(srcdir)/command-lines.in > $@
-
-command-lines-count.h: $(srcdir)/command-lines.in ccmd
-       $(top_builddir)/tools/ccmd --output count $(srcdir)/command-lines.in > $@
-
 # move properly to configure
 WC = /usr/bin/wc
 GREP = /bin/grep
 SORT = /bin/sort
-CUT = /bin/cut
-SED = /bin/sed
 
-# FIXME Add licence text from template file
-command-lines-count-new.h: $(srcdir)/command-lines.in ccmd Makefile
+command-count.h: $(srcdir)/command-lines.in Makefile
+       set -o pipefail && \
+       ( cat $(top_srcdir)/doc/license.txt && \
+         echo "/* Do not edit. This file is generated by the Makefile. */" && \
+         echo -n "#define COMMAND_COUNT " && \
+         $(GREP) '^ID:' $(srcdir)/command-lines.in | $(WC) -l \
+       ) > $@
+
+cmds.h: $(srcdir)/command-lines.in Makefile
+       set -o pipefail && \
+       ( cat $(top_srcdir)/doc/license.txt && \
+         echo "/* Do not edit. This file is generated by the Makefile. */" && \
+         echo "cmd(CMD_NONE, none)" && \
+         $(GREP) '^ID:' $(srcdir)/command-lines.in | $(SORT) -u | $(AWK) '{print "cmd(" $$2 "_CMD, " $$2 ")"}' && \
+         echo "cmd(CMD_COUNT, count)" \
+       ) > $@
+
+command-lines-input.h: $(srcdir)/command-lines.in Makefile
        set -o pipefail && \
-       (echo -n "#define COMMAND_COUNT " && \
-       $(GREP) '^ID:' $(srcdir)/command-lines.in | $(WC) -l && \
-       echo -e "enum {\n\tno_CMD," && \
-       $(GREP) '^ID:' $(srcdir)/command-lines.in | $(CUT) -d\  -f2 | $(SORT) -u | $(SED) 's/\(.*\)/\t&_CMD,/' && \
-       echo -e "\tCOMMAND_ID_COUNT,\n};" \
+       ( cat $(top_srcdir)/doc/license.txt && \
+         echo "/* Do not edit. This file is generated by the Makefile. */" && \
+         echo -en "const char _command_input[] =\n\n\"" && \
+         $(GREP) -Ev '^#|\-\-\-|^$$' $(srcdir)/command-lines.in | $(AWK) 'BEGIN {ORS = "\\n\"\n\""} //' && \
+         echo "\\n\";" \
        ) > $@
 
-$(SOURCES:%.c=%.d): command-lines.h command-lines-count.h
+$(SOURCES:%.c=%.d) $(SOURCES2:%.c=%.d): command-lines-input.h command-count.h cmds.h
 
 ifneq ("$(CFLOW_CMD)", "")
 CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES))
diff --git a/tools/ccmd-main.c b/tools/ccmd-main.c
deleted file mode 100644 (file)
index 85d5656..0000000
+++ /dev/null
@@ -1,1130 +0,0 @@
-#include <asm/types.h>
-#include <sys/types.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/wait.h>
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <stdarg.h>
-#include <limits.h>
-#include <unistd.h>
-#include <syslog.h>
-#include <sched.h>
-#include <dirent.h>
-#include <ctype.h>
-#include <getopt.h>
-
-#include "ccmd.h"
-
-
-/* input util functions (in ccmd-util.c) */
-char *split_line(char *buf, int *argc, char **argv, char sep);
-int val_str_to_num(char *str);
-int opt_str_to_num(char *str);
-int lvp_name_to_enum(char *str);
-int lv_to_enum(char *name);
-uint64_t lv_to_bits(char *name);
-
-/* header output functions (in ccmd-util.c) */
-void print_header_struct(void);
-void print_header_count(void);
-void print_ambiguous(void);
-
-/* man page output (in ccmd-main.c) */
-void print_man(char *man_command_name, int include_primary, int include_secondary);
-
-
-/* create table of value names, e.g. String, and corresponding enum from vals.h */
-
-struct val_name val_names[VAL_COUNT + 1] = {
-#define val(a, b, c, d) { # a, a, b, c, d },
-#include "vals.h"
-#undef val
-};
-
-/* create table of option names, e.g. --foo, and corresponding enum from args.h */
-
-struct opt_name opt_names[ARG_COUNT + 1] = {
-#define arg(a, b, c, d, e, f, g) { # a, a, b, "", "--" c, d, e, f, g },
-#include "args.h"
-#undef arg
-};
-
-/* create table of lv property names, e.g. lv_is_foo, and corresponding enum from lv_props.h */
-
-struct lvp_name lvp_names[LVP_COUNT + 1] = {
-#define lvp(a, b, c) { # a, a, b },
-#include "lv_props.h"
-#undef lvp
-};
-
-/* create table of lv type names, e.g. linear and corresponding enum from lv_types.h */
-
-struct lvt_name lvt_names[LVT_COUNT + 1] = {
-#define lvt(a, b, c) { # a, a, b },
-#include "lv_types.h"
-#undef lvt
-};
-
-/* create table of command names, e.g. vgcreate */
-
-struct cmd_name cmd_names[MAX_CMD_NAMES] = {
-#define xx(a, b, c) { # a , b } ,
-#include "commands.h"
-#undef xx
-};
-
-/* array of pointers into opt_names[] that is sorted alphabetically (by long opt name) */
-
-struct opt_name *opt_names_alpha[ARG_COUNT + 1];
-
-/* lvm_all is for recording options that are common for all lvm commands */
-
-struct command lvm_all;
-
-/* saves OO_FOO lines (groups of optional options) to include in multiple defs */
-
-static int oo_line_count;
-#define MAX_OO_LINES 256
-
-struct oo_line {
-       char *name;
-       char *line;
-};
-static struct oo_line oo_lines[MAX_OO_LINES];
-
-#define REQUIRED 1  /* required option */
-#define OPTIONAL 0  /* optional option */
-#define IGNORE -1   /* ignore option */
-
-/* control man page output */
-
-static int include_man_secondary = 1; /* include SECONDARY forms in man output */
-static int include_man_primary = 1;   /* include primary forms in man output */
-static char *man_command_name = NULL; /* print man page for a single command name */
-
-
-static void add_optional_opt_line(struct command *cmd, int argc, char *argv[]);
-
-/*
- * Parse command-lines.in and record those definitions
- * in an array of struct command: cmd_array[].
- */
-
-static const char *is_command_name(char *str)
-{
-       int i;
-
-       for (i = 0; i < MAX_CMD_NAMES; i++) {
-               if (!cmd_names[i].name)
-                       break;
-               if (!strcmp(cmd_names[i].name, str))
-                       return cmd_names[i].name;
-       }
-       return NULL;
-}
-
-struct cmd_name *find_command_name(const char *str)
-{
-       int i;
-
-       for (i = 0; i < MAX_CMD_NAMES; i++) {
-               if (!cmd_names[i].name)
-                       break;
-               if (!strcmp(cmd_names[i].name, str))
-                       return &cmd_names[i];
-       }
-       return NULL;
-}
-
-static int is_opt_name(char *str)
-{
-       if (!strncmp(str, "--", 2))
-               return 1;
-
-       if ((str[0] == '-') && (str[1] != '-')) {
-               printf("Options must be specified in long form: %s\n", str);
-               exit(1);
-       }
-
-       return 0;
-}
-
-/*
- * "Select" as a pos name means that the position
- * can be empty if the --select option is used.
- */
-
-static int is_pos_name(char *str)
-{
-       if (!strncmp(str, "VG", 2))
-               return 1;
-       if (!strncmp(str, "LV", 2))
-               return 1;
-       if (!strncmp(str, "PV", 2))
-               return 1;
-       if (!strncmp(str, "Tag", 3))
-               return 1;
-       if (!strncmp(str, "String", 6))
-               return 1;
-       if (!strncmp(str, "Select", 6))
-               return 1;
-       return 0;
-}
-
-static int is_oo_definition(char *str)
-{
-       if (!strncmp(str, "OO_", 3) && strstr(str, ":"))
-               return 1;
-       return 0;
-}
-
-static int is_oo_line(char *str)
-{
-       if (!strncmp(str, "OO:", 3))
-               return 1;
-       return 0;
-}
-
-static int is_io_line(char *str)
-{
-       if (!strncmp(str, "IO:", 3))
-               return 1;
-       return 0;
-}
-
-static int is_op_line(char *str)
-{
-       if (!strncmp(str, "OP:", 3))
-               return 1;
-       return 0;
-}
-
-static int is_desc_line(char *str)
-{
-       if (!strncmp(str, "DESC:", 5))
-               return 1;
-       return 0;
-}
-
-static int is_flags_line(char *str)
-{
-       if (!strncmp(str, "FLAGS:", 6))
-               return 1;
-       return 0;
-}
-
-static int is_rule_line(char *str)
-{
-       if (!strncmp(str, "RULE:", 5))
-               return 1;
-       return 0;
-}
-
-static int is_id_line(char *str)
-{
-       if (!strncmp(str, "ID:", 3))
-               return 1;
-       return 0;
-}
-
-/*
- * Save a positional arg in a struct arg_def.
- * Parse str for anything that can appear in a position,
- * like VG, VG|LV, VG|LV_linear|LV_striped, etc.
- */
-
-static void set_pos_def(struct command *cmd, char *str, struct arg_def *def)
-{
-       char *argv[MAX_LINE_ARGC];
-       int argc;
-       char *name;
-       int val_enum;
-       int i;
-
-       split_line(str, &argc, argv, '|');
-
-       for (i = 0; i < argc; i++) {
-               name = argv[i];
-
-               val_enum = val_str_to_num(name);
-
-               if (!val_enum) {
-                       printf("Unknown pos arg: %s\n", name);
-                       exit(1);
-               }
-
-               def->val_bits |= val_enum_to_bit(val_enum);
-
-               if ((val_enum == lv_VAL) && strstr(name, "_"))
-                       def->lvt_bits = lv_to_bits(name);
-
-               if (strstr(name, "_new")) {
-                       if (val_enum == lv_VAL)
-                               def->flags |= ARG_DEF_FLAG_NEW_LV;
-                       else if (val_enum == vg_VAL)
-                               def->flags |= ARG_DEF_FLAG_NEW_VG;
-               }
-       }
-}
-
-/*
- * Save an option arg in a struct arg_def.
- * Parse str for anything that can follow --option.
- */
-
-static void set_opt_def(struct command *cmd, char *str, struct arg_def *def)
-{
-       char *argv[MAX_LINE_ARGC];
-       int argc;
-       char *name;
-       int val_enum;
-       int i, j;
-
-       split_line(str, &argc, argv, '|');
-
-       for (i = 0; i < argc; i++) {
-               name = argv[i];
-
-               val_enum = val_str_to_num(name);
-
-               if (!val_enum) {
-                       /* a literal number or string */
-
-                       if (isdigit(name[0]))
-                               val_enum = constnum_VAL;
-
-                       else if (isalpha(name[0]))
-                               val_enum = conststr_VAL;
-
-                       else {
-                               printf("Unknown opt arg: %s\n", name);
-                               exit(0);
-                       }
-               }
-
-
-               def->val_bits |= val_enum_to_bit(val_enum);
-
-               if (val_enum == constnum_VAL)
-                       def->num = (uint64_t)atoi(name);
-
-               if (val_enum == conststr_VAL)
-                       def->str = strdup(name);
-
-               if (val_enum == lv_VAL) {
-                       if (strstr(name, "_"))
-                               def->lvt_bits = lv_to_bits(name);
-               }
-
-               if (strstr(name, "_new")) {
-                       if (val_enum == lv_VAL)
-                               def->flags |= ARG_DEF_FLAG_NEW_LV;
-                       else if (val_enum == vg_VAL)
-                               def->flags |= ARG_DEF_FLAG_NEW_VG;
-                               
-               }
-       }
-}
-
-/*
- * Save a set of common options so they can be included in
- * multiple command defs.
- *
- * OO_FOO: --opt1 ...
- *
- * oo->name = "OO_FOO";
- * oo->line = "--opt1 ...";
- */
-
-static void add_oo_definition_line(const char *name, const char *line)
-{
-       struct oo_line *oo;
-       char *colon;
-       char *start;
-
-       oo = &oo_lines[oo_line_count++];
-       oo->name = strdup(name);
-
-       if ((colon = strstr(oo->name, ":")))
-               *colon = '\0';
-       else {
-               printf("invalid OO definition\n");
-               exit(1);
-       }
-
-       start = strstr(line, ":") + 2;
-       oo->line = strdup(start);
-}
-
-/* Support OO_FOO: continuing on multiple lines. */
-
-static void append_oo_definition_line(const char *new_line)
-{
-       struct oo_line *oo;
-       char *old_line;
-       char *line;
-       int len;
-
-       oo = &oo_lines[oo_line_count-1];
-
-       old_line = oo->line;
-
-       /* +2 = 1 space between old and new + 1 terminating \0 */
-       len = strlen(old_line) + strlen(new_line) + 2;
-       line = malloc(len);
-       memset(line, 0, len);
-
-       strcat(line, old_line);
-       strcat(line, " ");
-       strcat(line, new_line);
-
-       free(oo->line);
-       oo->line = line;
-}
-
-/* Find a saved OO_FOO definition. */
-
-char *get_oo_line(char *str)
-{
-       char *name;
-       char *end;
-       char str2[64];
-       int i;
-
-       strcpy(str2, str);
-       if ((end = strstr(str2, ":")))
-               *end = '\0';
-       if ((end = strstr(str2, ",")))
-               *end = '\0';
-
-       for (i = 0; i < oo_line_count; i++) {
-               name = oo_lines[i].name;
-               if (!strcmp(name, str2))
-                       return oo_lines[i].line;
-       }
-       return NULL;
-}
-
-/*
- * Add optional_opt_args entries when OO_FOO appears on OO: line,
- * i.e. include common options from an OO_FOO definition.
- */
-
-static void include_optional_opt_args(struct command *cmd, char *str)
-{
-       char *oo_line;
-       char *line;
-       char *line_argv[MAX_LINE_ARGC];
-       int line_argc;
-
-       if (!(oo_line = get_oo_line(str))) {
-               printf("No OO line found for %s\n", str);
-               exit(1);
-       }
-
-       if (!(line = strdup(oo_line)))
-               exit(1); 
-
-       split_line(line, &line_argc, line_argv, ' ');
-       add_optional_opt_line(cmd, line_argc, line_argv);
-       free(line);
-}
-
-/*
- * When an --option is seen, add a new opt_args entry for it.
- * This function sets the opt_args.opt value for it.
- */
-
-static void add_opt_arg(struct command *cmd, char *str, int *takes_arg, int required)
-{
-       char *comma;
-       int opt;
-
-       /* opt_arg.opt set here */
-       /* opt_arg.def will be set in update_prev_opt_arg() if needed */
-
-       if ((comma = strstr(str, ",")))
-               *comma = '\0';
-
-       /*
-        * Work around nasty hack where --uuid is used for both uuid_ARG
-        * and uuidstr_ARG.  The input uses --uuidstr, where an actual
-        * command uses --uuid string.
-        */
-       if (!strcmp(str, "--uuidstr")) {
-               opt = uuidstr_ARG;
-               goto skip;
-       }
-
-       opt = opt_str_to_num(str);
-skip:
-       if (required > 0)
-               cmd->required_opt_args[cmd->ro_count++].opt = opt;
-       else if (!required)
-               cmd->optional_opt_args[cmd->oo_count++].opt = opt;
-       else if (required < 0)
-               cmd->ignore_opt_args[cmd->io_count++].opt = opt;
-       else
-               exit(1);
-
-       *takes_arg = opt_names[opt].val_enum ? 1 : 0;
-}
-
-/*
- * After --option has been seen, this function sets opt_args.def value
- * for the value that appears after --option.
- */
-
-static void update_prev_opt_arg(struct command *cmd, char *str, int required)
-{
-       struct arg_def def = { 0 };
-       char *comma;
-
-       if (str[0] == '-') {
-               printf("Option %s must be followed by an arg.\n", str);
-               exit(1);
-       }
-
-       /* opt_arg.def set here */
-       /* opt_arg.opt was previously set in add_opt_arg() when --foo was read */
-
-       if ((comma = strstr(str, ",")))
-               *comma = '\0';
-
-       set_opt_def(cmd, str, &def);
-
-       if (required > 0)
-               cmd->required_opt_args[cmd->ro_count-1].def = def;
-       else if (!required)
-               cmd->optional_opt_args[cmd->oo_count-1].def = def;
-       else if (required < 0)
-               cmd->ignore_opt_args[cmd->io_count-1].def = def;
-       else
-               exit(1);
-}
-
-/*
- * When an position arg is seen, add a new pos_args entry for it.
- * This function sets the pos_args.pos and pos_args.def.
- */
-
-static void add_pos_arg(struct command *cmd, char *str, int required)
-{
-       struct arg_def def = { 0 };
-
-       /* pos_arg.pos and pos_arg.def are set here */
-
-       set_pos_def(cmd, str, &def);
-
-       if (required) {
-               cmd->required_pos_args[cmd->rp_count].pos = cmd->pos_count++;
-               cmd->required_pos_args[cmd->rp_count].def = def;
-               cmd->rp_count++;
-       } else {
-               cmd->optional_pos_args[cmd->op_count].pos = cmd->pos_count++;;
-               cmd->optional_pos_args[cmd->op_count].def = def;
-               cmd->op_count++;
-       }
-}
-
-/* Process something that follows a pos arg, which is not a new pos arg. */
-
-static void update_prev_pos_arg(struct command *cmd, char *str, int required)
-{
-       struct arg_def *def;
-
-       /* a previous pos_arg.def is modified here */
-
-       if (required)
-               def = &cmd->required_pos_args[cmd->rp_count-1].def;
-       else
-               def = &cmd->optional_pos_args[cmd->op_count-1].def;
-
-       if (!strcmp(str, "..."))
-               def->flags |= ARG_DEF_FLAG_MAY_REPEAT;
-       else {
-               printf("Unknown pos arg: %s\n", str);
-               exit(1);
-       }
-}
-
-/* Process what follows OO:, which are the optional opt args for the cmd def. */
-
-static void add_optional_opt_line(struct command *cmd, int argc, char *argv[])
-{
-       int takes_arg;
-       int i;
-
-       for (i = 0; i < argc; i++) {
-               if (!i && !strncmp(argv[i], "OO:", 3))
-                       continue;
-               if (is_opt_name(argv[i]))
-                       add_opt_arg(cmd, argv[i], &takes_arg, OPTIONAL);
-               else if (!strncmp(argv[i], "OO_", 3))
-                       include_optional_opt_args(cmd, argv[i]);
-               else if (takes_arg)
-                       update_prev_opt_arg(cmd, argv[i], OPTIONAL);
-               else
-                       printf("Can't parse argc %d argv %s prev %s\n",
-                               i, argv[i], argv[i-1]);
-       }
-}
-
-/* Process what follows IO:, which are the ignore options for the cmd def. */
-
-static void add_ignore_opt_line(struct command *cmd, int argc, char *argv[])
-{
-       int takes_arg;
-       int i;
-
-       for (i = 0; i < argc; i++) {
-               if (!i && !strncmp(argv[i], "IO:", 3))
-                       continue;
-               if (is_opt_name(argv[i]))
-                       add_opt_arg(cmd, argv[i], &takes_arg, IGNORE);
-               else if (takes_arg)
-                       update_prev_opt_arg(cmd, argv[i], IGNORE);
-               else
-                       printf("Can't parse argc %d argv %s prev %s\n",
-                               i, argv[i], argv[i-1]);
-       }
-}
-
-/* Process what follows OP:, which are optional pos args for the cmd def. */
-
-static void add_optional_pos_line(struct command *cmd, int argc, char *argv[])
-{
-       int i;
-
-       for (i = 0; i < argc; i++) {
-               if (!i && !strncmp(argv[i], "OP:", 3))
-                       continue;
-               if (is_pos_name(argv[i]))
-                       add_pos_arg(cmd, argv[i], OPTIONAL);
-               else
-                       update_prev_pos_arg(cmd, argv[i], OPTIONAL);
-       }
-}
-
-static void add_required_opt_line(struct command *cmd, int argc, char *argv[])
-{
-       int takes_arg;
-       int i;
-
-       for (i = 0; i < argc; i++) {
-               if (is_opt_name(argv[i]))
-                       add_opt_arg(cmd, argv[i], &takes_arg, REQUIRED);
-               else if (takes_arg)
-                       update_prev_opt_arg(cmd, argv[i], REQUIRED);
-               else
-                       printf("Can't parse argc %d argv %s prev %s\n",
-                               i, argv[i], argv[i-1]);
-       }
-}
-
-/*
- * Add to required_opt_args from an OO_FOO definition.
- * (This is the special case of vgchange/lvchange where one
- * optional option is required, and others are then optional.)
- * The set of options from OO_FOO are saved in required_opt_args,
- * and flag CMD_FLAG_ONE_REQUIRED_OPT is set on the cmd indicating
- * this special case.
- */
-static void include_required_opt_args(struct command *cmd, char *str)
-{
-       char *oo_line;
-       char *line;
-       char *line_argv[MAX_LINE_ARGC];
-       int line_argc;
-
-       if (!(oo_line = get_oo_line(str))) {
-               printf("No OO line found for %s\n", str);
-               exit(1);
-       }
-
-       if (!(line = strdup(oo_line)))
-               exit(1); 
-
-       split_line(line, &line_argc, line_argv, ' ');
-       add_required_opt_line(cmd, line_argc, line_argv);
-       free(line);
-}
-
-/* Process what follows command_name, which are required opt/pos args. */
-
-static void add_required_line(struct command *cmd, int argc, char *argv[])
-{
-       int i;
-       int takes_arg;
-       int prev_was_opt = 0, prev_was_pos = 0;
-
-       /* argv[0] is command name */
-
-       for (i = 1; i < argc; i++) {
-
-               if (is_opt_name(argv[i])) {
-                       /* add new required_opt_arg */
-                       add_opt_arg(cmd, argv[i], &takes_arg, REQUIRED);
-                       prev_was_opt = 1;
-                       prev_was_pos = 0;
-
-               } else if (prev_was_opt && takes_arg) {
-                       /* set value for previous required_opt_arg */
-                       update_prev_opt_arg(cmd, argv[i], REQUIRED);
-                       prev_was_opt = 0;
-                       prev_was_pos = 0;
-
-               } else if (is_pos_name(argv[i])) {
-                       /* add new required_pos_arg */
-                       add_pos_arg(cmd, argv[i], REQUIRED);
-                       prev_was_opt = 0;
-                       prev_was_pos = 1;
-
-               } else if (!strncmp(argv[i], "OO_", 3)) {
-                       /* one required_opt_arg is required, special case lv/vgchange */
-                       cmd->cmd_flags |= CMD_FLAG_ONE_REQUIRED_OPT;
-                       include_required_opt_args(cmd, argv[i]);
-
-               } else if (prev_was_pos) {
-                       /* set property for previous required_pos_arg */
-                       update_prev_pos_arg(cmd, argv[i], REQUIRED);
-               } else
-                       printf("Can't parse argc %d argv %s prev %s\n",
-                               i, argv[i], argv[i-1]);
-
-       }
-}
-
-static void add_flags(struct command *cmd, char *line)
-{
-       if (strstr(line, "SECONDARY_SYNTAX"))
-               cmd->cmd_flags |= CMD_FLAG_SECONDARY_SYNTAX;
-}
-
-#define MAX_RULE_OPTS 64
-
-static void add_rule(struct command *cmd, char *line)
-{
-       struct cmd_rule *rule;
-       char *line_argv[MAX_LINE_ARGC];
-       char *arg;
-       int line_argc;
-       int i, lvt_enum, lvp_enum;
-       int check = 0;
-
-       if (cmd->rule_count == CMD_MAX_RULES) {
-               printf("too many rules for cmd\n");
-               exit(1);
-       }
-
-       rule = &cmd->rules[cmd->rule_count++];
-
-       split_line(line, &line_argc, line_argv, ' ');
-
-       for (i = 0; i < line_argc; i++) {
-               arg = line_argv[i];
-
-               if (!strcmp(arg, "not")) {
-                       rule->rule = RULE_INVALID;
-                       check = 1;
-               }
-
-               else if (!strcmp(arg, "and")) {
-                       rule->rule = RULE_REQUIRE;
-                       check = 1;
-               }
-
-               else if (!strncmp(arg, "all", 3)) {
-                       /* opt/lvt_bits/lvp_bits all remain 0 to mean all */
-                       continue;
-               }
-
-               else if (!strncmp(arg, "--", 2)) {
-                       if (!rule->opts) {
-                               if (!(rule->opts = malloc(MAX_RULE_OPTS * sizeof(int)))) {
-                                       printf("no mem\n");
-                                       exit(1);
-                               }
-                               memset(rule->opts, 0, MAX_RULE_OPTS * sizeof(int));
-                       }
-
-                       if (!rule->check_opts) {
-                               if (!(rule->check_opts = malloc(MAX_RULE_OPTS * sizeof(int)))) {
-                                       printf("no mem\n");
-                                       exit(1);
-                               }
-                               memset(rule->check_opts, 0, MAX_RULE_OPTS * sizeof(int));
-                       }
-
-                       if (check)
-                               rule->check_opts[rule->check_opts_count++] = opt_str_to_num(arg);
-                       else
-                               rule->opts[rule->opts_count++] = opt_str_to_num(arg);
-               }
-
-               else if (!strncmp(arg, "LV_", 3)) {
-                       lvt_enum = lv_to_enum(arg);
-
-                       if (check)
-                               rule->check_lvt_bits |= lvt_enum_to_bit(lvt_enum);
-                       else
-                               rule->lvt_bits |= lvt_enum_to_bit(lvt_enum);
-               }
-
-               else if (!strncmp(arg, "lv_is_", 6)) {
-                       lvp_enum = lvp_name_to_enum(arg);
-
-                       if (check)
-                               rule->check_lvp_bits |= lvp_enum_to_bit(lvp_enum);
-                       else
-                               rule->lvp_bits |= lvp_enum_to_bit(lvp_enum);
-               }
-       }
-}
-
-/* The given option is common to all lvm commands (set in lvm_all). */
-
-int is_lvm_all_opt(int opt)
-{
-       int oo;
-
-       for (oo = 0; oo < lvm_all.oo_count; oo++) {
-               if (lvm_all.optional_opt_args[oo].opt == opt)
-                       return 1;
-       }
-       return 0;
-}
-
-/* Find common options for all variants of each command name. */
-
-static void factor_common_options(void)
-{
-       int cn, opt_enum, ci, oo, ro, found;
-       struct command *cmd;
-
-       for (cn = 0; cn < MAX_CMD_NAMES; cn++) {
-               if (!cmd_names[cn].name)
-                       break;
-
-               for (ci = 0; ci < cmd_count; ci++) {
-                       cmd = &cmd_array[ci];
-
-                       if (strcmp(cmd->name, cmd_names[cn].name))
-                               continue;
-
-                       cmd_names[cn].variants++;
-               }
-
-               for (opt_enum = 0; opt_enum < ARG_COUNT; opt_enum++) {
-
-                       for (ci = 0; ci < cmd_count; ci++) {
-                               cmd = &cmd_array[ci];
-
-                               if (strcmp(cmd->name, cmd_names[cn].name))
-                                       continue;
-
-                               if (cmd->ro_count)
-                                       cmd_names[cn].variant_has_ro = 1;
-                               if (cmd->rp_count)
-                                       cmd_names[cn].variant_has_rp = 1;
-                               if (cmd->oo_count)
-                                       cmd_names[cn].variant_has_oo = 1;
-                               if (cmd->op_count)
-                                       cmd_names[cn].variant_has_op = 1;
-
-                               for (ro = 0; ro < cmd->ro_count; ro++) {
-                                       cmd_names[cn].all_options[cmd->required_opt_args[ro].opt] = 1;
-
-                                       if ((cmd->required_opt_args[ro].opt == size_ARG) && !strncmp(cmd->name, "lv", 2))
-                                               cmd_names[cn].all_options[extents_ARG] = 1;
-                               }
-                               for (oo = 0; oo < cmd->oo_count; oo++)
-                                       cmd_names[cn].all_options[cmd->optional_opt_args[oo].opt] = 1;
-
-                               found = 0;
-
-                               for (oo = 0; oo < cmd->oo_count; oo++) {
-                                       if (cmd->optional_opt_args[oo].opt == opt_enum) {
-                                               found = 1;
-                                               break;
-                                       }
-                               }
-
-                               if (!found)
-                                       goto next_opt;
-                       }
-
-                       /* all commands starting with this name use this option */
-                       cmd_names[cn].common_options[opt_enum] = 1;
- next_opt:
-                       ;
-               }
-       }
-}
-
-static int long_name_compare(const void *on1, const void *on2)
-{
-       struct opt_name **optname1 = (void *)on1;
-       struct opt_name **optname2 = (void *)on2;
-       return strcmp((*optname1)->long_opt + 2, (*optname2)->long_opt + 2);
-}
-
-/* Create list of option names for printing alphabetically. */
-
-static void create_opt_names_alpha(void)
-{
-       int i;
-
-       for (i = 0; i < ARG_COUNT; i++)
-               opt_names_alpha[i] = &opt_names[i];
-
-       qsort(opt_names_alpha, ARG_COUNT, sizeof(long), long_name_compare);
-}
-
-static void print_help(int argc, char *argv[])
-{
-       printf("%s [options] --output <format> <filename>\n", argv[0]);
-       printf("\n");
-       printf("output formats:\n");
-       printf("struct:    print C structures for command-lines.h\n");
-       printf("count:     print defines and enums for command-lines-count.h\n");
-       printf("ambiguous: print commands differing only by LV types\n");
-       printf("man:       print man page format.\n");
-       printf("\n");
-       printf("options:\n");
-       printf("-c|--man-command <commandname>  man output for one command name\n");
-}
-
-int main(int argc, char *argv[])
-{
-       char *outputformat = NULL;
-       char *inputfile = NULL;
-       FILE *file;
-       struct command *cmd;
-       char line[MAX_LINE];
-       char line_orig[MAX_LINE];
-       const char *name;
-       char *line_argv[MAX_LINE_ARGC];
-       char *n;
-       int line_argc;
-       int prev_was_oo_def = 0;
-       int prev_was_oo = 0;
-       int prev_was_op = 0;
-
-       if (argc < 2) {
-               print_help(argc, argv);
-               exit(EXIT_FAILURE);
-       }
-
-       create_opt_names_alpha();
-
-       static struct option long_options[] = {
-               {"help",      no_argument,       0, 'h' },
-               {"output",    required_argument, 0, 'o' },
-               {"man-primary", required_argument, 0, 'p' },
-               {"man-secondary", required_argument, 0, 's' },
-               {"man-command", required_argument, 0, 'c' },
-               {0, 0, 0, 0 }
-       };
-
-        while (1) {
-               int c;
-               int option_index = 0;
-
-               c = getopt_long(argc, argv, "ho:p:s:c:",
-                               long_options, &option_index);
-               if (c == -1)
-                       break;
-
-               switch (c) {
-               case '0':
-                       break;
-               case 'h':
-                        print_help(argc, argv);
-                       exit(EXIT_SUCCESS);
-               case 'o':
-                       outputformat = strdup(optarg);
-                       break;
-               case 'p':
-                       include_man_primary = atoi(optarg);
-                       break;
-               case 's':
-                       include_man_secondary = atoi(optarg);
-                       break;
-               case 'c':
-                       man_command_name = strdup(optarg);
-                       break;
-               }
-       }
-
-       if (optind < argc)
-               inputfile = argv[optind];
-       else {
-               printf("Missing filename.\n");
-               return 0;
-       }
-
-       if (!(file = fopen(inputfile, "r"))) {
-               printf("Cannot open %s\n", argv[1]);
-               return -1;
-       }
-
-       /* Process each line of input file. */
-
-       while (fgets(line, MAX_LINE, file)) {
-               if (line[0] == '#')
-                       continue;
-               if (line[0] == '\n')
-                       continue;
-               if (line[0] == '-' && line[1] == '-' && line[2] == '-')
-                       continue;
-
-               if ((n = strchr(line, '\n')))
-                       *n = '\0';
-
-               memcpy(line_orig, line, sizeof(line));
-               split_line(line, &line_argc, line_argv, ' ');
-
-               if (!line_argc)
-                       continue;
-
-               /* command ... */
-               if ((name = is_command_name(line_argv[0]))) {
-                       if (cmd_count >= MAX_CMDS) {
-                               printf("MAX_CMDS too small\n");
-                               return -1;
-                       }
-                       cmd = &cmd_array[cmd_count++];
-                       cmd->name = name;
-                       cmd->pos_count = 1;
-                       add_required_line(cmd, line_argc, line_argv);
-
-                       /* Every cmd gets the OO_ALL options */
-                       include_optional_opt_args(cmd, "OO_ALL:");
-                       continue;
-               }
-
-               if (is_desc_line(line_argv[0])) {
-                       char *desc = strdup(line_orig);
-                       if (cmd->desc) {
-                               int newlen = strlen(cmd->desc) + strlen(desc) + 2;
-                               char *newdesc = malloc(newlen);
-                               memset(newdesc, 0, newlen);
-                               snprintf(newdesc, newlen, "%s %s", cmd->desc, desc);
-                               cmd->desc = newdesc;
-                               free(desc);
-                       } else
-                               cmd->desc = desc;
-                       continue;
-               }
-
-               if (is_flags_line(line_argv[0])) {
-                       add_flags(cmd, line_orig);
-                       continue;
-               }
-
-               if (is_rule_line(line_argv[0])) {
-                       add_rule(cmd, line_orig);
-                       continue;
-               }
-
-               if (is_id_line(line_argv[0])) {
-                       cmd->command_line_id = strdup(line_argv[1]);
-                       continue;
-               }
-
-               /* OO_FOO: ... */
-               if (is_oo_definition(line_argv[0])) {
-                       add_oo_definition_line(line_argv[0], line_orig);
-                       prev_was_oo_def = 1;
-                       prev_was_oo = 0;
-                       prev_was_op = 0;
-                       continue;
-               }
-
-               /* OO: ... */
-               if (is_oo_line(line_argv[0])) {
-                       add_optional_opt_line(cmd, line_argc, line_argv);
-                       prev_was_oo_def = 0;
-                       prev_was_oo = 1;
-                       prev_was_op = 0;
-                       continue;
-               }
-
-               /* OP: ... */
-               if (is_op_line(line_argv[0])) {
-                       add_optional_pos_line(cmd, line_argc, line_argv);
-                       prev_was_oo_def = 0;
-                       prev_was_oo = 0;
-                       prev_was_op = 1;
-                       continue;
-               }
-
-               /* IO: ... */
-               if (is_io_line(line_argv[0])) {
-                       add_ignore_opt_line(cmd, line_argc, line_argv);
-                       prev_was_oo = 0;
-                       prev_was_op = 0;
-                       continue;
-               }
-
-               /* handle OO_FOO:, OO:, OP: continuing on multiple lines */
-
-               if (prev_was_oo_def) {
-                       append_oo_definition_line(line_orig);
-                       continue;
-               }
-
-               if (prev_was_oo) {
-                       add_optional_opt_line(cmd, line_argc, line_argv);
-                       continue;
-               }
-
-               if (prev_was_op) {
-                       add_optional_pos_line(cmd, line_argc, line_argv);
-                       continue;
-               }
-       }
-
-       fclose(file);
-
-       /*
-        * Looks at all variants of each command name and figures out
-        * which options are common to all variants (for compact output)
-        */
-       factor_common_options();
-
-       /*
-        * Predefined string of options common to all commands
-        * (for compact output)
-        */
-       include_optional_opt_args(&lvm_all, "OO_USAGE_COMMON");
-
-       /*
-        * Print output.
-        */
-
-       if (!strcmp(outputformat, "struct"))
-               print_header_struct();
-
-       else if (!strcmp(outputformat, "count"))
-               print_header_count();
-
-       else if (!strcmp(outputformat, "ambiguous"))
-               print_ambiguous();
-
-       else if (!strcmp(outputformat, "man"))
-               print_man(man_command_name, include_man_primary, include_man_secondary);
-       else
-               print_help(argc, argv);
-
-       return 0;
-}
-
diff --git a/tools/ccmd-man.c b/tools/ccmd-man.c
deleted file mode 100644 (file)
index 34a9c38..0000000
+++ /dev/null
@@ -1,997 +0,0 @@
-#include <asm/types.h>
-#include <sys/types.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/wait.h>
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <stdarg.h>
-#include <limits.h>
-#include <unistd.h>
-#include <syslog.h>
-#include <sched.h>
-#include <dirent.h>
-#include <ctype.h>
-
-#include "ccmd.h"
-
-char *split_line(char *buf, int *argc, char **argv, char sep);
-struct cmd_name *find_command_name(const char *str);
-int is_lvm_all_opt(int opt);
-const char *lvt_enum_to_name(int lvt_enum);
-
-extern struct val_name val_names[VAL_COUNT + 1];
-extern struct opt_name opt_names[ARG_COUNT + 1];
-extern struct lvp_name lvp_names[LVP_COUNT + 1];
-extern struct lvt_name lvt_names[LVT_COUNT + 1];
-extern struct cmd_name cmd_names[MAX_CMD_NAMES];
-extern struct opt_name *opt_names_alpha[ARG_COUNT + 1];
-extern struct command lvm_all;
-
-static const char *cmd_name_desc(const char *name)
-{
-       int i;
-
-       for (i = 0; i < MAX_CMD_NAMES; i++) {
-               if (!cmd_names[i].name)
-                       break;
-               if (!strcmp(cmd_names[i].name, name))
-                       return cmd_names[i].desc;
-       }
-       return NULL;
-}
-
-static void print_val_man(const char *str)
-{
-       char *line;
-       char *line_argv[MAX_LINE_ARGC];
-       int line_argc;
-       int i;
-
-       if (!strcmp(str, "Number") ||
-           !strcmp(str, "String") ||
-           !strncmp(str, "VG", 2) ||
-           !strncmp(str, "LV", 2) ||
-           !strncmp(str, "PV", 2) ||
-           !strcmp(str, "Tag")) {
-               printf("\\fI%s\\fP", str);
-               return;
-       }
-
-       if (strstr(str, "Number[") || strstr(str, "]Number")) {
-               for (i = 0; i < strlen(str); i++) {
-                       if (str[i] == 'N')
-                               printf("\\fI");
-                       if (str[i] == 'r') {
-                               printf("%c", str[i]);
-                               printf("\\fP");
-                               continue;
-                       }
-                       printf("%c", str[i]);
-               }
-               return;
-       }
-
-       if (strstr(str, "|")) {
-               int len = strlen(str);
-               line = strdup(str);
-               split_line(line, &line_argc, line_argv, '|');
-               for (i = 0; i < line_argc; i++) {
-                       if (i) {
-                               printf("|");
-
-                               /* this is a hack to add a line break for
-                                  a long string of opt values */
-                               if ((len > 40) && (i >= (line_argc / 2) + 1)) {
-                                       printf("\n");
-                                       printf("       ");
-                                       len = 0;
-                               }
-                       }
-                       if (strstr(line_argv[i], "Number"))
-                               printf("\\fI%s\\fP", line_argv[i]);
-                       else
-                               printf("\\fB%s\\fP", line_argv[i]);
-               }
-               return;
-       }
-
-       printf("\\fB%s\\fP", str);
-}
-
-static void print_def_man(struct arg_def *def, int usage)
-{
-       int val_enum;
-       int lvt_enum;
-       int sep = 0;
-       int i;
-
-       for (val_enum = 0; val_enum < VAL_COUNT; val_enum++) {
-               if (def->val_bits & val_enum_to_bit(val_enum)) {
-
-                       if (val_enum == conststr_VAL) {
-                               printf("\\fB");
-                               printf("%s", def->str);
-                               printf("\\fP");
-                       }
-
-                       else if (val_enum == constnum_VAL) {
-                               printf("\\fB");
-                               printf("%llu", (unsigned long long)def->num);
-                               printf("\\fP");
-                       }
-
-                       else {
-                               if (sep) printf("|");
-
-                               if (!usage || !val_names[val_enum].usage) {
-                                       printf("\\fI");
-                                       printf("%s", val_names[val_enum].name);
-                                       printf("\\fP");
-                               } else {
-                                       print_val_man(val_names[val_enum].usage);
-                               }
-
-                               sep = 1;
-                       }
-
-                       if (val_enum == lv_VAL && def->lvt_bits) {
-                               printf("\\fI");
-                               for (lvt_enum = 1; lvt_enum < LVT_COUNT; lvt_enum++) {
-                                       if (lvt_bit_is_set(def->lvt_bits, lvt_enum))
-                                               printf("_%s", lvt_enum_to_name(lvt_enum));
-                               }
-                               printf("\\fP");
-                       }
-
-                       if ((val_enum == vg_VAL) && (def->flags & ARG_DEF_FLAG_NEW_VG)) {
-                               printf("\\fI");
-                               printf("_new");
-                               printf("\\fP");
-                       }
-                       if ((val_enum == lv_VAL) && (def->flags & ARG_DEF_FLAG_NEW_LV)) {
-                               printf("\\fI");
-                               printf("_new");
-                               printf("\\fP");
-                       }
-               }
-       }
-
-       if (def->flags & ARG_DEF_FLAG_MAY_REPEAT)
-               printf(" ...");
-}
-
-static char *man_long_opt_name(const char *cmdname, int opt_enum)
-{
-       static char long_opt_name[64];
-
-       memset(&long_opt_name, 0, sizeof(long_opt_name));
-
-       switch (opt_enum) {
-       case syncaction_ARG:
-               strncpy(long_opt_name, "--[raid]syncaction", 63);
-               break;
-       case writemostly_ARG:
-               strncpy(long_opt_name, "--[raid]writemostly", 63);
-               break;
-       case minrecoveryrate_ARG:
-               strncpy(long_opt_name, "--[raid]minrecoveryrate", 63);
-               break;
-       case maxrecoveryrate_ARG:
-               strncpy(long_opt_name, "--[raid]maxrecoveryrate", 63);
-               break;
-       case writebehind_ARG:
-               strncpy(long_opt_name, "--[raid]writebehind", 63);
-               break;
-       case vgmetadatacopies_ARG:
-               if (!strncmp(cmdname, "vg", 2))
-                       strncpy(long_opt_name, "--[vg]metadatacopies", 63);
-               else
-                       strncpy(long_opt_name, "--vgmetadatacopies", 63);
-               break;
-       case pvmetadatacopies_ARG:
-               if (!strncmp(cmdname, "pv", 2))
-                       strncpy(long_opt_name, "--[pv]metadatacopies", 63);
-               else
-                       strncpy(long_opt_name, "--pvmetadatacopies", 63);
-               break;
-       default:
-               strncpy(long_opt_name, opt_names[opt_enum].long_opt, 63);
-               break;
-       }
-
-       return long_opt_name;
-}
-
-void print_man_usage(struct command *cmd)
-{
-       struct cmd_name *cname;
-       int onereq = (cmd->cmd_flags & CMD_FLAG_ONE_REQUIRED_OPT) ? 1 : 0;
-       int i, sep, ro, rp, oo, op, opt_enum;
-
-       if (!(cname = find_command_name(cmd->name)))
-               return;
-
-       printf("\\fB%s\\fP", cmd->name);
-
-       if (!onereq)
-               goto ro_normal;
-
-       /*
-        * one required option in a set, print as:
-        * ( -a|--a,
-        *   -b|--b,
-        *      --c,
-        *      --d )
-        *
-        * First loop through ro prints those with short opts,
-        * and the second loop prints those without short opts.
-        */
-
-       if (cmd->ro_count) {
-               printf("\n");
-               printf(".RS 4\n");
-               printf("(");
-
-               sep = 0;
-
-               /* print required options with a short opt */
-               for (ro = 0; ro < cmd->ro_count; ro++) {
-                       opt_enum = cmd->required_opt_args[ro].opt;
-
-                       if (!opt_names[opt_enum].short_opt)
-                               continue;
-
-                       if (sep) {
-                               printf(",");
-                               printf("\n.br\n");
-                               printf(" ");
-                       }
-
-                       if (opt_names[opt_enum].short_opt) {
-                               printf(" \\fB-%c\\fP|\\fB%s\\fP",
-                                      opt_names[opt_enum].short_opt,
-                                      man_long_opt_name(cmd->name, opt_enum));
-                       } else {
-                               printf("   ");
-                               printf(" \\fB%s\\fP", man_long_opt_name(cmd->name, opt_enum));
-                       }
-
-                       if (cmd->required_opt_args[ro].def.val_bits) {
-                               printf(" ");
-                               print_def_man(&cmd->required_opt_args[ro].def, 1);
-                       }
-
-                       sep = 1;
-               }
-
-               /* print required options without a short opt */
-               for (ro = 0; ro < cmd->ro_count; ro++) {
-                       opt_enum = cmd->required_opt_args[ro].opt;
-
-                       if (opt_names[opt_enum].short_opt)
-                               continue;
-
-                       if (sep) {
-                               printf(",");
-                               printf("\n.br\n");
-                               printf(" ");
-                       }
-
-                       printf("   ");
-                       printf(" \\fB%s\\fP", man_long_opt_name(cmd->name, opt_enum));
-
-                       if (cmd->required_opt_args[ro].def.val_bits) {
-                               printf(" ");
-                               print_def_man(&cmd->required_opt_args[ro].def, 1);
-                       }
-
-                       sep = 1;
-               }
-
-               printf(" )\n");
-               printf(".RE\n");
-       }
-
-       /* print required position args on a new line after the onereq set */
-       if (cmd->rp_count) {
-               printf(".RS 4\n");
-               for (rp = 0; rp < cmd->rp_count; rp++) {
-                       if (cmd->required_pos_args[rp].def.val_bits) {
-                               printf(" ");
-                               print_def_man(&cmd->required_pos_args[rp].def, 1);
-                       }
-               }
-
-               printf("\n");
-               printf(".RE\n");
-       } else {
-               /* printf("\n"); */
-       }
-
-       printf(".br\n");
-       goto oo_count;
-
- ro_normal:
-
-       /*
-        * all are required options, print as:
-        * -a|--aaa <val> -b|--bbb <val>
-        */
-
-       if (cmd->ro_count) {
-               for (ro = 0; ro < cmd->ro_count; ro++) {
-                       opt_enum = cmd->required_opt_args[ro].opt;
-
-                       if (opt_names[opt_enum].short_opt) {
-                               printf(" \\fB-%c\\fP|\\fB%s\\fP",
-                                      opt_names[opt_enum].short_opt,
-                                      man_long_opt_name(cmd->name, opt_enum));
-                       } else {
-                               printf(" \\fB%s\\fP", opt_names[cmd->required_opt_args[ro].opt].long_opt);
-                       }
-
-                       if (cmd->required_opt_args[ro].def.val_bits) {
-                               printf(" ");
-                               print_def_man(&cmd->required_opt_args[ro].def, 1);
-                       }
-               }
-       }
-
-       /* print required position args on the same line as the required options */
-       if (cmd->rp_count) {
-               for (rp = 0; rp < cmd->rp_count; rp++) {
-                       if (cmd->required_pos_args[rp].def.val_bits) {
-                               printf(" ");
-                               print_def_man(&cmd->required_pos_args[rp].def, 1);
-                       }
-               }
-
-               printf("\n");
-       } else {
-               printf("\n");
-       }
-
-       printf(".br\n");
-
- oo_count:
-       if (!cmd->oo_count)
-               goto op_count;
-
-       sep = 0;
-
-       if (cmd->oo_count) {
-               printf(".RS 4\n");
-               printf("[");
-
-               /* print optional options with short opts */
-
-               for (oo = 0; oo < cmd->oo_count; oo++) {
-                       opt_enum = cmd->optional_opt_args[oo].opt;
-
-                       if (!opt_names[opt_enum].short_opt)
-                               continue;
-
-                       /*
-                        * Skip common opts which are in the usage_common string.
-                        * The common opts are those in lvm_all and in
-                        * cname->common_options.
-                        */
-
-                       if (is_lvm_all_opt(opt_enum))
-                               continue;
-
-                       if ((cname->variants > 1) && cname->common_options[opt_enum])
-                               continue;
-
-                       if (sep) {
-                               printf(",");
-                               printf("\n.br\n");
-                               printf(" ");
-                       }
-
-                       printf(" \\fB-%c\\fP|\\fB%s\\fP",
-                               opt_names[opt_enum].short_opt,
-                               man_long_opt_name(cmd->name, opt_enum));
-
-                       if (cmd->optional_opt_args[oo].def.val_bits) {
-                               printf(" ");
-                               print_def_man(&cmd->optional_opt_args[oo].def, 1);
-                       }
-                       sep = 1;
-               }
-
-               /* print optional options without short opts */
-
-               for (oo = 0; oo < cmd->oo_count; oo++) {
-                       opt_enum = cmd->optional_opt_args[oo].opt;
-
-                       if (opt_names[opt_enum].short_opt)
-                               continue;
-
-                       /*
-                        * Skip common opts which are in the usage_common string.
-                        * The common opts are those in lvm_all and in
-                        * cname->common_options.
-                        */
-
-                       if (is_lvm_all_opt(opt_enum))
-                               continue;
-
-                       if ((cname->variants > 1) && cname->common_options[opt_enum])
-                               continue;
-
-                       if (sep) {
-                               printf(",");
-                               printf("\n.br\n");
-                               printf(" ");
-                       }
-
-                       /* space alignment without short opt */
-                       printf("   ");
-
-                       printf(" \\fB%s\\fP", man_long_opt_name(cmd->name, opt_enum));
-
-                       if (cmd->optional_opt_args[oo].def.val_bits) {
-                               printf(" ");
-                               print_def_man(&cmd->optional_opt_args[oo].def, 1);
-                       }
-                       sep = 1;
-               }
-
-               if (sep) {
-                       printf(",");
-                       printf("\n.br\n");
-                       printf(" ");
-                       /* space alignment without short opt */
-                       printf("   ");
-               }
-               printf(" COMMON_OPTIONS");
-               printf(" ]\n");
-               printf(".RE\n");
-               printf(".br\n");
-       }
-
- op_count:
-       if (!cmd->op_count)
-               goto done;
-
-       printf(".RS 4\n");
-       printf("[");
-
-       if (cmd->op_count) {
-               for (op = 0; op < cmd->op_count; op++) {
-                       if (cmd->optional_pos_args[op].def.val_bits) {
-                               printf(" ");
-                               print_def_man(&cmd->optional_pos_args[op].def, 1);
-                       }
-               }
-       }
-
-       printf(" ]\n");
-       printf(".RE\n");
-
- done:
-       printf("\n");
-}
-
-/*
- * common options listed in the usage section.
- *
- * For commands with only one variant, this is only
- * the options which are common to all lvm commands
- * (in lvm_all, see is_lvm_all_opt).
- *
- * For commands with more than one variant, this
- * is the set of options common to all variants
- * (in cname->common_options), (which obviously
- * includes the options common to all lvm commands.)
- *
- * List ordering:
- * options with short+long names, alphabetically,
- * then options with only long names, alphabetically
- */
-
-void print_man_usage_common(struct command *cmd)
-{
-       struct cmd_name *cname;
-       int i, sep, ro, rp, oo, op, opt_enum;
-
-       if (!(cname = find_command_name(cmd->name)))
-               return;
-
-       sep = 0;
-
-       printf(".RS 4\n");
-       printf("[");
-
-       /* print those with short opts */
-       for (i = 0; i < ARG_COUNT; i++) {
-               opt_enum = opt_names_alpha[i]->opt_enum;
-
-               if (!cname->common_options[opt_enum])
-                       continue;
-
-               if (!opt_names[opt_enum].short_opt)
-                       continue;
-
-               if ((cname->variants < 2) && !is_lvm_all_opt(opt_enum))
-                       continue;
-
-               if (sep) {
-                       printf(",");
-                       printf("\n.br\n");
-                       printf(" ");
-               }
-
-               for (oo = 0; oo < cmd->oo_count; oo++) {
-                       if (cmd->optional_opt_args[oo].opt != opt_enum)
-                               continue;
-
-                       printf(" \\fB-%c\\fP|\\fB%s\\fP",
-                               opt_names[opt_enum].short_opt,
-                               man_long_opt_name(cmd->name, opt_enum));
-
-                       if (cmd->optional_opt_args[oo].def.val_bits) {
-                               printf(" ");
-                               print_def_man(&cmd->optional_opt_args[oo].def, 1);
-                       }
-                       sep = 1;
-                       break;
-               }
-
-       }
-
-       /* print those without short opts */
-       for (i = 0; i < ARG_COUNT; i++) {
-               opt_enum = opt_names_alpha[i]->opt_enum;
-
-               if (!cname->common_options[opt_enum])
-                       continue;
-
-               if (opt_names[opt_enum].short_opt)
-                       continue;
-
-               if ((cname->variants < 2) && !is_lvm_all_opt(opt_enum))
-                       continue;
-
-               if (sep) {
-                       printf(",");
-                       printf("\n.br\n");
-                       printf(" ");
-               }
-
-               for (oo = 0; oo < cmd->oo_count; oo++) {
-                       if (cmd->optional_opt_args[oo].opt != opt_enum)
-                               continue;
-
-                       /* space alignment without short opt */
-                       printf("   ");
-
-                       printf(" \\fB%s\\fP", man_long_opt_name(cmd->name, opt_enum));
-
-                       if (cmd->optional_opt_args[oo].def.val_bits) {
-                               printf(" ");
-                               print_def_man(&cmd->optional_opt_args[oo].def, 1);
-                       }
-                       sep = 1;
-                       break;
-               }
-       }
-
-       printf(" ]\n");
-       return;
-}
-
-/*
- * Format of description, when different command names have
- * different descriptions:
- *
- * "#cmdname1"
- * "text foo goes here"
- * "a second line of text."
- * "#cmdname2"
- * "text bar goes here"
- * "another line of text."
- *
- * When called for cmdname2, this function should just print:
- *
- * "text bar goes here"
- * "another line of text."
- */
-
-static void print_man_option_desc(struct cmd_name *cname, int opt_enum)
-{
-       const char *desc = opt_names[opt_enum].desc;
-       char buf[DESC_LINE];
-       int started_cname = 0;
-       int line_count = 0;
-       int di, bi = 0;
-
-       if (desc[0] != '#') {
-               printf("%s", desc);
-               return;
-       }
-
-       for (di = 0; di < strlen(desc); di++) {
-               buf[bi++] = desc[di];
-
-               if (bi == DESC_LINE) {
-                       printf("print_man_option_desc line too long\n");
-                       return;
-               }
-
-               if (buf[bi-1] != '\n')
-                       continue;
-
-               if (buf[0] != '#') {
-                       if (started_cname) {
-                               printf("%s", buf);
-                               line_count++;
-                       }
-
-                       memset(buf, 0, sizeof(buf));
-                       bi = 0;
-                       continue;
-               }
-
-               /* Line starting with #cmdname */
-
-               /*
-                * Must be starting a new command name.
-                * If no lines have been printed, multiple command names
-                * are using the same text. If lines have been printed,
-                * then the start of a new command name means the end
-                * of text for the current command name.
-                */
-               if (line_count && started_cname)
-                       return;
-
-               if (!strncmp(buf + 1, cname->name, strlen(cname->name))) {
-                       /* The start of our command name. */
-                       started_cname = 1;
-                       memset(buf, 0, sizeof(buf));
-                       bi = 0;
-               } else {
-                       /* The start of another command name. */
-                       memset(buf, 0, sizeof(buf));
-                       bi = 0;
-               }
-       }
-
-       if (bi && started_cname)
-               printf("%s", buf);
-}
-
-/*
- * Print a list of all options names for a given
- * command name, listed by:
- * options with short+long names, alphabetically,
- * then options with only long names, alphabetically
- */
-
-void print_man_all_options_list(struct cmd_name *cname)
-{
-       int opt_enum, val_enum;
-       int sep = 0;
-       int i;
-
-       /* print those with both short and long opts */
-       for (i = 0; i < ARG_COUNT; i++) {
-               opt_enum = opt_names_alpha[i]->opt_enum;
-
-
-               if (!cname->all_options[opt_enum])
-                       continue;
-
-               if (!opt_names[opt_enum].short_opt)
-                       continue;
-
-               if (sep)
-                       printf("\n.br\n");
-
-               printf(" \\fB-%c\\fP|\\fB%s\\fP",
-                       opt_names[opt_enum].short_opt,
-                       man_long_opt_name(cname->name, opt_enum));
-
-               val_enum = opt_names[opt_enum].val_enum;
-
-               if (!val_names[val_enum].fn) {
-                       /* takes no arg */
-               } else if (!val_names[val_enum].usage) {
-                       printf(" ");
-                       printf("\\fI");
-                       printf("%s", val_names[val_enum].name);
-                       printf("\\fP");
-               } else {
-                       printf(" ");
-                       print_val_man(val_names[val_enum].usage);
-               }
-
-               sep = 1;
-       }
-
-       /* print those without short opts */
-       for (i = 0; i < ARG_COUNT; i++) {
-               opt_enum = opt_names_alpha[i]->opt_enum;
-
-               if (!cname->all_options[opt_enum])
-                       continue;
-
-               if (opt_names[opt_enum].short_opt)
-                       continue;
-
-               if (sep)
-                       printf("\n.br\n");
-
-               /* space alignment without short opt */
-               printf("   ");
-
-               printf(" \\fB%s\\fP", man_long_opt_name(cname->name, opt_enum));
-
-               val_enum = opt_names[opt_enum].val_enum;
-
-               if (!val_names[val_enum].fn) {
-                       /* takes no arg */
-               } else if (!val_names[val_enum].usage) {
-                       printf(" ");
-                       printf("\\fI");
-                       printf("%s", val_names[val_enum].name);
-                       printf("\\fP");
-               } else {
-                       printf(" ");
-                       print_val_man(val_names[val_enum].usage);
-               }
-
-               sep = 1;
-       }
-}
-
-/*
- * All options used for a given command name, along with descriptions.
- * listed in order of:
- * 1. options that are not common to all lvm commands, alphabetically
- * 2. options common to all lvm commands, alphabetically
- */
-
-void print_man_all_options_desc(struct cmd_name *cname)
-{
-       int opt_enum, val_enum;
-       int print_common = 0;
-       int sep = 0;
-       int i;
-
- again:
-       /*
-        * Loop 1: print options that are not common to all lvm commands.
-        * Loop 2: print options common to all lvm commands (lvm_all)
-        */
-
-       for (i = 0; i < ARG_COUNT; i++) {
-               opt_enum = opt_names_alpha[i]->opt_enum;
-
-               if (!cname->all_options[opt_enum])
-                       continue;
-
-               if (!print_common && is_lvm_all_opt(opt_enum))
-                       continue;
-
-               if (print_common && !is_lvm_all_opt(opt_enum))
-                       continue;
-
-               if (sep)
-                       printf("\n.br\n");
-
-               printf("\n.TP\n");
-
-               if (opt_names[opt_enum].short_opt) {
-                       printf("\\fB-%c\\fP|\\fB%s\\fP",
-                              opt_names[opt_enum].short_opt,
-                              man_long_opt_name(cname->name, opt_enum));
-               } else {
-                       printf("\\fB%s\\fP", man_long_opt_name(cname->name, opt_enum));
-               }
-
-               val_enum = opt_names[opt_enum].val_enum;
-
-               if (!val_names[val_enum].fn) {
-                       /* takes no arg */
-               } else if (!val_names[val_enum].usage) {
-                       printf(" ");
-                       printf("\\fI");
-                       printf("%s", val_names[val_enum].name);
-                       printf("\\fP");
-               } else {
-                       printf(" ");
-                       print_val_man(val_names[val_enum].usage);
-               }
-
-               if (opt_names[opt_enum].desc) {
-                       printf("\n");
-                       printf(".br\n");
-                       print_man_option_desc(cname, opt_enum);
-               }
-
-               sep = 1;
-       }
-
-       if (!print_common) {
-               print_common = 1;
-               goto again;
-       }
-}
-
-void print_desc_man(const char *desc)
-{
-       char buf[DESC_LINE] = {0};
-       int di = 0;
-       int bi = 0;
-
-       for (di = 0; di < strlen(desc); di++) {
-               if (desc[di] == '\0')
-                       break;
-               if (desc[di] == '\n')
-                       continue;
-
-               if (!strncmp(&desc[di], "DESC:", 5)) {
-                       if (bi) {
-                               printf("%s\n", buf);
-                               printf(".br\n");
-                               memset(buf, 0, sizeof(buf));
-                               bi = 0;
-                       }
-                       di += 5;
-                       continue;
-               }
-
-               if (!bi && desc[di] == ' ')
-                       continue;
-
-               buf[bi++] = desc[di];
-
-               if (bi == (DESC_LINE - 1))
-                       break;
-       }
-
-       if (bi) {
-               printf("%s\n", buf);
-               printf(".br\n");
-       }
-}
-
-static char *upper_command_name(char *str)
-{
-       static char str_upper[32];
-       int i = 0;
-
-       while (*str) {
-               str_upper[i++] = toupper(*str);
-               str++;
-       }
-       str_upper[i] = '\0';
-       return str_upper;
-}
-
-void print_man(char *man_command_name, int include_primary, int include_secondary)
-{
-       struct cmd_name *cname;
-       struct command *cmd, *prev_cmd = NULL;
-       const char *desc;
-       int i, j, ro, rp, oo, op;
-
-       printf(".TH %s 8 \"LVM TOOLS #VERSION#\" \"Sistina Software UK\"\n",
-               man_command_name ? upper_command_name(man_command_name) : "LVM_COMMANDS");
-
-       for (i = 0; i < cmd_count; i++) {
-
-               cmd = &cmd_array[i];
-
-               if (prev_cmd && strcmp(prev_cmd->name, cmd->name)) {
-                       printf("Common options:\n");
-                       printf(".\n");
-                       print_man_usage_common(prev_cmd);
-
-                       printf("\n");
-                       printf(".SH OPTIONS\n");
-                       printf(".br\n");
-                       print_man_all_options_desc(cname);
-
-                       prev_cmd = NULL;
-               }
-
-               if ((cmd->cmd_flags & CMD_FLAG_SECONDARY_SYNTAX) && !include_secondary)
-                       continue;
-
-               if (!(cmd->cmd_flags & CMD_FLAG_SECONDARY_SYNTAX) && !include_primary)
-                       continue;
-
-               if (man_command_name && strcmp(man_command_name, cmd->name))
-                       continue;
-
-               if (!prev_cmd || strcmp(prev_cmd->name, cmd->name)) {
-                       printf(".SH NAME\n");
-                       printf(".\n");
-                       if ((desc = cmd_name_desc(cmd->name)))
-                               printf("%s \\- %s\n", cmd->name, desc);
-                       else
-                               printf("%s\n", cmd->name);
-                       printf(".br\n");
-                       printf(".P\n");
-                       printf(".\n");
-                       printf(".SH SYNOPSIS\n");
-                       printf(".br\n");
-                       printf(".P\n");
-                       printf(".\n");
-                       prev_cmd = cmd;
-
-                       if (!(cname = find_command_name(cmd->name)))
-                               return;
-
-                       if (cname->variant_has_ro && cname->variant_has_rp)
-                               printf("\\fB%s\\fP \\fIrequired_option_args\\fP \\fIrequired_position_args\\fP\n", cmd->name);
-                       else if (cname->variant_has_ro && !cname->variant_has_rp)
-                               printf("\\fB%s\\fP \\fIrequired_option_args\\fP\n", cmd->name);
-                       else if (!cname->variant_has_ro && cname->variant_has_rp)
-                               printf("\\fB%s\\fP \\fIrequired_position_args\\fP\n", cmd->name);
-                       else if (!cname->variant_has_ro && !cname->variant_has_rp)
-                               printf("\\fB%s\\fP\n", cmd->name);
-
-                       printf(".br\n");
-
-                       if (cname->variant_has_oo) {
-                               printf("    [ \\fIoptional_option_args\\fP ]\n");
-                               printf(".br\n");
-                       }
-
-                       if (cname->variant_has_op) {
-                               printf("    [ \\fIoptional_position_args\\fP ]\n");
-                               printf(".br\n");
-                       }
-
-                       printf(".P\n");
-                       printf("\n");
-
-                       /* listing them all when there's only 1 or 2 is just repetative */
-                       if (cname->variants > 2) {
-                               printf(".P\n");
-                               print_man_all_options_list(cname);
-                               printf("\n");
-                               printf(".P\n");
-                               printf("\n");
-                       }
-
-                       printf(".SH USAGE\n");
-                       printf(".br\n");
-                       printf(".P\n");
-                       printf(".\n");
-               }
-
-               if (cmd->desc) {
-                       print_desc_man(cmd->desc);
-                       printf(".P\n");
-               }
-
-               print_man_usage(cmd);
-
-               if (i == (cmd_count - 1)) {
-                       printf("Common options:\n");
-                       printf(".\n");
-                       print_man_usage_common(cmd);
-
-                       printf("\n");
-                       printf(".SH OPTIONS\n");
-                       printf(".br\n");
-                       print_man_all_options_desc(cname);
-
-               }
-
-               printf("\n");
-               continue;
-       }
-}
-
diff --git a/tools/ccmd-util.c b/tools/ccmd-util.c
deleted file mode 100644 (file)
index 15b2f96..0000000
+++ /dev/null
@@ -1,936 +0,0 @@
-#include <asm/types.h>
-#include <sys/types.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <sys/wait.h>
-#include <stdio.h>
-#include <errno.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <stdarg.h>
-#include <limits.h>
-#include <unistd.h>
-#include <syslog.h>
-#include <sched.h>
-#include <dirent.h>
-#include <ctype.h>
-
-#include "ccmd.h"
-
-struct cmd_name *find_command_name(const char *str);
-int is_lvm_all_opt(int opt);
-
-extern struct val_name val_names[VAL_COUNT + 1];
-extern struct opt_name opt_names[ARG_COUNT + 1];
-extern struct lvp_name lvp_names[LVP_COUNT + 1];
-extern struct lvt_name lvt_names[LVT_COUNT + 1];
-extern struct cmd_name cmd_names[MAX_CMD_NAMES];
-extern struct command lvm_all;
-
-/*
- * modifies buf, replacing the sep characters with \0
- * argv pointers point to positions in buf
- */
-
-char *split_line(char *buf, int *argc, char **argv, char sep)
-{
-       char *p = buf, *rp = NULL;
-       int i;
-
-       argv[0] = p;
-
-       for (i = 1; i < MAX_LINE_ARGC; i++) {
-               p = strchr(buf, sep);
-               if (!p)
-                       break;
-               *p = '\0';
-
-               argv[i] = p + 1;
-               buf = p + 1;
-       }
-       *argc = i;
-
-       /* we ended by hitting \0, return the point following that */
-       if (!rp)
-               rp = strchr(buf, '\0') + 1;
-
-       return rp;
-}
-
-/* convert value string, e.g. Number, to foo_VAL enum */
-
-int val_str_to_num(char *str)
-{
-       char name[32] = { 0 };
-       char *new;
-       int i;
-
-       /* compare the name before any suffix like _new or _<lvtype> */
-
-       strncpy(name, str, 31);
-       if ((new = strstr(name, "_")))
-               *new = '\0';
-
-       for (i = 0; i < VAL_COUNT; i++) {
-               if (!val_names[i].name)
-                       break;
-               if (!strncmp(name, val_names[i].name, strlen(val_names[i].name)))
-                       return val_names[i].val_enum;
-       }
-
-       return 0;
-}
-
-/* convert "--option" to foo_ARG enum */
-
-int opt_str_to_num(char *str)
-{
-       char long_name[32];
-       char *p;
-       int i;
-
-       /*
-        * --foo_long means there are two args entries
-        * for --foo, one with a short option and one
-        * without, and we want the one without the
-        * short option.
-        */
-       if (strstr(str, "_long")) {
-               strcpy(long_name, str);
-               p = strstr(long_name, "_long");
-               *p = '\0';
-
-               for (i = 0; i < ARG_COUNT; i++) {
-                       if (!opt_names[i].long_opt)
-                               continue;
-                       /* skip anything with a short opt */
-                       if (opt_names[i].short_opt)
-                               continue;
-                       if (!strcmp(opt_names[i].long_opt, long_name))
-                               return opt_names[i].opt_enum;
-               }
-
-               printf("Unknown opt str: %s %s\n", str, long_name);
-               exit(1);
-       }
-
-       for (i = 0; i < ARG_COUNT; i++) {
-               if (!opt_names[i].long_opt)
-                       continue;
-               /* These are only selected using --foo_long */
-               if (strstr(opt_names[i].name, "_long_ARG"))
-                       continue;
-               if (!strcmp(opt_names[i].long_opt, str))
-                       return opt_names[i].opt_enum;
-       }
-
-       printf("Unknown opt str: \"%s\"\n", str);
-       exit(1);
-}
-
-/* "lv_is_prop" to is_prop_LVP */
-
-int lvp_name_to_enum(char *str)
-{
-       int i;
-
-       for (i = 1; i < LVP_COUNT; i++) {
-               if (!strcmp(str, lvp_names[i].name))
-                       return lvp_names[i].lvp_enum;
-       }
-       printf("unknown lv property %s\n", str);
-       exit(1);
-}
-
-/* type_LVT to "type" */
-
-const char *lvt_enum_to_name(int lvt_enum)
-{
-       return lvt_names[lvt_enum].name;
-}
-
-/* "type" to type_LVT */
-
-static int lvt_name_to_enum(char *str)
-{
-       int i;
-
-       for (i = 1; i < LVT_COUNT; i++) {
-               if (!strcmp(str, lvt_names[i].name))
-                       return lvt_names[i].lvt_enum;
-       }
-       printf("unknown lv type %s\n", str);
-       exit(1);
-}
-
-/* LV_<type> to <type>_LVT */
-
-int lv_to_enum(char *name)
-{
-       return lvt_name_to_enum(name + 3);
-}
-
-/*
- * LV_<type1>_<type2> to lvt_bits
- *
- * type1 to lvt_enum
- * lvt_bits |= lvt_enum_to_bit(lvt_enum)
- * type2 to lvt_enum
- * lvt_bits |= lvt_enum_to_bit(lvt_enum)
- */
-
-uint64_t lv_to_bits(char *name)
-{
-       char buf[64];
-       char *argv[MAX_LINE_ARGC];
-       uint64_t lvt_bits = 0;
-       int lvt_enum;
-       int argc;
-       int i;
-
-       strcpy(buf, name);
-
-       split_line(buf, &argc, argv, '_');
-
-       /* 0 is "LV" */
-       for (i = 1; i < argc; i++) {
-               if (!strcmp(argv[i], "new"))
-                       continue;
-               lvt_enum = lvt_name_to_enum(argv[i]);
-               lvt_bits |= lvt_enum_to_bit(lvt_enum);
-       }
-
-       return lvt_bits;
-}
-
-/* output for struct/count */
-
-static char *val_bits_to_str(uint64_t val_bits)
-{
-       static char buf[1024];
-       int i;
-       int or = 0;
-
-       memset(buf, 0, sizeof(buf));
-
-       for (i = 0; i < VAL_COUNT; i++) {
-               if (val_bits & val_enum_to_bit(i)) {
-                       if (or) strcat(buf, " | ");
-                       strcat(buf, "val_enum_to_bit(");
-                       strcat(buf, val_names[i].enum_name);
-                       strcat(buf, ")");
-                       or = 1;
-               }
-       }
-
-       return buf;
-}
-
-/*
- * When bits for foo_LVP and bar_LVP are both set in bits, print:
- * lvp_enum_to_bit(foo_LVP) | lvp_enum_to_bit(bar_LVP)
- */
-
-static char *lvp_bits_to_str(uint64_t bits)
-{
-       static char lvp_buf[1024];
-       int i;
-       int or = 0;
-
-       memset(lvp_buf, 0, sizeof(lvp_buf));
-
-       for (i = 0; i < LVP_COUNT; i++) {
-               if (bits & lvp_enum_to_bit(i)) {
-                       if (or) strcat(lvp_buf, " | ");
-                       strcat(lvp_buf, "lvp_enum_to_bit(");
-                       strcat(lvp_buf, lvp_names[i].enum_name);
-                       strcat(lvp_buf, ")");
-                       or = 1;
-               }
-       }
-
-       return lvp_buf;
-}
-
-/*
- * When bits for foo_LVT and bar_LVT are both set in bits, print:
- * lvt_enum_to_bit(foo_LVT) | lvt_enum_to_bit(bar_LVT)
- */
-
-static char *lvt_bits_to_str(uint64_t bits)
-{
-       static char lvt_buf[1024];
-       int i;
-       int or = 0;
-
-       memset(lvt_buf, 0, sizeof(lvt_buf));
-
-       for (i = 1; i < LVT_COUNT; i++) {
-               if (bits & lvt_enum_to_bit(i)) {
-                       if (or) strcat(lvt_buf, " | ");
-                       strcat(lvt_buf, "lvt_enum_to_bit(");
-                       strcat(lvt_buf, lvt_names[i].enum_name);
-                       strcat(lvt_buf, ")");
-                       or = 1;
-               }
-       }
-
-       return lvt_buf;
-}
-
-static void print_def(struct arg_def *def, int usage)
-{
-       int val_enum;
-       int lvt_enum;
-       int sep = 0;
-       int i;
-
-       for (val_enum = 0; val_enum < VAL_COUNT; val_enum++) {
-               if (def->val_bits & val_enum_to_bit(val_enum)) {
-
-                       if (val_enum == conststr_VAL)
-                               printf("%s", def->str);
-
-                       else if (val_enum == constnum_VAL)
-                               printf("%llu", (unsigned long long)def->num);
-
-                       else {
-                               if (sep) printf("|");
-
-                               if (!usage || !val_names[val_enum].usage)
-                                       printf("%s", val_names[val_enum].name);
-                               else
-                                       printf("%s", val_names[val_enum].usage);
-
-                               sep = 1;
-                       }
-
-                       if (val_enum == lv_VAL && def->lvt_bits) {
-                               for (lvt_enum = 1; lvt_enum < LVT_COUNT; lvt_enum++) {
-                                       if (lvt_bit_is_set(def->lvt_bits, lvt_enum))
-                                               printf("_%s", lvt_enum_to_name(lvt_enum));
-                               }
-                       }
-
-                       if ((val_enum == vg_VAL) && (def->flags & ARG_DEF_FLAG_NEW_VG))
-                               printf("_new");
-                       if ((val_enum == lv_VAL) && (def->flags & ARG_DEF_FLAG_NEW_LV))
-                               printf("_new");
-               }
-       }
-
-       if (def->flags & ARG_DEF_FLAG_MAY_REPEAT)
-               printf(" ...");
-}
-
-static int opt_arg_matches(struct opt_arg *oa1, struct opt_arg *oa2)
-{
-       if (oa1->opt != oa2->opt)
-               return 0;
-
-       /* FIXME: some cases may need more specific val_bits checks */
-       if (oa1->def.val_bits != oa2->def.val_bits)
-               return 0;
-
-       if (oa1->def.str && oa2->def.str && strcmp(oa1->def.str, oa2->def.str))
-               return 0;
-
-       if (oa1->def.num != oa2->def.num)
-               return 0;
-
-       /*
-        * Do NOT compare lv_types because we are checking if two
-        * command lines are ambiguous before the LV type is known.
-        */
-
-       return 1;
-}
-
-static int pos_arg_matches(struct pos_arg *pa1, struct pos_arg *pa2)
-{
-       if (pa1->pos != pa2->pos)
-               return 0;
-
-       /* FIXME: some cases may need more specific val_bits checks */
-       if (pa1->def.val_bits != pa2->def.val_bits)
-               return 0;
-
-       if (pa1->def.str && pa2->def.str && strcmp(pa1->def.str, pa2->def.str))
-               return 0;
-
-       if (pa1->def.num != pa2->def.num)
-               return 0;
-
-       /*
-        * Do NOT compare lv_types because we are checking if two
-        * command lines are ambiguous before the LV type is known.
-        */
-
-       return 1;
-}
-
-static const char *opt_to_enum_str(int opt)
-{
-       return opt_names[opt].name;
-}
-
-static char *flags_to_str(int flags)
-{
-       static char buf_flags[32];
-
-       memset(buf_flags, 0, sizeof(buf_flags));
-
-       if (flags & ARG_DEF_FLAG_MAY_REPEAT) {
-               if (buf_flags[0])
-                       strcat(buf_flags, " | ");
-               strcat(buf_flags, "ARG_DEF_FLAG_MAY_REPEAT");
-       }
-       if (flags & ARG_DEF_FLAG_NEW_VG) {
-               if (buf_flags[0])
-                       strcat(buf_flags, " | ");
-               strcat(buf_flags, "ARG_DEF_FLAG_NEW_VG");
-       }
-       if (flags & ARG_DEF_FLAG_NEW_LV) {
-               if (buf_flags[0])
-                       strcat(buf_flags, " | ");
-               strcat(buf_flags, "ARG_DEF_FLAG_NEW_LV");
-       }
-
-       return buf_flags;
-}
-
-static char *rule_to_define_str(int rule_type)
-{
-       switch (rule_type) {
-       case RULE_INVALID:
-               return "RULE_INVALID";
-       case RULE_REQUIRE:
-               return "RULE_REQUIRE";
-       }
-}
-
-static char *cmd_flags_to_str(uint32_t flags)
-{
-       static char buf_cmd_flags[32];
-
-       memset(buf_cmd_flags, 0, sizeof(buf_cmd_flags));
-
-       if (flags & CMD_FLAG_SECONDARY_SYNTAX) {
-               if (buf_cmd_flags[0])
-                       strcat(buf_cmd_flags, " | ");
-               strcat(buf_cmd_flags, "CMD_FLAG_SECONDARY_SYNTAX");
-       }
-       if (flags & CMD_FLAG_ONE_REQUIRED_OPT) {
-               if (buf_cmd_flags[0])
-                       strcat(buf_cmd_flags, " | ");
-               strcat(buf_cmd_flags, "CMD_FLAG_ONE_REQUIRED_OPT");
-       }
-
-       return buf_cmd_flags;
-}
-
-static void print_usage_common(struct command *cmd)
-{
-       struct cmd_name *cname;
-       int i, sep, ro, rp, oo, op, opt_enum;
-
-       if (!(cname = find_command_name(cmd->name)))
-               return;
-
-       sep = 0;
-
-       /*
-        * when there's more than one variant, options that
-        * are common to all commands with a common name.
-        */
-
-       if (cname->variants < 2)
-               goto all;
-
-       for (opt_enum = 0; opt_enum < ARG_COUNT; opt_enum++) {
-               if (!cname->common_options[opt_enum])
-                       continue;
-
-               if (is_lvm_all_opt(opt_enum))
-                       continue;
-
-               if (!sep) {
-                       printf("\n");
-                       printf("\" [");
-               } else {
-                       printf(",");
-               }
-
-               for (oo = 0; oo < cmd->oo_count; oo++) {
-                       if (cmd->optional_opt_args[oo].opt != opt_enum)
-                               continue;
-
-                       printf(" %s", opt_names[opt_enum].long_opt);
-                       if (cmd->optional_opt_args[oo].def.val_bits) {
-                               printf(" ");
-                               print_def(&cmd->optional_opt_args[oo].def, 1);
-                       }
-                       sep = 1;
-                       break;
-               }
-       }
-
- all:
-       /* options that are common to all lvm commands */
-
-       for (oo = 0; oo < lvm_all.oo_count; oo++) {
-               opt_enum = lvm_all.optional_opt_args[oo].opt;
-
-               if (!sep) {
-                       printf("\n");
-                       printf("\" [");
-               } else {
-                       printf(",");
-               }
-
-               printf(" %s", opt_names[opt_enum].long_opt);
-               if (lvm_all.optional_opt_args[oo].def.val_bits) {
-                       printf(" ");
-                       print_def(&lvm_all.optional_opt_args[oo].def, 1);
-               }
-               sep = 1;
-       }
-
-       printf(" ]\"");
-       printf(";\n");
-}
-
-static void print_usage(struct command *cmd)
-{
-       struct cmd_name *cname;
-       int onereq = (cmd->cmd_flags & CMD_FLAG_ONE_REQUIRED_OPT) ? 1 : 0;
-       int i, sep, ro, rp, oo, op, opt_enum;
-
-       if (!(cname = find_command_name(cmd->name)))
-               return;
-
-       printf("\"%s", cmd->name);
-
-       if (cmd->ro_count) {
-               if (onereq)
-                       printf(" (");
-               for (ro = 0; ro < cmd->ro_count; ro++) {
-                       if (ro && onereq)
-                               printf(",");
-                       printf(" %s", opt_names[cmd->required_opt_args[ro].opt].long_opt);
-
-                       if (cmd->required_opt_args[ro].def.val_bits) {
-                               printf(" ");
-                               print_def(&cmd->required_opt_args[ro].def, 1);
-                       }
-               }
-               if (onereq)
-                       printf(" )");
-       }
-
-       if (cmd->rp_count) {
-               for (rp = 0; rp < cmd->rp_count; rp++) {
-                       if (cmd->required_pos_args[rp].def.val_bits) {
-                               printf(" ");
-                               print_def(&cmd->required_pos_args[rp].def, 1);
-                       }
-               }
-       }
-
-       printf("\"");
-
- oo_count:
-       if (!cmd->oo_count)
-               goto op_count;
-
-       sep = 0;
-
-       if (cmd->oo_count) {
-               printf("\n");
-               printf("\" [");
-
-               for (oo = 0; oo < cmd->oo_count; oo++) {
-                       opt_enum = cmd->optional_opt_args[oo].opt;
-
-                       /*
-                        * Skip common opts which are in the usage_common string.
-                        * The common opts are those in lvm_all and in
-                        * cname->common_options.
-                        */
-
-                       if (is_lvm_all_opt(opt_enum))
-                               continue;
-
-                       if ((cname->variants > 1) && cname->common_options[opt_enum])
-                               continue;
-
-                       if (sep)
-                               printf(",");
-
-                       printf(" %s", opt_names[opt_enum].long_opt);
-                       if (cmd->optional_opt_args[oo].def.val_bits) {
-                               printf(" ");
-                               print_def(&cmd->optional_opt_args[oo].def, 1);
-                       }
-                       sep = 1;
-               }
-
-               if (sep)
-                       printf(",");
-               printf(" COMMON_OPTIONS");
-               printf(" ]\"");
-       }
-
- op_count:
-       if (!cmd->op_count)
-               goto done;
-
-       printf("\n");
-       printf("\" [");
-
-       if (cmd->op_count) {
-               for (op = 0; op < cmd->op_count; op++) {
-                       if (cmd->optional_pos_args[op].def.val_bits) {
-                               printf(" ");
-                               print_def(&cmd->optional_pos_args[op].def, 1);
-                       }
-               }
-       }
-
-       printf(" ]\"");
-
- done:
-       printf(";\n");
-}
-
-void print_header_struct(void)
-{
-       struct command *cmd;
-       int i, j, ro, rp, oo, op, ru, ruo, io;
-
-       printf("/* Do not edit. This file is generated by tools/create-commands */\n");
-       printf("/* using command definitions from tools/command-lines.in */\n");
-       printf("\n");
-
-       for (i = 0; i < cmd_count; i++) {
-               cmd = &cmd_array[i];
-
-               printf("commands[%d].name = \"%s\";\n", i, cmd->name);
-               printf("commands[%d].command_line_id = \"%s\";\n", i, cmd->command_line_id);
-               printf("commands[%d].command_line_enum = %s_CMD;\n", i, cmd->command_line_id);
-               printf("commands[%d].fn = %s;\n", i, cmd->name);
-               printf("commands[%d].ro_count = %d;\n", i, cmd->ro_count);
-               printf("commands[%d].rp_count = %d;\n", i, cmd->rp_count);
-               printf("commands[%d].oo_count = %d;\n", i, cmd->oo_count);
-               printf("commands[%d].op_count = %d;\n", i, cmd->op_count);
-               printf("commands[%d].io_count = %d;\n", i, cmd->io_count);
-               printf("commands[%d].rule_count = %d;\n", i, cmd->rule_count);
-
-               if (cmd->cmd_flags)
-                       printf("commands[%d].cmd_flags = %s;\n", i, cmd_flags_to_str(cmd->cmd_flags));
-               else
-                       printf("commands[%d].cmd_flags = 0;\n", i, cmd_flags_to_str(cmd->cmd_flags));
-
-               printf("commands[%d].desc = \"%s\";\n", i, cmd->desc ?: "");
-               printf("commands[%d].usage = ", i);
-               print_usage(cmd);
-
-               if (cmd->oo_count) {
-                       printf("commands[%d].usage_common = ", i);
-                       print_usage_common(cmd);
-               } else {
-                       printf("commands[%d].usage_common = \"NULL\";\n", i);
-               }
-
-               if (cmd->ro_count) {
-                       for (ro = 0; ro < cmd->ro_count; ro++) {
-                               printf("commands[%d].required_opt_args[%d].opt = %s;\n",
-                                       i, ro, opt_to_enum_str(cmd->required_opt_args[ro].opt));
-
-                               if (!cmd->required_opt_args[ro].def.val_bits)
-                                       continue;
-
-                               printf("commands[%d].required_opt_args[%d].def.val_bits = %s;\n",
-                                       i, ro, val_bits_to_str(cmd->required_opt_args[ro].def.val_bits));
-
-                               if (cmd->required_opt_args[ro].def.lvt_bits)
-                                       printf("commands[%d].required_opt_args[%d].def.lvt_bits = %s;\n",
-                                               i, ro, lvt_bits_to_str(cmd->required_opt_args[ro].def.lvt_bits));
-
-                               if (cmd->required_opt_args[ro].def.flags)
-                                       printf("commands[%d].required_opt_args[%d].def.flags = %s;\n",
-                                               i, ro, flags_to_str(cmd->required_opt_args[ro].def.flags));
-
-                               if (val_bit_is_set(cmd->required_opt_args[ro].def.val_bits, constnum_VAL))
-                                       printf("commands[%d].required_opt_args[%d].def.num = %d;\n",
-                                               i, ro, cmd->required_opt_args[ro].def.num);
-
-                               if (val_bit_is_set(cmd->required_opt_args[ro].def.val_bits, conststr_VAL))
-                                       printf("commands[%d].required_opt_args[%d].def.str = \"%s\";\n",
-                                               i, ro, cmd->required_opt_args[ro].def.str ?: "NULL");
-                       }
-               }
-
-               if (cmd->rp_count) {
-                       for (rp = 0; rp < cmd->rp_count; rp++) {
-                               printf("commands[%d].required_pos_args[%d].pos = %d;\n",
-                                       i, rp, cmd->required_pos_args[rp].pos);
-
-                               if (!cmd->required_pos_args[rp].def.val_bits)
-                                       continue;
-
-                               printf("commands[%d].required_pos_args[%d].def.val_bits = %s;\n",
-                                       i, rp, val_bits_to_str(cmd->required_pos_args[rp].def.val_bits));
-
-                               if (cmd->required_pos_args[rp].def.lvt_bits)
-                                       printf("commands[%d].required_pos_args[%d].def.lvt_bits = %s;\n",
-                                               i, rp, lvt_bits_to_str(cmd->required_pos_args[rp].def.lvt_bits));
-
-                               if (cmd->required_pos_args[rp].def.flags)
-                                       printf("commands[%d].required_pos_args[%d].def.flags = %s;\n",
-                                               i, rp, flags_to_str(cmd->required_pos_args[rp].def.flags));
-
-                               if (val_bit_is_set(cmd->required_pos_args[rp].def.val_bits, constnum_VAL))
-                                       printf("commands[%d].required_pos_args[%d].def.num = %d;\n",
-                                               i, rp, cmd->required_pos_args[rp].def.num);
-
-                               if (val_bit_is_set(cmd->required_pos_args[rp].def.val_bits, conststr_VAL))
-                                       printf("commands[%d].required_pos_args[%d].def.str = \"%s\";\n",
-                                               i, rp, cmd->required_pos_args[rp].def.str ?: "NULL");
-                       }
-               }
-
-               if (cmd->oo_count) {
-                       for (oo = 0; oo < cmd->oo_count; oo++) {
-                               printf("commands[%d].optional_opt_args[%d].opt = %s;\n",
-                                       i, oo, opt_to_enum_str(cmd->optional_opt_args[oo].opt));
-
-                               if (!cmd->optional_opt_args[oo].def.val_bits)
-                                       continue;
-
-                               printf("commands[%d].optional_opt_args[%d].def.val_bits = %s;\n",
-                                       i, oo, val_bits_to_str(cmd->optional_opt_args[oo].def.val_bits));
-
-                               if (cmd->optional_opt_args[oo].def.lvt_bits)
-                                       printf("commands[%d].optional_opt_args[%d].def.lvt_bits = %s;\n",
-                                               i, oo, lvt_bits_to_str(cmd->optional_opt_args[oo].def.lvt_bits));
-
-                               if (cmd->optional_opt_args[oo].def.flags)
-                                       printf("commands[%d].optional_opt_args[%d].def.flags = %s;\n",
-                                               i, oo, flags_to_str(cmd->optional_opt_args[oo].def.flags));
-
-                               if (val_bit_is_set(cmd->optional_opt_args[oo].def.val_bits, constnum_VAL)) 
-                                       printf("commands[%d].optional_opt_args[%d].def.num = %d;\n",
-                                               i, oo, cmd->optional_opt_args[oo].def.num);
-
-                               if (val_bit_is_set(cmd->optional_opt_args[oo].def.val_bits, conststr_VAL))
-                                       printf("commands[%d].optional_opt_args[%d].def.str = \"%s\";\n",
-                                               i, oo, cmd->optional_opt_args[oo].def.str ?: "NULL");
-                       }
-               }
-
-               if (cmd->io_count) {
-                       for (io = 0; io < cmd->io_count; io++) {
-                               printf("commands[%d].ignore_opt_args[%d].opt = %s;\n",
-                                       i, io, opt_to_enum_str(cmd->ignore_opt_args[io].opt));
-
-                               if (!cmd->ignore_opt_args[io].def.val_bits)
-                                       continue;
-
-                               printf("commands[%d].ignore_opt_args[%d].def.val_bits = %s;\n",
-                                       i, io, val_bits_to_str(cmd->ignore_opt_args[io].def.val_bits));
-
-                               if (cmd->ignore_opt_args[io].def.lvt_bits)
-                                       printf("commands[%d].ignore_opt_args[%d].def.lvt_bits = %s;\n",
-                                               i, io, lvt_bits_to_str(cmd->ignore_opt_args[io].def.lvt_bits));
-
-                               if (cmd->ignore_opt_args[io].def.flags)
-                                       printf("commands[%d].ignore_opt_args[%d].def.flags = %s;\n",
-                                               i, io, flags_to_str(cmd->ignore_opt_args[io].def.flags));
-
-                               if (val_bit_is_set(cmd->ignore_opt_args[io].def.val_bits, constnum_VAL)) 
-                                       printf("commands[%d].ignore_opt_args[%d].def.num = %d;\n",
-                                               i, io, cmd->ignore_opt_args[io].def.num);
-
-                               if (val_bit_is_set(cmd->ignore_opt_args[io].def.val_bits, conststr_VAL))
-                                       printf("commands[%d].ignore_opt_args[%d].def.str = \"%s\";\n",
-                                               i, io, cmd->ignore_opt_args[io].def.str ?: "NULL");
-                       }
-               }
-
-               if (cmd->op_count) {
-                       for (op = 0; op < cmd->op_count; op++) {
-                               printf("commands[%d].optional_pos_args[%d].pos = %d;\n",
-                                       i, op, cmd->optional_pos_args[op].pos);
-
-                               if (!cmd->optional_pos_args[op].def.val_bits)
-                                       continue;
-
-                               printf("commands[%d].optional_pos_args[%d].def.val_bits = %s;\n",
-                                       i, op, val_bits_to_str(cmd->optional_pos_args[op].def.val_bits));
-
-                               if (cmd->optional_pos_args[op].def.lvt_bits)
-                                       printf("commands[%d].optional_pos_args[%d].def.lvt_bits = %s;\n",
-                                               i, op, lvt_bits_to_str(cmd->optional_pos_args[op].def.lvt_bits));
-
-                               if (cmd->optional_pos_args[op].def.flags)
-                                       printf("commands[%d].optional_pos_args[%d].def.flags = %s;\n",
-                                               i, op, flags_to_str(cmd->optional_pos_args[op].def.flags));
-
-                               if (val_bit_is_set(cmd->optional_pos_args[op].def.val_bits, constnum_VAL))
-                                       printf("commands[%d].optional_pos_args[%d].def.num = %d;\n",
-                                               i, op, cmd->optional_pos_args[op].def.num);
-
-                               if (val_bit_is_set(cmd->optional_pos_args[op].def.val_bits, conststr_VAL))
-                                       printf("commands[%d].optional_pos_args[%d].def.str = \"%s\";\n",
-                                               i, op, cmd->optional_pos_args[op].def.str ?: "NULL");
-                       }
-               }
-
-               if (cmd->rule_count) {
-                       for (ru = 0; ru < cmd->rule_count; ru++) {
-
-                               printf("commands[%d].rules[%d].opts_count = %d;\n", i, ru, cmd->rules[ru].opts_count);
-
-                               if (cmd->rules[ru].opts_count) {
-                                       printf("static int _command%d_rule%d_opts[] = { ", i, ru);
-                                       for (ruo = 0; ruo < cmd->rules[ru].opts_count; ruo++) {
-                                               if (ruo)
-                                                       printf(", ");
-                                               printf("%s", opt_to_enum_str(cmd->rules[ru].opts[ruo]));
-                                       }
-                                       printf(" };\n");
-                                       printf("commands[%d].rules[%d].opts = _command%d_rule%d_opts;\n", i, ru, i, ru);
-                               } else {
-                                       printf("commands[%d].rules[%d].opts = NULL;\n", i, ru);
-                               }
-
-                               printf("commands[%d].rules[%d].check_opts_count = %d;\n", i, ru, cmd->rules[ru].check_opts_count);
-
-                               if (cmd->rules[ru].check_opts_count) {
-                                       printf("static int _command%d_rule%d_check_opts[] = { ", i, ru);
-                                       for (ruo = 0; ruo < cmd->rules[ru].check_opts_count; ruo++) {
-                                               if (ruo)
-                                                       printf(",");
-                                               printf("%s ", opt_to_enum_str(cmd->rules[ru].check_opts[ruo]));
-                                       }
-                                       printf(" };\n");
-                                       printf("commands[%d].rules[%d].check_opts = _command%d_rule%d_check_opts;\n", i, ru, i, ru);
-                               } else {
-                                       printf("commands[%d].rules[%d].check_opts = NULL;\n", i, ru);
-                               }
-
-                               printf("commands[%d].rules[%d].lvt_bits = %s;\n", i, ru,
-                                       cmd->rules[ru].lvt_bits ? lvt_bits_to_str(cmd->rules[ru].lvt_bits) : "0");
-
-                               printf("commands[%d].rules[%d].lvp_bits = %s;\n", i, ru,
-                                       cmd->rules[ru].lvp_bits ? lvp_bits_to_str(cmd->rules[ru].lvp_bits) : "0");
-
-                               printf("commands[%d].rules[%d].rule = %s;\n", i, ru,
-                                       rule_to_define_str(cmd->rules[ru].rule));
-
-                               printf("commands[%d].rules[%d].check_lvt_bits = %s;\n", i, ru,
-                                       cmd->rules[ru].check_lvt_bits ? lvt_bits_to_str(cmd->rules[ru].check_lvt_bits) : "0");
-
-                               printf("commands[%d].rules[%d].check_lvp_bits = %s;\n", i, ru,
-                                       cmd->rules[ru].check_lvp_bits ? lvp_bits_to_str(cmd->rules[ru].check_lvp_bits) : "0");
-                       }
-               }
-
-               printf("\n");
-       }
-}
-
-void print_header_count(void)
-{
-       struct command *cmd;
-       int i, j;
-
-       printf("/* Do not edit. This file is generated by tools/create-commands */\n");
-       printf("/* using command definitions from tools/command-lines.in */\n");
-       printf("#define COMMAND_COUNT %d\n", cmd_count);
-
-       printf("enum {\n");
-       printf("\tno_CMD,\n");  /* enum value 0 is not used */
-
-       for (i = 0; i < cmd_count; i++) {
-               cmd = &cmd_array[i];
-
-               if (!cmd->command_line_id) {
-                       printf("Missing ID: at %d\n", i);
-                       exit(1);
-               }
-
-               for (j = 0; j < i; j++) {
-                       if (!strcmp(cmd->command_line_id, cmd_array[j].command_line_id))
-                               goto next;
-               }
-
-               printf("\t%s_CMD,\n", cmd->command_line_id);
-       next:
-               ;
-       }
-       printf("\tCOMMAND_ID_COUNT,\n");
-       printf("};\n");
-}
-
-struct cmd_pair {
-       int i, j;
-};
-
-void print_ambiguous(void)
-{
-       struct command *cmd, *dup;
-       struct cmd_pair dups[64] = { 0 };
-       int found = 0;
-       int i, j, f, ro, rp;
-
-       for (i = 0; i < cmd_count; i++) {
-               cmd = &cmd_array[i];
-
-               for (j = 0; j < cmd_count; j++) {
-                       dup = &cmd_array[j];
-
-                       if (i == j)
-                               continue;
-                       if (strcmp(cmd->name, dup->name))
-                               continue;
-                       if (cmd->ro_count != dup->ro_count)
-                               continue;
-                       if (cmd->rp_count != dup->rp_count)
-                               continue;
-
-                       for (ro = 0; ro < cmd->ro_count; ro++) {
-                               if (!opt_arg_matches(&cmd->required_opt_args[ro],
-                                                    &dup->required_opt_args[ro]))
-                                       goto next;
-                       }
-
-                       for (rp = 0; rp < cmd->rp_count; rp++) {
-                               if (!pos_arg_matches(&cmd->required_pos_args[rp],
-                                                    &dup->required_pos_args[rp]))
-                                       goto next;
-                       }
-
-                       for (f = 0; f < found; f++) {
-                               if ((dups[f].i == j) && (dups[f].j == i))
-                                       goto next;
-                       }
-
-                       printf("Ambiguous commands %d and %d:\n", i, j);
-                       print_usage(cmd);
-                       print_usage(dup);
-                       printf("\n");
-
-                       dups[found].i = i;
-                       dups[found].j = j;
-                       found++;
-next:
-                       ;
-               }
-       }
-}
-
diff --git a/tools/ccmd.h b/tools/ccmd.h
deleted file mode 100644 (file)
index 1e18125..0000000
+++ /dev/null
@@ -1,144 +0,0 @@
-
-#ifndef __CCMD_H__
-#define __CCMD_H__
-
-/* needed to include args.h */
-#define ARG_COUNTABLE 0x00000001
-#define ARG_GROUPABLE 0x00000002
-struct cmd_context;
-struct arg_values;
-
-/* needed to include args.h */
-static inline int yes_no_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; }
-static inline int activation_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; }
-static inline int cachemode_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; }
-static inline int discards_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; }
-static inline int mirrorlog_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; }
-static inline int size_kb_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; }
-static inline int size_mb_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; }
-static inline int size_mb_arg_with_percent(struct cmd_context *cmd, struct arg_values *av) { return 0; }
-static inline int int_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; }
-static inline int uint32_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; }
-static inline int int_arg_with_sign(struct cmd_context *cmd, struct arg_values *av) { return 0; }
-static inline int int_arg_with_sign_and_percent(struct cmd_context *cmd, struct arg_values *av) { return 0; }
-static inline int major_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; }
-static inline int minor_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; }
-static inline int string_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; }
-static inline int tag_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; }
-static inline int permission_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; }
-static inline int metadatatype_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; }
-static inline int units_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; }
-static inline int segtype_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; }
-static inline int alloc_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; }
-static inline int locktype_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; }
-static inline int readahead_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; }
-static inline int vgmetadatacopies_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av) { return 0; }
-static inline int pvmetadatacopies_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av) { return 0; }
-static inline int metadatacopies_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av) { return 0; }
-static inline int polloperation_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av) { return 0; }
-static inline int writemostly_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av) { return 0; }
-static inline int syncaction_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av) { return 0; }
-static inline int reportformat_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av) { return 0; }
-static inline int configreport_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av) { return 0; }
-static inline int configtype_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av) { return 0; }
-
-/* also see arg_props in tools.h and args.h */
-struct opt_name {
-       const char *name;       /* "foo_ARG" */
-       int opt_enum;           /* foo_ARG */
-       const char short_opt;   /* -f */
-       char _padding[7];
-       const char *long_opt;   /* --foo */
-       int val_enum;           /* xyz_VAL when --foo takes a val like "--foo xyz" */
-       uint32_t unused1;
-       uint32_t unused2;
-       const char *desc;
-};
-
-/* also see val_props in tools.h and vals.h */
-struct val_name {
-       const char *enum_name;  /* "foo_VAL" */
-       int val_enum;           /* foo_VAL */
-       int (*fn) (struct cmd_context *cmd, struct arg_values *av); /* foo_arg() */
-       const char *name;       /* FooVal */
-       const char *usage;
-};
-
-/* also see lv_props in tools.h and lv_props.h */
-struct lvp_name {
-       const char *enum_name; /* "is_foo_LVP" */
-       int lvp_enum;          /* is_foo_LVP */
-       const char *name;      /* "lv_is_foo" */
-};
-
-/* also see lv_types in tools.h and lv_types.h */
-struct lvt_name {
-       const char *enum_name; /* "foo_LVT" */
-       int lvt_enum;          /* foo_LVT */
-       const char *name;      /* "foo" */
-};
-
-/* create foo_VAL enums for option and position values */
-
-enum {
-#define val(a, b, c, d) a ,
-#include "vals.h"
-#undef val
-};
-
-/* create foo_ARG enums for --option's */
-
-enum {
-#define arg(a, b, c, d, e, f, g) a ,
-#include "args.h"
-#undef arg
-};
-
-/* create foo_LVP enums for LV properties */
-
-enum {
-#define lvp(a, b, c) a,
-#include "lv_props.h"
-#undef lvp
-};
-
-/* create foo_LVT enums for LV types */
-
-enum {
-#define lvt(a, b, c) a,
-#include "lv_types.h"
-#undef lvt
-};
-
-/* one for each command name, see cmd_names[] */
-
-#define MAX_CMD_NAMES 128
-struct cmd_name {
-       const char *name;
-       const char *desc;
-       int common_options[ARG_COUNT + 1]; /* options common to all defs */
-       int all_options[ARG_COUNT + 1];    /* union of options from all defs */
-       int variants;        /* number of command defs with this command name */
-       int variant_has_ro;  /* do variants use required_opt_args ? */
-       int variant_has_rp;  /* do variants use required_pos_args ? */
-       int variant_has_oo;  /* do variants use optional_opt_args ? */
-       int variant_has_op;  /* do variants use optional_pos_args ? */
-};
-
-/* struct command */
-
-#include "command.h"
-
-/* one for each command defininition (command-lines.in as struct command) */
-
-#define MAX_CMDS 256
-int cmd_count;
-struct command cmd_array[MAX_CMDS];
-
-#define MAX_LINE 1024
-#define MAX_LINE_ARGC 256
-
-#define DESC_LINE 256
-
-#endif
-
index 4cc51fea4e3ec1558d60915d994256671cc028dd..30573f45222f5bf800c0fc4beab258b4223525d9 100644 (file)
@@ -1,12 +1,15 @@
+# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+# Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
 #
-# When this file is changed, tools/command-lines.h
-# and tools/command-lines-count.h must be regenerated
-# with:
+# This file is part of LVM2.
 #
-# tools/create-commands --output count tools/command-lines.in > tools/command-lines-count.h
-# tools/create-commands --output struct tools/command-lines.in > tools/command-lines.h
+# This copyrighted material is made available to anyone wishing to use,
+# modify, copy, or redistribute it subject to the terms and conditions
+# of the GNU Lesser General Public License v.2.1.
 #
-
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program; if not, write to the Free Software Foundation,
+# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 #
 # Syntax
 #
@@ -261,7 +264,7 @@ RULE: --permission not lv_is_external_origin lv_is_raid_metadata lv_is_raid_imag
 RULE: --alloc --contiguous --metadataprofile --permission --persistent --profile --readahead not lv_is_thick_origin
 RULE: --alloc --discards --zero --cachemode --cachepolicy --cachesettings not lv_is_partial
 
-# It's unfortunate that acativate needs to be optionally allowed here,
+# It's unfortunate that activate needs to be optionally allowed here,
 # like above, it was previouly allowed in combination.
 
 lvchange --resync VG|LV_raid_mirror|Tag|Select ...
diff --git a/tools/command.c b/tools/command.c
new file mode 100644 (file)
index 0000000..59c9ea0
--- /dev/null
@@ -0,0 +1,2694 @@
+/*
+ * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
+ * Copyright (C) 2004-2017 Red Hat, Inc. All rights reserved.
+ *
+ * This file is part of LVM2.
+ *
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License v.2.1.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <asm/types.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdarg.h>
+#include <limits.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <sched.h>
+#include <dirent.h>
+#include <ctype.h>
+#include <getopt.h>
+
+/*
+ * This file can be compiled by itself as a man page generator.
+ */
+#ifdef MAN_PAGE_GENERATOR
+
+#define log_error(fmt, args...) \
+do { \
+       printf(fmt "\n", ##args); \
+} while (0)
+
+/* needed to include args.h */
+#define ARG_COUNTABLE 0x00000001
+#define ARG_GROUPABLE 0x00000002
+struct cmd_context;
+struct arg_values;
+
+/* needed to include args.h */
+static inline int yes_no_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; }
+static inline int activation_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; }
+static inline int cachemode_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; }
+static inline int discards_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; }
+static inline int mirrorlog_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; }
+static inline int size_kb_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; }
+static inline int size_mb_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; }
+static inline int size_mb_arg_with_percent(struct cmd_context *cmd, struct arg_values *av) { return 0; }
+static inline int int_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; }
+static inline int uint32_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; }
+static inline int int_arg_with_sign(struct cmd_context *cmd, struct arg_values *av) { return 0; }
+static inline int int_arg_with_sign_and_percent(struct cmd_context *cmd, struct arg_values *av) { return 0; }
+static inline int major_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; }
+static inline int minor_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; }
+static inline int string_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; }
+static inline int tag_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; }
+static inline int permission_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; }
+static inline int metadatatype_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; }
+static inline int units_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; }
+static inline int segtype_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; }
+static inline int alloc_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; }
+static inline int locktype_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; }
+static inline int readahead_arg(struct cmd_context *cmd, struct arg_values *av) { return 0; }
+static inline int vgmetadatacopies_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av) { return 0; }
+static inline int pvmetadatacopies_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av) { return 0; }
+static inline int metadatacopies_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av) { return 0; }
+static inline int polloperation_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av) { return 0; }
+static inline int writemostly_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av) { return 0; }
+static inline int syncaction_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av) { return 0; }
+static inline int reportformat_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av) { return 0; }
+static inline int configreport_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av) { return 0; }
+static inline int configtype_arg(struct cmd_context *cmd __attribute__((unused)), struct arg_values *av) { return 0; }
+
+/* needed to include commands.h when building man page generator */
+#define CACHE_VGMETADATA        0x00000001
+#define PERMITTED_READ_ONLY     0x00000002
+#define ALL_VGS_IS_DEFAULT      0x00000004
+#define ENABLE_ALL_DEVS         0x00000008      
+#define ALLOW_UUID_AS_NAME      0x00000010
+#define LOCKD_VG_SH             0x00000020
+#define NO_METADATA_PROCESSING  0x00000040
+#define REQUIRES_FULL_LABEL_SCAN 0x00000080
+#define MUST_USE_ALL_ARGS        0x00000100
+#define NO_LVMETAD_AUTOSCAN      0x00000200
+#define ENABLE_DUPLICATE_DEVS    0x00000400
+#define DISALLOW_TAG_ARGS        0x00000800
+#define GET_VGNAME_FROM_OPTIONS  0x00001000
+
+/* create foo_CMD enums for command def ID's in command-lines.in */
+
+enum {
+#define cmd(a, b) a ,
+#include "cmds.h"
+#undef cmd
+};
+
+/* create foo_VAL enums for option and position values */
+
+enum {
+#define val(a, b, c, d) a ,
+#include "vals.h"
+#undef val
+};
+
+/* create foo_ARG enums for --option's */
+
+enum {
+#define arg(a, b, c, d, e, f, g) a ,
+#include "args.h"
+#undef arg
+};
+
+/* create foo_LVP enums for LV properties */
+
+enum {
+#define lvp(a, b, c) a,
+#include "lv_props.h"
+#undef lvp
+};
+
+/* create foo_LVT enums for LV types */
+
+enum {
+#define lvt(a, b, c) a,
+#include "lv_types.h"
+#undef lvt
+};
+
+#else
+
+#include "tools.h"
+
+#endif
+
+#include "command.h"       /* defines struct command */
+#include "command-count.h" /* defines COMMAND_COUNT */
+
+
+/* see opt_names[] below, also see arg_props[] in tools.h and args.h */
+
+struct opt_name {
+       const char *name;       /* "foo_ARG" */
+       int opt_enum;           /* foo_ARG */
+       const char short_opt;   /* -f */
+       char _padding[7];
+       const char *long_opt;   /* --foo */
+       int val_enum;           /* xyz_VAL when --foo takes a val like "--foo xyz" */
+       uint32_t unused1;
+       uint32_t unused2;
+       const char *desc;
+};
+
+/* see val_names[] below, also see val_props[] in tools.h and vals.h */
+
+struct val_name {
+       const char *enum_name;  /* "foo_VAL" */
+       int val_enum;           /* foo_VAL */
+       int (*fn) (struct cmd_context *cmd, struct arg_values *av); /* foo_arg() */
+       const char *name;       /* FooVal */
+       const char *usage;
+};
+
+/* see lvp_names[] below, also see lv_props[] in tools.h and lv_props.h */
+
+struct lvp_name {
+       const char *enum_name; /* "is_foo_LVP" */
+       int lvp_enum;          /* is_foo_LVP */
+       const char *name;      /* "lv_is_foo" */
+};
+
+/* see lvt_names[] below, also see lv_types[] in tools.h and lv_types.h */
+
+struct lvt_name {
+       const char *enum_name; /* "foo_LVT" */
+       int lvt_enum;          /* foo_LVT */
+       const char *name;      /* "foo" */
+};
+
+/* see cmd_names[] below, one for each unique "ID" in command-lines.in */
+
+struct cmd_name {
+       const char *enum_name; /* "foo_CMD" */
+       int cmd_enum;          /* foo_CMD */
+       const char *name;      /* "foo" from string after ID: */
+};
+
+/* create table of value names, e.g. String, and corresponding enum from vals.h */
+
+struct val_name val_names[VAL_COUNT + 1] = {
+#define val(a, b, c, d) { # a, a, b, c, d },
+#include "vals.h"
+#undef val
+};
+
+/* create table of option names, e.g. --foo, and corresponding enum from args.h */
+
+struct opt_name opt_names[ARG_COUNT + 1] = {
+#define arg(a, b, c, d, e, f, g) { # a, a, b, "", "--" c, d, e, f, g },
+#include "args.h"
+#undef arg
+};
+
+/* create table of lv property names, e.g. lv_is_foo, and corresponding enum from lv_props.h */
+
+struct lvp_name lvp_names[LVP_COUNT + 1] = {
+#define lvp(a, b, c) { # a, a, b },
+#include "lv_props.h"
+#undef lvp
+};
+
+/* create table of lv type names, e.g. linear and corresponding enum from lv_types.h */
+
+struct lvt_name lvt_names[LVT_COUNT + 1] = {
+#define lvt(a, b, c) { # a, a, b },
+#include "lv_types.h"
+#undef lvt
+};
+
+/* create table of command IDs */
+
+struct cmd_name cmd_names[CMD_COUNT + 1] = {
+#define cmd(a, b) { # a, a, # b },
+#include "cmds.h"
+#undef cmd
+};
+
+/*
+ * command_names[] and commands[] are defined in lvmcmdline.c when building lvm,
+ * but need to be defined here when building the stand-alone man page generator.
+ */
+
+#ifdef MAN_PAGE_GENERATOR
+struct command_name command_names[MAX_COMMAND_NAMES] = {
+#define xx(a, b, c...) { # a, b, c },
+#include "commands.h"
+#undef xx
+};
+struct command commands[COMMAND_COUNT];
+#else
+extern struct command_name command_names[MAX_COMMAND_NAMES]; /* defined in lvmcmdline.c */
+extern struct command commands[COMMAND_COUNT]; /* defined in lvmcmdline.c */
+#endif
+
+/* array of pointers into opt_names[] that is sorted alphabetically (by long opt name) */
+
+struct opt_name *opt_names_alpha[ARG_COUNT + 1];
+
+/* lvm_all is for recording options that are common for all lvm commands */
+
+struct command lvm_all;
+
+/* saves OO_FOO lines (groups of optional options) to include in multiple defs */
+
+static int oo_line_count;
+#define MAX_OO_LINES 256
+
+struct oo_line {
+       char *name;
+       char *line;
+};
+static struct oo_line oo_lines[MAX_OO_LINES];
+
+#define REQUIRED 1  /* required option */
+#define OPTIONAL 0  /* optional option */
+#define IGNORE -1   /* ignore option */
+
+#define MAX_LINE 1024
+#define MAX_LINE_ARGC 256
+#define DESC_LINE 1024
+
+/*
+ * Contains _command_input[] which is command-lines.in with comments
+ * removed and wrapped as a string.  The _command_input[] string is
+ * used to populate commands[].
+ */
+#include "command-lines-input.h"
+
+static void add_optional_opt_line(struct command *cmd, int argc, char *argv[]);
+
+/*
+ * modifies buf, replacing the sep characters with \0
+ * argv pointers point to positions in buf
+ */
+
+static char *split_line(char *buf, int *argc, char **argv, char sep)
+{
+       char *p = buf, *rp = NULL;
+       int i;
+
+       argv[0] = p;
+
+       for (i = 1; i < MAX_LINE_ARGC; i++) {
+               p = strchr(buf, sep);
+               if (!p)
+                       break;
+               *p = '\0';
+
+               argv[i] = p + 1;
+               buf = p + 1;
+       }
+       *argc = i;
+
+       /* we ended by hitting \0, return the point following that */
+       if (!rp)
+               rp = strchr(buf, '\0') + 1;
+
+       return rp;
+}
+
+/* convert value string, e.g. Number, to foo_VAL enum */
+
+static int val_str_to_num(char *str)
+{
+       char name[32] = { 0 };
+       char *new;
+       int i;
+
+       /* compare the name before any suffix like _new or _<lvtype> */
+
+       strncpy(name, str, 31);
+       if ((new = strstr(name, "_")))
+               *new = '\0';
+
+       for (i = 0; i < VAL_COUNT; i++) {
+               if (!val_names[i].name)
+                       break;
+               if (!strncmp(name, val_names[i].name, strlen(val_names[i].name)))
+                       return val_names[i].val_enum;
+       }
+
+       return 0;
+}
+
+/* convert "--option" to foo_ARG enum */
+
+static int opt_str_to_num(char *str)
+{
+       char long_name[32];
+       char *p;
+       int i;
+
+       /*
+        * --foo_long means there are two args entries
+        * for --foo, one with a short option and one
+        * without, and we want the one without the
+        * short option.
+        */
+       if (strstr(str, "_long")) {
+               strcpy(long_name, str);
+               p = strstr(long_name, "_long");
+               *p = '\0';
+
+               for (i = 0; i < ARG_COUNT; i++) {
+                       if (!opt_names[i].long_opt)
+                               continue;
+                       /* skip anything with a short opt */
+                       if (opt_names[i].short_opt)
+                               continue;
+                       if (!strcmp(opt_names[i].long_opt, long_name))
+                               return opt_names[i].opt_enum;
+               }
+
+               log_error("Parsing command defs: unknown opt str: %s %s", str, long_name);
+               exit(EXIT_FAILURE);
+       }
+
+       for (i = 0; i < ARG_COUNT; i++) {
+               if (!opt_names[i].long_opt)
+                       continue;
+               /* These are only selected using --foo_long */
+               if (strstr(opt_names[i].name, "_long_ARG"))
+                       continue;
+               if (!strcmp(opt_names[i].long_opt, str))
+                       return opt_names[i].opt_enum;
+       }
+
+       log_error("Parsing command defs: unknown opt str: \"%s\"", str);
+       exit(EXIT_FAILURE);
+}
+
+/* "foo" string to foo_CMD int */
+
+int command_id_to_enum(const char *str)
+{
+       int i;
+
+       for (i = 1; i < CMD_COUNT; i++) {
+               if (!strcmp(str, cmd_names[i].name))
+                       return cmd_names[i].cmd_enum;
+       }
+       log_error("Parsing command defs: unknown cmd name %s", str);
+       exit(EXIT_FAILURE);
+}
+
+/* "lv_is_prop" to is_prop_LVP */
+
+static int lvp_name_to_enum(char *str)
+{
+       int i;
+
+       for (i = 1; i < LVP_COUNT; i++) {
+               if (!strcmp(str, lvp_names[i].name))
+                       return lvp_names[i].lvp_enum;
+       }
+       log_error("Parsing command defs: unknown lv property %s", str);
+       exit(EXIT_FAILURE);
+}
+
+/* "type" to type_LVT */
+
+static int lvt_name_to_enum(char *str)
+{
+       int i;
+
+       for (i = 1; i < LVT_COUNT; i++) {
+               if (!strcmp(str, lvt_names[i].name))
+                       return lvt_names[i].lvt_enum;
+       }
+       log_error("Parsing command defs: unknown lv type %s", str);
+       exit(EXIT_FAILURE);
+}
+
+/* LV_<type> to <type>_LVT */
+
+static int lv_to_enum(char *name)
+{
+       return lvt_name_to_enum(name + 3);
+}
+
+/*
+ * LV_<type1>_<type2> to lvt_bits
+ *
+ * type1 to lvt_enum
+ * lvt_bits |= lvt_enum_to_bit(lvt_enum)
+ * type2 to lvt_enum
+ * lvt_bits |= lvt_enum_to_bit(lvt_enum)
+ */
+
+static uint64_t lv_to_bits(char *name)
+{
+       char buf[64];
+       char *argv[MAX_LINE_ARGC];
+       uint64_t lvt_bits = 0;
+       int lvt_enum;
+       int argc;
+       int i;
+
+       strcpy(buf, name);
+
+       split_line(buf, &argc, argv, '_');
+
+       /* 0 is "LV" */
+       for (i = 1; i < argc; i++) {
+               if (!strcmp(argv[i], "new"))
+                       continue;
+               lvt_enum = lvt_name_to_enum(argv[i]);
+               lvt_bits |= lvt_enum_to_bit(lvt_enum);
+       }
+
+       return lvt_bits;
+}
+
+static struct command_name *find_command_name(const char *name)
+{
+       int i;
+
+       for (i = 0; i < MAX_COMMAND_NAMES; i++) {
+               if (!command_names[i].name)
+                       break;
+               if (!strcmp(command_names[i].name, name))
+                       return &command_names[i];
+       }
+       return NULL;
+}
+
+static const char *is_command_name(char *str)
+{
+       int i;
+
+       for (i = 0; i < MAX_COMMAND_NAMES; i++) {
+               if (!command_names[i].name)
+                       break;
+               if (!strcmp(command_names[i].name, str))
+                       return command_names[i].name;
+       }
+       return NULL;
+}
+
+static int is_opt_name(char *str)
+{
+       if (!strncmp(str, "--", 2))
+               return 1;
+
+       if ((str[0] == '-') && (str[1] != '-')) {
+               log_error("Parsing command defs: options must be specified in long form: %s", str);
+               exit(EXIT_FAILURE);
+       }
+
+       return 0;
+}
+
+/*
+ * "Select" as a pos name means that the position
+ * can be empty if the --select option is used.
+ */
+
+static int is_pos_name(char *str)
+{
+       if (!strncmp(str, "VG", 2))
+               return 1;
+       if (!strncmp(str, "LV", 2))
+               return 1;
+       if (!strncmp(str, "PV", 2))
+               return 1;
+       if (!strncmp(str, "Tag", 3))
+               return 1;
+       if (!strncmp(str, "String", 6))
+               return 1;
+       if (!strncmp(str, "Select", 6))
+               return 1;
+       return 0;
+}
+
+static int is_oo_definition(char *str)
+{
+       if (!strncmp(str, "OO_", 3) && strstr(str, ":"))
+               return 1;
+       return 0;
+}
+
+static int is_oo_line(char *str)
+{
+       if (!strncmp(str, "OO:", 3))
+               return 1;
+       return 0;
+}
+
+static int is_io_line(char *str)
+{
+       if (!strncmp(str, "IO:", 3))
+               return 1;
+       return 0;
+}
+
+static int is_op_line(char *str)
+{
+       if (!strncmp(str, "OP:", 3))
+               return 1;
+       return 0;
+}
+
+static int is_desc_line(char *str)
+{
+       if (!strncmp(str, "DESC:", 5))
+               return 1;
+       return 0;
+}
+
+static int is_flags_line(char *str)
+{
+       if (!strncmp(str, "FLAGS:", 6))
+               return 1;
+       return 0;
+}
+
+static int is_rule_line(char *str)
+{
+       if (!strncmp(str, "RULE:", 5))
+               return 1;
+       return 0;
+}
+
+static int is_id_line(char *str)
+{
+       if (!strncmp(str, "ID:", 3))
+               return 1;
+       return 0;
+}
+
+/*
+ * Save a positional arg in a struct arg_def.
+ * Parse str for anything that can appear in a position,
+ * like VG, VG|LV, VG|LV_linear|LV_striped, etc.
+ */
+
+static void set_pos_def(struct command *cmd, char *str, struct arg_def *def)
+{
+       char *argv[MAX_LINE_ARGC];
+       int argc;
+       char *name;
+       int val_enum;
+       int i;
+
+       split_line(str, &argc, argv, '|');
+
+       for (i = 0; i < argc; i++) {
+               name = argv[i];
+
+               val_enum = val_str_to_num(name);
+
+               if (!val_enum) {
+                       log_error("Parsing command defs: unknown pos arg: %s", name);
+                       exit(EXIT_FAILURE);
+               }
+
+               def->val_bits |= val_enum_to_bit(val_enum);
+
+               if ((val_enum == lv_VAL) && strstr(name, "_"))
+                       def->lvt_bits = lv_to_bits(name);
+
+               if (strstr(name, "_new")) {
+                       if (val_enum == lv_VAL)
+                               def->flags |= ARG_DEF_FLAG_NEW_LV;
+                       else if (val_enum == vg_VAL)
+                               def->flags |= ARG_DEF_FLAG_NEW_VG;
+               }
+       }
+}
+
+/*
+ * Save an option arg in a struct arg_def.
+ * Parse str for anything that can follow --option.
+ */
+
+static void set_opt_def(struct command *cmd, char *str, struct arg_def *def)
+{
+       char *argv[MAX_LINE_ARGC];
+       int argc;
+       char *name;
+       int val_enum;
+       int i;
+
+       split_line(str, &argc, argv, '|');
+
+       for (i = 0; i < argc; i++) {
+               name = argv[i];
+
+               val_enum = val_str_to_num(name);
+
+               if (!val_enum) {
+                       /* a literal number or string */
+
+                       if (isdigit(name[0]))
+                               val_enum = constnum_VAL;
+
+                       else if (isalpha(name[0]))
+                               val_enum = conststr_VAL;
+
+                       else {
+                               log_error("Parsing command defs: unknown opt arg: %s", name);
+                               exit(EXIT_FAILURE);
+                       }
+               }
+
+
+               def->val_bits |= val_enum_to_bit(val_enum);
+
+               if (val_enum == constnum_VAL)
+                       def->num = (uint64_t)atoi(name);
+
+               if (val_enum == conststr_VAL)
+                       def->str = strdup(name);
+
+               if (val_enum == lv_VAL) {
+                       if (strstr(name, "_"))
+                               def->lvt_bits = lv_to_bits(name);
+               }
+
+               if (strstr(name, "_new")) {
+                       if (val_enum == lv_VAL)
+                               def->flags |= ARG_DEF_FLAG_NEW_LV;
+                       else if (val_enum == vg_VAL)
+                               def->flags |= ARG_DEF_FLAG_NEW_VG;
+                               
+               }
+       }
+}
+
+/*
+ * Save a set of common options so they can be included in
+ * multiple command defs.
+ *
+ * OO_FOO: --opt1 ...
+ *
+ * oo->name = "OO_FOO";
+ * oo->line = "--opt1 ...";
+ */
+
+static void add_oo_definition_line(const char *name, const char *line)
+{
+       struct oo_line *oo;
+       char *colon;
+       char *start;
+
+       oo = &oo_lines[oo_line_count++];
+       oo->name = strdup(name);
+
+       if ((colon = strstr(oo->name, ":")))
+               *colon = '\0';
+       else {
+               log_error("Parsing command defs: invalid OO definition");
+               exit(EXIT_FAILURE);
+       }
+
+       start = strstr(line, ":") + 2;
+       oo->line = strdup(start);
+}
+
+/* Support OO_FOO: continuing on multiple lines. */
+
+static void append_oo_definition_line(const char *new_line)
+{
+       struct oo_line *oo;
+       char *old_line;
+       char *line;
+       int len;
+
+       oo = &oo_lines[oo_line_count-1];
+
+       old_line = oo->line;
+
+       /* +2 = 1 space between old and new + 1 terminating \0 */
+       len = strlen(old_line) + strlen(new_line) + 2;
+       line = malloc(len);
+       memset(line, 0, len);
+
+       strcat(line, old_line);
+       strcat(line, " ");
+       strcat(line, new_line);
+
+       free(oo->line);
+       oo->line = line;
+}
+
+/* Find a saved OO_FOO definition. */
+
+static char *get_oo_line(const char *str)
+{
+       char *name;
+       char *end;
+       char str2[64];
+       int i;
+
+       strcpy(str2, str);
+       if ((end = strstr(str2, ":")))
+               *end = '\0';
+       if ((end = strstr(str2, ",")))
+               *end = '\0';
+
+       for (i = 0; i < oo_line_count; i++) {
+               name = oo_lines[i].name;
+               if (!strcmp(name, str2))
+                       return oo_lines[i].line;
+       }
+       return NULL;
+}
+
+/*
+ * Add optional_opt_args entries when OO_FOO appears on OO: line,
+ * i.e. include common options from an OO_FOO definition.
+ */
+
+static void include_optional_opt_args(struct command *cmd, const char *str)
+{
+       char *oo_line;
+       char *line;
+       char *line_argv[MAX_LINE_ARGC];
+       int line_argc;
+
+       if (!(oo_line = get_oo_line(str))) {
+               log_error("Parsing command defs: no OO line found for %s", str);
+               exit(EXIT_FAILURE);
+       }
+
+       if (!(line = strdup(oo_line)))
+               exit(EXIT_FAILURE);
+
+       split_line(line, &line_argc, line_argv, ' ');
+       add_optional_opt_line(cmd, line_argc, line_argv);
+       free(line);
+}
+
+/*
+ * When an --option is seen, add a new opt_args entry for it.
+ * This function sets the opt_args.opt value for it.
+ */
+
+static void add_opt_arg(struct command *cmd, char *str, int *takes_arg, int required)
+{
+       char *comma;
+       int opt;
+
+       /* opt_arg.opt set here */
+       /* opt_arg.def will be set in update_prev_opt_arg() if needed */
+
+       if ((comma = strstr(str, ",")))
+               *comma = '\0';
+
+       /*
+        * Work around nasty hack where --uuid is used for both uuid_ARG
+        * and uuidstr_ARG.  The input uses --uuidstr, where an actual
+        * command uses --uuid string.
+        */
+       if (!strcmp(str, "--uuidstr")) {
+               opt = uuidstr_ARG;
+               goto skip;
+       }
+
+       opt = opt_str_to_num(str);
+skip:
+       if (required > 0)
+               cmd->required_opt_args[cmd->ro_count++].opt = opt;
+       else if (!required)
+               cmd->optional_opt_args[cmd->oo_count++].opt = opt;
+       else if (required < 0)
+               cmd->ignore_opt_args[cmd->io_count++].opt = opt;
+       else
+               exit(EXIT_FAILURE);
+
+       *takes_arg = opt_names[opt].val_enum ? 1 : 0;
+}
+
+/*
+ * After --option has been seen, this function sets opt_args.def value
+ * for the value that appears after --option.
+ */
+
+static void update_prev_opt_arg(struct command *cmd, char *str, int required)
+{
+       struct arg_def def = { 0 };
+       char *comma;
+
+       if (str[0] == '-') {
+               log_error("Parsing command defs: option %s must be followed by an arg.", str);
+               exit(EXIT_FAILURE);
+       }
+
+       /* opt_arg.def set here */
+       /* opt_arg.opt was previously set in add_opt_arg() when --foo was read */
+
+       if ((comma = strstr(str, ",")))
+               *comma = '\0';
+
+       set_opt_def(cmd, str, &def);
+
+       if (required > 0)
+               cmd->required_opt_args[cmd->ro_count-1].def = def;
+       else if (!required)
+               cmd->optional_opt_args[cmd->oo_count-1].def = def;
+       else if (required < 0)
+               cmd->ignore_opt_args[cmd->io_count-1].def = def;
+       else
+               exit(EXIT_FAILURE);
+}
+
+/*
+ * When an position arg is seen, add a new pos_args entry for it.
+ * This function sets the pos_args.pos and pos_args.def.
+ */
+
+static void add_pos_arg(struct command *cmd, char *str, int required)
+{
+       struct arg_def def = { 0 };
+
+       /* pos_arg.pos and pos_arg.def are set here */
+
+       set_pos_def(cmd, str, &def);
+
+       if (required) {
+               cmd->required_pos_args[cmd->rp_count].pos = cmd->pos_count++;
+               cmd->required_pos_args[cmd->rp_count].def = def;
+               cmd->rp_count++;
+       } else {
+               cmd->optional_pos_args[cmd->op_count].pos = cmd->pos_count++;;
+               cmd->optional_pos_args[cmd->op_count].def = def;
+               cmd->op_count++;
+       }
+}
+
+/* Process something that follows a pos arg, which is not a new pos arg. */
+
+static void update_prev_pos_arg(struct command *cmd, char *str, int required)
+{
+       struct arg_def *def;
+
+       /* a previous pos_arg.def is modified here */
+
+       if (required)
+               def = &cmd->required_pos_args[cmd->rp_count-1].def;
+       else
+               def = &cmd->optional_pos_args[cmd->op_count-1].def;
+
+       if (!strcmp(str, "..."))
+               def->flags |= ARG_DEF_FLAG_MAY_REPEAT;
+       else {
+               log_error("Parsing command defs: unknown pos arg: %s", str);
+               exit(EXIT_FAILURE);
+       }
+}
+
+/* Process what follows OO:, which are the optional opt args for the cmd def. */
+
+static void add_optional_opt_line(struct command *cmd, int argc, char *argv[])
+{
+       int takes_arg;
+       int i;
+
+       for (i = 0; i < argc; i++) {
+               if (!i && !strncmp(argv[i], "OO:", 3))
+                       continue;
+               if (is_opt_name(argv[i]))
+                       add_opt_arg(cmd, argv[i], &takes_arg, OPTIONAL);
+               else if (!strncmp(argv[i], "OO_", 3))
+                       include_optional_opt_args(cmd, argv[i]);
+               else if (takes_arg)
+                       update_prev_opt_arg(cmd, argv[i], OPTIONAL);
+               else {
+                       log_error("Parsing command defs: can't parse argc %d argv %s prev %s",
+                               i, argv[i], argv[i-1]);
+                       exit(EXIT_FAILURE);
+               }
+       }
+}
+
+/* Process what follows IO:, which are the ignore options for the cmd def. */
+
+static void add_ignore_opt_line(struct command *cmd, int argc, char *argv[])
+{
+       int takes_arg;
+       int i;
+
+       for (i = 0; i < argc; i++) {
+               if (!i && !strncmp(argv[i], "IO:", 3))
+                       continue;
+               if (is_opt_name(argv[i]))
+                       add_opt_arg(cmd, argv[i], &takes_arg, IGNORE);
+               else if (takes_arg)
+                       update_prev_opt_arg(cmd, argv[i], IGNORE);
+               else {
+                       log_error("Parsing command defs: can't parse argc %d argv %s prev %s",
+                               i, argv[i], argv[i-1]);
+                       exit(EXIT_FAILURE);
+               }
+       }
+}
+
+/* Process what follows OP:, which are optional pos args for the cmd def. */
+
+static void add_optional_pos_line(struct command *cmd, int argc, char *argv[])
+{
+       int i;
+
+       for (i = 0; i < argc; i++) {
+               if (!i && !strncmp(argv[i], "OP:", 3))
+                       continue;
+               if (is_pos_name(argv[i]))
+                       add_pos_arg(cmd, argv[i], OPTIONAL);
+               else
+                       update_prev_pos_arg(cmd, argv[i], OPTIONAL);
+       }
+}
+
+static void add_required_opt_line(struct command *cmd, int argc, char *argv[])
+{
+       int takes_arg;
+       int i;
+
+       for (i = 0; i < argc; i++) {
+               if (is_opt_name(argv[i]))
+                       add_opt_arg(cmd, argv[i], &takes_arg, REQUIRED);
+               else if (takes_arg)
+                       update_prev_opt_arg(cmd, argv[i], REQUIRED);
+               else {
+                       log_error("Parsing command defs: can't parse argc %d argv %s prev %s",
+                                 i, argv[i], argv[i-1]);
+                       exit(EXIT_FAILURE);
+               }
+       }
+}
+
+/*
+ * Add to required_opt_args from an OO_FOO definition.
+ * (This is the special case of vgchange/lvchange where one
+ * optional option is required, and others are then optional.)
+ * The set of options from OO_FOO are saved in required_opt_args,
+ * and flag CMD_FLAG_ONE_REQUIRED_OPT is set on the cmd indicating
+ * this special case.
+ */
+static void include_required_opt_args(struct command *cmd, char *str)
+{
+       char *oo_line;
+       char *line;
+       char *line_argv[MAX_LINE_ARGC];
+       int line_argc;
+
+       if (!(oo_line = get_oo_line(str))) {
+               log_error("Parsing command defs: no OO line found for %s", str);
+               exit(EXIT_FAILURE);
+       }
+
+       if (!(line = strdup(oo_line)))
+               exit(EXIT_FAILURE);
+
+       split_line(line, &line_argc, line_argv, ' ');
+       add_required_opt_line(cmd, line_argc, line_argv);
+       free(line);
+}
+
+/* Process what follows command_name, which are required opt/pos args. */
+
+static void add_required_line(struct command *cmd, int argc, char *argv[])
+{
+       int i;
+       int takes_arg;
+       int prev_was_opt = 0, prev_was_pos = 0;
+
+       /* argv[0] is command name */
+
+       for (i = 1; i < argc; i++) {
+
+               if (is_opt_name(argv[i])) {
+                       /* add new required_opt_arg */
+                       add_opt_arg(cmd, argv[i], &takes_arg, REQUIRED);
+                       prev_was_opt = 1;
+                       prev_was_pos = 0;
+
+               } else if (prev_was_opt && takes_arg) {
+                       /* set value for previous required_opt_arg */
+                       update_prev_opt_arg(cmd, argv[i], REQUIRED);
+                       prev_was_opt = 0;
+                       prev_was_pos = 0;
+
+               } else if (is_pos_name(argv[i])) {
+                       /* add new required_pos_arg */
+                       add_pos_arg(cmd, argv[i], REQUIRED);
+                       prev_was_opt = 0;
+                       prev_was_pos = 1;
+
+               } else if (!strncmp(argv[i], "OO_", 3)) {
+                       /* one required_opt_arg is required, special case lv/vgchange */
+                       cmd->cmd_flags |= CMD_FLAG_ONE_REQUIRED_OPT;
+                       include_required_opt_args(cmd, argv[i]);
+
+               } else if (prev_was_pos) {
+                       /* set property for previous required_pos_arg */
+                       update_prev_pos_arg(cmd, argv[i], REQUIRED);
+               } else {
+                       log_error("Parsing command defs: can't parse argc %d argv %s prev %s",
+                                 i, argv[i], argv[i-1]);
+                       exit(EXIT_FAILURE);
+               }
+
+       }
+}
+
+static void add_flags(struct command *cmd, char *line)
+{
+       if (strstr(line, "SECONDARY_SYNTAX"))
+               cmd->cmd_flags |= CMD_FLAG_SECONDARY_SYNTAX;
+}
+
+#define MAX_RULE_OPTS 64
+
+static void add_rule(struct command *cmd, char *line)
+{
+       struct cmd_rule *rule;
+       char *line_argv[MAX_LINE_ARGC];
+       char *arg;
+       int line_argc;
+       int i, lvt_enum, lvp_enum;
+       int check = 0;
+
+       if (cmd->rule_count == CMD_MAX_RULES) {
+               log_error("Parsing command defs: too many rules for cmd");
+               exit(EXIT_FAILURE);
+       }
+
+       rule = &cmd->rules[cmd->rule_count++];
+
+       split_line(line, &line_argc, line_argv, ' ');
+
+       for (i = 0; i < line_argc; i++) {
+               arg = line_argv[i];
+
+               if (!strcmp(arg, "not")) {
+                       rule->rule = RULE_INVALID;
+                       check = 1;
+               }
+
+               else if (!strcmp(arg, "and")) {
+                       rule->rule = RULE_REQUIRE;
+                       check = 1;
+               }
+
+               else if (!strncmp(arg, "all", 3)) {
+                       /* opt/lvt_bits/lvp_bits all remain 0 to mean all */
+                       continue;
+               }
+
+               else if (!strncmp(arg, "--", 2)) {
+                       if (!rule->opts) {
+                               if (!(rule->opts = malloc(MAX_RULE_OPTS * sizeof(int)))) {
+                                       log_error("Parsing command defs: no mem");
+                                       exit(EXIT_FAILURE);
+                               }
+                               memset(rule->opts, 0, MAX_RULE_OPTS * sizeof(int));
+                       }
+
+                       if (!rule->check_opts) {
+                               if (!(rule->check_opts = malloc(MAX_RULE_OPTS * sizeof(int)))) {
+                                       log_error("Parsing command defs: no mem");
+                                       exit(EXIT_FAILURE);
+                               }
+                               memset(rule->check_opts, 0, MAX_RULE_OPTS * sizeof(int));
+                       }
+
+                       if (check)
+                               rule->check_opts[rule->check_opts_count++] = opt_str_to_num(arg);
+                       else
+                               rule->opts[rule->opts_count++] = opt_str_to_num(arg);
+               }
+
+               else if (!strncmp(arg, "LV_", 3)) {
+                       lvt_enum = lv_to_enum(arg);
+
+                       if (check)
+                               rule->check_lvt_bits |= lvt_enum_to_bit(lvt_enum);
+                       else
+                               rule->lvt_bits |= lvt_enum_to_bit(lvt_enum);
+               }
+
+               else if (!strncmp(arg, "lv_is_", 6)) {
+                       lvp_enum = lvp_name_to_enum(arg);
+
+                       if (check)
+                               rule->check_lvp_bits |= lvp_enum_to_bit(lvp_enum);
+                       else
+                               rule->lvp_bits |= lvp_enum_to_bit(lvp_enum);
+               }
+       }
+}
+
+/* The given option is common to all lvm commands (set in lvm_all). */
+
+static int is_lvm_all_opt(int opt)
+{
+       int oo;
+
+       for (oo = 0; oo < lvm_all.oo_count; oo++) {
+               if (lvm_all.optional_opt_args[oo].opt == opt)
+                       return 1;
+       }
+       return 0;
+}
+
+/* Find common options for all variants of each command name. */
+
+static void factor_common_options(void)
+{
+       int cn, opt_enum, ci, oo, ro, found;
+       struct command *cmd;
+
+       for (cn = 0; cn < MAX_COMMAND_NAMES; cn++) {
+               if (!command_names[cn].name)
+                       break;
+
+               for (ci = 0; ci < COMMAND_COUNT; ci++) {
+                       cmd = &commands[ci];
+
+                       if (strcmp(cmd->name, command_names[cn].name))
+                               continue;
+
+                       command_names[cn].variants++;
+               }
+
+               for (opt_enum = 0; opt_enum < ARG_COUNT; opt_enum++) {
+
+                       for (ci = 0; ci < COMMAND_COUNT; ci++) {
+                               cmd = &commands[ci];
+
+                               if (strcmp(cmd->name, command_names[cn].name))
+                                       continue;
+
+                               if (cmd->ro_count)
+                                       command_names[cn].variant_has_ro = 1;
+                               if (cmd->rp_count)
+                                       command_names[cn].variant_has_rp = 1;
+                               if (cmd->oo_count)
+                                       command_names[cn].variant_has_oo = 1;
+                               if (cmd->op_count)
+                                       command_names[cn].variant_has_op = 1;
+
+                               for (ro = 0; ro < cmd->ro_count; ro++) {
+                                       command_names[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;
+                               }
+                               for (oo = 0; oo < cmd->oo_count; oo++)
+                                       command_names[cn].all_options[cmd->optional_opt_args[oo].opt] = 1;
+
+                               found = 0;
+
+                               for (oo = 0; oo < cmd->oo_count; oo++) {
+                                       if (cmd->optional_opt_args[oo].opt == opt_enum) {
+                                               found = 1;
+                                               break;
+                                       }
+                               }
+
+                               if (!found)
+                                       goto next_opt;
+                       }
+
+                       /* all commands starting with this name use this option */
+                       command_names[cn].common_options[opt_enum] = 1;
+ next_opt:
+                       ;
+               }
+       }
+}
+
+static int long_name_compare(const void *on1, const void *on2)
+{
+       struct opt_name **optname1 = (void *)on1;
+       struct opt_name **optname2 = (void *)on2;
+       return strcmp((*optname1)->long_opt + 2, (*optname2)->long_opt + 2);
+}
+
+/* Create list of option names for printing alphabetically. */
+
+static void create_opt_names_alpha(void)
+{
+       int i;
+
+       for (i = 0; i < ARG_COUNT; i++)
+               opt_names_alpha[i] = &opt_names[i];
+
+       qsort(opt_names_alpha, ARG_COUNT, sizeof(long), long_name_compare);
+}
+
+static int copy_line(char *line, int max_line, int *position)
+{
+       int p = *position;
+       int i = 0;
+
+       memset(line, 0, max_line);
+
+       while (1) {
+               line[i] = _command_input[p];
+               i++;
+               p++;
+
+               if (_command_input[p] == '\n') {
+                       p++;
+                       break;
+               }
+
+               if (i == (max_line - 1))
+                       break;
+       }
+       *position = p;
+       return 1;
+}
+
+int define_commands(void)
+{
+       struct command *cmd;
+       char line[MAX_LINE];
+       char line_orig[MAX_LINE];
+       char *line_argv[MAX_LINE_ARGC];
+       const char *name;
+       char *n;
+       int line_argc;
+       int cmd_count = 0;
+       int prev_was_oo_def = 0;
+       int prev_was_oo = 0;
+       int prev_was_op = 0;
+       int copy_pos = 0;
+
+       create_opt_names_alpha();
+
+       /* Process each line of command-lines-input.h (from command-lines.in) */
+
+       while (copy_line(line, MAX_LINE, &copy_pos)) {
+               if (line[0] == '\n')
+                       break;
+
+               if ((n = strchr(line, '\n')))
+                       *n = '\0';
+
+               memcpy(line_orig, line, sizeof(line));
+               split_line(line, &line_argc, line_argv, ' ');
+
+               if (!line_argc)
+                       continue;
+
+               /* New cmd def begins: command_name <required opt/pos args> */
+               if ((name = is_command_name(line_argv[0]))) {
+                       if (cmd_count >= COMMAND_COUNT) {
+                               return 0;
+                       }
+
+                       /*
+                        * FIXME: when running one specific command name,
+                        * we can optimize by not parsing command defs
+                        * that don't start with that command name.
+                        */
+
+                       cmd = &commands[cmd_count];
+                       cmd->command_index = cmd_count;
+                       cmd_count++;
+                       cmd->name = strdup(name);
+                       cmd->pos_count = 1;
+                       add_required_line(cmd, line_argc, line_argv);
+
+                       /* Every cmd gets the OO_ALL options */
+                       include_optional_opt_args(cmd, "OO_ALL:");
+                       continue;
+               }
+
+               /*
+                * All other kinds of lines are processed in the
+                * context of the existing command[].
+                */
+
+               if (is_desc_line(line_argv[0])) {
+                       char *desc = strdup(line_orig);
+                       if (cmd->desc) {
+                               int newlen = strlen(cmd->desc) + strlen(desc) + 2;
+                               char *newdesc = malloc(newlen);
+                               memset(newdesc, 0, newlen);
+                               snprintf(newdesc, newlen, "%s %s", cmd->desc, desc);
+                               cmd->desc = newdesc;
+                               free(desc);
+                       } else
+                               cmd->desc = desc;
+                       continue;
+               }
+
+               if (is_flags_line(line_argv[0])) {
+                       add_flags(cmd, line_orig);
+                       continue;
+               }
+
+               if (is_rule_line(line_argv[0])) {
+                       add_rule(cmd, line_orig);
+                       continue;
+               }
+
+               if (is_id_line(line_argv[0])) {
+                       cmd->command_id = strdup(line_argv[1]);
+                       continue;
+               }
+
+               /* OO_FOO: ... */
+               if (is_oo_definition(line_argv[0])) {
+                       add_oo_definition_line(line_argv[0], line_orig);
+                       prev_was_oo_def = 1;
+                       prev_was_oo = 0;
+                       prev_was_op = 0;
+                       continue;
+               }
+
+               /* OO: ... */
+               if (is_oo_line(line_argv[0])) {
+                       add_optional_opt_line(cmd, line_argc, line_argv);
+                       prev_was_oo_def = 0;
+                       prev_was_oo = 1;
+                       prev_was_op = 0;
+                       continue;
+               }
+
+               /* OP: ... */
+               if (is_op_line(line_argv[0])) {
+                       add_optional_pos_line(cmd, line_argc, line_argv);
+                       prev_was_oo_def = 0;
+                       prev_was_oo = 0;
+                       prev_was_op = 1;
+                       continue;
+               }
+
+               /* IO: ... */
+               if (is_io_line(line_argv[0])) {
+                       add_ignore_opt_line(cmd, line_argc, line_argv);
+                       prev_was_oo = 0;
+                       prev_was_op = 0;
+                       continue;
+               }
+
+               /* handle OO_FOO:, OO:, OP: continuing on multiple lines */
+
+               if (prev_was_oo_def) {
+                       append_oo_definition_line(line_orig);
+                       continue;
+               }
+
+               if (prev_was_oo) {
+                       add_optional_opt_line(cmd, line_argc, line_argv);
+                       continue;
+               }
+
+               if (prev_was_op) {
+                       add_optional_pos_line(cmd, line_argc, line_argv);
+                       continue;
+               }
+       }
+
+       /*
+        * For usage.
+        * Looks at all variants of each command name and figures out
+        * which options are common to all variants (for compact output)
+        */
+        factor_common_options();
+
+       /*
+        * For usage.
+        * Predefined string of options common to all commands
+        * (for compact output)
+        */
+        include_optional_opt_args(&lvm_all, "OO_USAGE_COMMON");
+
+       return 1;
+}
+
+/* type_LVT to "type" */
+
+static const char *lvt_enum_to_name(int lvt_enum)
+{
+       return lvt_names[lvt_enum].name;
+}
+
+static void _print_usage_description(struct command *cmd)
+{
+       const char *desc = cmd->desc;
+       char buf[MAX_LINE] = {0};
+       int di = 0;
+       int bi = 0;
+
+       for (di = 0; di < strlen(desc); di++) {
+               if (!strncmp(&desc[di], "DESC:", 5)) {
+                       if (bi) {
+                               buf[bi] = '\0';
+                               printf("  %s\n", buf);
+                               memset(buf, 0, sizeof(buf));
+                               bi = 0;
+                       }
+                       /* skip DESC: */
+                       di += 5;
+                       continue;
+               }
+
+               if (!bi && desc[di] == ' ')
+                       continue;
+
+               buf[bi++] = desc[di];
+
+               if (bi == (MAX_LINE - 1))
+                       break;
+       }
+
+       if (bi) {
+               buf[bi] = '\0';
+               printf("  %s\n", buf);
+       }
+}
+
+static void print_usage_def(struct arg_def *def)
+{
+       int val_enum;
+       int lvt_enum;
+       int sep = 0;
+
+       for (val_enum = 0; val_enum < VAL_COUNT; val_enum++) {
+               if (def->val_bits & val_enum_to_bit(val_enum)) {
+
+                       if (val_enum == conststr_VAL)
+                               printf("%s", def->str);
+
+                       else if (val_enum == constnum_VAL)
+                               printf("%llu", (unsigned long long)def->num);
+
+                       else {
+                               if (sep) printf("|");
+
+                               if (!val_names[val_enum].usage)
+                                       printf("%s", val_names[val_enum].name);
+                               else
+                                       printf("%s", val_names[val_enum].usage);
+
+                               sep = 1;
+                       }
+
+                       if (val_enum == lv_VAL && def->lvt_bits) {
+                               for (lvt_enum = 1; lvt_enum < LVT_COUNT; lvt_enum++) {
+                                       if (lvt_bit_is_set(def->lvt_bits, lvt_enum))
+                                               printf("_%s", lvt_enum_to_name(lvt_enum));
+                               }
+                       }
+
+                       if ((val_enum == vg_VAL) && (def->flags & ARG_DEF_FLAG_NEW_VG))
+                               printf("_new");
+                       if ((val_enum == lv_VAL) && (def->flags & ARG_DEF_FLAG_NEW_LV))
+                               printf("_new");
+               }
+       }
+
+       if (def->flags & ARG_DEF_FLAG_MAY_REPEAT)
+               printf(" ...");
+}
+
+void print_usage(struct command *cmd)
+{
+       struct command_name *cname = find_command_name(cmd->name);
+       int onereq = (cmd->cmd_flags & CMD_FLAG_ONE_REQUIRED_OPT) ? 1 : 0;
+       int ro, rp, oo, op, opt_enum, first;
+
+       if (cmd->desc)
+               _print_usage_description(cmd);
+
+       printf("  %s", cmd->name);
+
+       if (cmd->ro_count) {
+               first = 1;
+
+               for (ro = 0; ro < cmd->ro_count; ro++) {
+                       if (onereq) {
+                               if (first)
+                                       printf("\n\t(");
+                               else
+                                       printf(",\n\t ");
+                               first = 0;
+                       }
+
+                       printf(" %s", opt_names[cmd->required_opt_args[ro].opt].long_opt);
+                       if (cmd->required_opt_args[ro].def.val_bits) {
+                               printf(" ");
+                               print_usage_def(&cmd->required_opt_args[ro].def);
+                       }
+               }
+               if (onereq)
+                       printf(" )\n");
+       }
+
+       if (cmd->rp_count) {
+               if (onereq)
+                       printf("\t");
+               for (rp = 0; rp < cmd->rp_count; rp++) {
+                       if (cmd->required_pos_args[rp].def.val_bits) {
+                               printf(" ");
+                               print_usage_def(&cmd->required_pos_args[rp].def);
+                       }
+               }
+       }
+
+       if (!cmd->oo_count)
+               goto op_count;
+
+       if (cmd->oo_count) {
+               first = 1;
+
+               for (oo = 0; oo < cmd->oo_count; oo++) {
+                       opt_enum = cmd->optional_opt_args[oo].opt;
+
+                       /*
+                        * Skip common opts in lvm_all and cname->common_options.
+                        */
+
+                       if (is_lvm_all_opt(opt_enum))
+                               continue;
+
+                       if ((cname->variants > 1) && cname->common_options[opt_enum])
+                               continue;
+
+                       if (first)
+                               printf("\n\t[");
+                       else
+                               printf(",\n\t ");
+                       first = 0;
+
+                       printf(" %s", opt_names[opt_enum].long_opt);
+                       if (cmd->optional_opt_args[oo].def.val_bits) {
+                               printf(" ");
+                               print_usage_def(&cmd->optional_opt_args[oo].def);
+                       }
+               }
+
+               if (first)
+                       printf("\n\t[");
+               else
+                       printf(",\n\t ");
+               printf(" COMMON_OPTIONS ]");
+       }
+
+ op_count:
+       if (!cmd->op_count)
+               goto done;
+
+       printf("\n\t[");
+
+       if (cmd->op_count) {
+               for (op = 0; op < cmd->op_count; op++) {
+                       if (cmd->optional_pos_args[op].def.val_bits) {
+                               printf(" ");
+                               print_usage_def(&cmd->optional_pos_args[op].def);
+                       }
+               }
+       }
+
+       printf(" ]");
+ done:
+       printf("\n");
+       return;
+}
+
+
+void print_usage_common(struct command_name *cname, struct command *cmd)
+{
+       int oo, opt_enum, first;
+
+       printf("  Common options:");
+
+       /*
+        * when there's more than one variant, options that
+        * are common to all commands with a common name.
+        */
+
+       if (cname->variants < 2)
+               goto all;
+
+       first = 1;
+
+       for (opt_enum = 0; opt_enum < ARG_COUNT; opt_enum++) {
+               if (!cname->common_options[opt_enum])
+                       continue;
+
+               if (is_lvm_all_opt(opt_enum))
+                       continue;
+
+               if (first)
+                       printf("\n\t[");
+               else
+                       printf(",\n\t ");
+               first = 0;
+
+               for (oo = 0; oo < cmd->oo_count; oo++) {
+                       if (cmd->optional_opt_args[oo].opt != opt_enum)
+                               continue;
+
+                       printf(" %s", opt_names[opt_enum].long_opt);
+                       if (cmd->optional_opt_args[oo].def.val_bits) {
+                               printf(" ");
+                               print_usage_def(&cmd->optional_opt_args[oo].def);
+                       }
+                       break;
+               }
+       }
+
+ all:
+       /* options that are common to all lvm commands */
+
+       for (oo = 0; oo < lvm_all.oo_count; oo++) {
+               opt_enum = lvm_all.optional_opt_args[oo].opt;
+
+               if (first)
+                       printf("\n\t[");
+               else
+                       printf(",\n\t ");
+               first = 0;
+
+               printf(" %s", opt_names[opt_enum].long_opt);
+               if (lvm_all.optional_opt_args[oo].def.val_bits) {
+                       printf(" ");
+                       print_usage_def(&lvm_all.optional_opt_args[oo].def);
+               }
+       }
+
+       printf(" ]\n");
+}
+
+#ifdef MAN_PAGE_GENERATOR
+
+static void print_val_man(const char *str)
+{
+       char *line;
+       char *line_argv[MAX_LINE_ARGC];
+       int line_argc;
+       int i;
+
+       if (!strcmp(str, "Number") ||
+           !strcmp(str, "String") ||
+           !strncmp(str, "VG", 2) ||
+           !strncmp(str, "LV", 2) ||
+           !strncmp(str, "PV", 2) ||
+           !strcmp(str, "Tag")) {
+               printf("\\fI%s\\fP", str);
+               return;
+       }
+
+       if (strstr(str, "Number[") || strstr(str, "]Number")) {
+               for (i = 0; i < strlen(str); i++) {
+                       if (str[i] == 'N')
+                               printf("\\fI");
+                       if (str[i] == 'r') {
+                               printf("%c", str[i]);
+                               printf("\\fP");
+                               continue;
+                       }
+                       printf("%c", str[i]);
+               }
+               return;
+       }
+
+       if (strstr(str, "|")) {
+               int len = strlen(str);
+               line = strdup(str);
+               split_line(line, &line_argc, line_argv, '|');
+               for (i = 0; i < line_argc; i++) {
+                       if (i) {
+                               printf("|");
+
+                               /* this is a hack to add a line break for
+                                  a long string of opt values */
+                               if ((len > 40) && (i >= (line_argc / 2) + 1)) {
+                                       printf("\n");
+                                       printf("       ");
+                                       len = 0;
+                               }
+                       }
+                       if (strstr(line_argv[i], "Number"))
+                               printf("\\fI%s\\fP", line_argv[i]);
+                       else
+                               printf("\\fB%s\\fP", line_argv[i]);
+               }
+               return;
+       }
+
+       printf("\\fB%s\\fP", str);
+}
+
+static void print_def_man(struct arg_def *def, int usage)
+{
+       int val_enum;
+       int lvt_enum;
+       int sep = 0;
+       int i;
+
+       for (val_enum = 0; val_enum < VAL_COUNT; val_enum++) {
+               if (def->val_bits & val_enum_to_bit(val_enum)) {
+
+                       if (val_enum == conststr_VAL) {
+                               printf("\\fB");
+                               printf("%s", def->str);
+                               printf("\\fP");
+                       }
+
+                       else if (val_enum == constnum_VAL) {
+                               printf("\\fB");
+                               printf("%llu", (unsigned long long)def->num);
+                               printf("\\fP");
+                       }
+
+                       else {
+                               if (sep) printf("|");
+
+                               if (!usage || !val_names[val_enum].usage) {
+                                       printf("\\fI");
+                                       printf("%s", val_names[val_enum].name);
+                                       printf("\\fP");
+                               } else {
+                                       print_val_man(val_names[val_enum].usage);
+                               }
+
+                               sep = 1;
+                       }
+
+                       if (val_enum == lv_VAL && def->lvt_bits) {
+                               printf("\\fI");
+                               for (lvt_enum = 1; lvt_enum < LVT_COUNT; lvt_enum++) {
+                                       if (lvt_bit_is_set(def->lvt_bits, lvt_enum))
+                                               printf("_%s", lvt_enum_to_name(lvt_enum));
+                               }
+                               printf("\\fP");
+                       }
+
+                       if ((val_enum == vg_VAL) && (def->flags & ARG_DEF_FLAG_NEW_VG)) {
+                               printf("\\fI");
+                               printf("_new");
+                               printf("\\fP");
+                       }
+                       if ((val_enum == lv_VAL) && (def->flags & ARG_DEF_FLAG_NEW_LV)) {
+                               printf("\\fI");
+                               printf("_new");
+                               printf("\\fP");
+                       }
+               }
+       }
+
+       if (def->flags & ARG_DEF_FLAG_MAY_REPEAT)
+               printf(" ...");
+}
+
+static char *man_long_opt_name(const char *cmdname, int opt_enum)
+{
+       static char long_opt_name[64];
+
+       memset(&long_opt_name, 0, sizeof(long_opt_name));
+
+       switch (opt_enum) {
+       case syncaction_ARG:
+               strncpy(long_opt_name, "--[raid]syncaction", 63);
+               break;
+       case writemostly_ARG:
+               strncpy(long_opt_name, "--[raid]writemostly", 63);
+               break;
+       case minrecoveryrate_ARG:
+               strncpy(long_opt_name, "--[raid]minrecoveryrate", 63);
+               break;
+       case maxrecoveryrate_ARG:
+               strncpy(long_opt_name, "--[raid]maxrecoveryrate", 63);
+               break;
+       case writebehind_ARG:
+               strncpy(long_opt_name, "--[raid]writebehind", 63);
+               break;
+       case vgmetadatacopies_ARG:
+               if (!strncmp(cmdname, "vg", 2))
+                       strncpy(long_opt_name, "--[vg]metadatacopies", 63);
+               else
+                       strncpy(long_opt_name, "--vgmetadatacopies", 63);
+               break;
+       case pvmetadatacopies_ARG:
+               if (!strncmp(cmdname, "pv", 2))
+                       strncpy(long_opt_name, "--[pv]metadatacopies", 63);
+               else
+                       strncpy(long_opt_name, "--pvmetadatacopies", 63);
+               break;
+       default:
+               strncpy(long_opt_name, opt_names[opt_enum].long_opt, 63);
+               break;
+       }
+
+       return long_opt_name;
+}
+
+void print_man_usage(char *lvmname, struct command *cmd)
+{
+       struct command_name *cname;
+       int onereq = (cmd->cmd_flags & CMD_FLAG_ONE_REQUIRED_OPT) ? 1 : 0;
+       int i, sep, ro, rp, oo, op, opt_enum;
+       int need_ro_indent_end = 0;
+
+       if (!(cname = find_command_name(cmd->name)))
+               return;
+
+       printf("\\fB%s\\fP", lvmname);
+
+       if (!onereq)
+               goto ro_normal;
+
+       /*
+        * one required option in a set, print as:
+        * ( -a|--a,
+        *   -b|--b,
+        *      --c,
+        *      --d )
+        *
+        * First loop through ro prints those with short opts,
+        * and the second loop prints those without short opts.
+        */
+
+       if (cmd->ro_count) {
+               printf("\n");
+               printf(".RS 4\n");
+               printf("(");
+
+               sep = 0;
+
+               /* print required options with a short opt */
+               for (ro = 0; ro < cmd->ro_count; ro++) {
+                       opt_enum = cmd->required_opt_args[ro].opt;
+
+                       if (!opt_names[opt_enum].short_opt)
+                               continue;
+
+                       if (sep) {
+                               printf(",");
+                               printf("\n.br\n");
+                               printf(" ");
+                       }
+
+                       if (opt_names[opt_enum].short_opt) {
+                               printf(" \\fB-%c\\fP|\\fB%s\\fP",
+                                      opt_names[opt_enum].short_opt,
+                                      man_long_opt_name(cmd->name, opt_enum));
+                       } else {
+                               printf("   ");
+                               printf(" \\fB%s\\fP", man_long_opt_name(cmd->name, opt_enum));
+                       }
+
+                       if (cmd->required_opt_args[ro].def.val_bits) {
+                               printf(" ");
+                               print_def_man(&cmd->required_opt_args[ro].def, 1);
+                       }
+
+                       sep++;
+               }
+
+               /* print required options without a short opt */
+               for (ro = 0; ro < cmd->ro_count; ro++) {
+                       opt_enum = cmd->required_opt_args[ro].opt;
+
+                       if (opt_names[opt_enum].short_opt)
+                               continue;
+
+                       if (sep) {
+                               printf(",");
+                               printf("\n.br\n");
+                               printf(" ");
+                       }
+
+                       printf("   ");
+                       printf(" \\fB%s\\fP", man_long_opt_name(cmd->name, opt_enum));
+
+                       if (cmd->required_opt_args[ro].def.val_bits) {
+                               printf(" ");
+                               print_def_man(&cmd->required_opt_args[ro].def, 1);
+                       }
+
+                       sep++;
+               }
+
+               printf(" )\n");
+               printf(".RE\n");
+       }
+
+       /* print required position args on a new line after the onereq set */
+       if (cmd->rp_count) {
+               printf(".RS 4\n");
+               for (rp = 0; rp < cmd->rp_count; rp++) {
+                       if (cmd->required_pos_args[rp].def.val_bits) {
+                               printf(" ");
+                               print_def_man(&cmd->required_pos_args[rp].def, 1);
+                       }
+               }
+
+               printf("\n");
+               printf(".RE\n");
+       } else {
+               /* printf("\n"); */
+       }
+
+       printf(".br\n");
+       goto oo_count;
+
+ ro_normal:
+
+       /*
+        * all are required options, print as:
+        * -a|--aaa <val> -b|--bbb <val>
+        */
+
+       if (cmd->ro_count) {
+               sep = 0;
+
+               for (ro = 0; ro < cmd->ro_count; ro++) {
+
+                       /* avoid long line wrapping */
+                       if ((cmd->ro_count > 2) && (sep == 2)) {
+                               printf("\n.RS 5\n");
+                               need_ro_indent_end = 1;
+                       }
+
+                       opt_enum = cmd->required_opt_args[ro].opt;
+
+                       if (opt_names[opt_enum].short_opt) {
+                               printf(" \\fB-%c\\fP|\\fB%s\\fP",
+                                      opt_names[opt_enum].short_opt,
+                                      man_long_opt_name(cmd->name, opt_enum));
+                       } else {
+                               printf(" \\fB%s\\fP", opt_names[cmd->required_opt_args[ro].opt].long_opt);
+                       }
+
+                       if (cmd->required_opt_args[ro].def.val_bits) {
+                               printf(" ");
+                               print_def_man(&cmd->required_opt_args[ro].def, 1);
+                       }
+
+                       sep++;
+               }
+       }
+
+       /* print required position args on the same line as the required options */
+       if (cmd->rp_count) {
+               for (rp = 0; rp < cmd->rp_count; rp++) {
+                       if (cmd->required_pos_args[rp].def.val_bits) {
+                               printf(" ");
+                               print_def_man(&cmd->required_pos_args[rp].def, 1);
+                       }
+               }
+
+               printf("\n");
+       } else {
+               printf("\n");
+       }
+
+       if (need_ro_indent_end)
+               printf(".RE\n");
+
+       printf(".br\n");
+
+ oo_count:
+       if (!cmd->oo_count)
+               goto op_count;
+
+       sep = 0;
+
+       if (cmd->oo_count) {
+               printf(".RS 4\n");
+               printf("[");
+
+               /* print optional options with short opts */
+
+               for (oo = 0; oo < cmd->oo_count; oo++) {
+                       opt_enum = cmd->optional_opt_args[oo].opt;
+
+                       if (!opt_names[opt_enum].short_opt)
+                               continue;
+
+                       if (is_lvm_all_opt(opt_enum))
+                               continue;
+
+                       if ((cname->variants > 1) && cname->common_options[opt_enum])
+                               continue;
+
+                       if (sep) {
+                               printf(",");
+                               printf("\n.br\n");
+                               printf(" ");
+                       }
+
+                       printf(" \\fB-%c\\fP|\\fB%s\\fP",
+                               opt_names[opt_enum].short_opt,
+                               man_long_opt_name(cmd->name, opt_enum));
+
+                       if (cmd->optional_opt_args[oo].def.val_bits) {
+                               printf(" ");
+                               print_def_man(&cmd->optional_opt_args[oo].def, 1);
+                       }
+                       sep = 1;
+               }
+
+               /* print optional options without short opts */
+
+               for (oo = 0; oo < cmd->oo_count; oo++) {
+                       opt_enum = cmd->optional_opt_args[oo].opt;
+
+                       if (opt_names[opt_enum].short_opt)
+                               continue;
+
+                       if (is_lvm_all_opt(opt_enum))
+                               continue;
+
+                       if ((cname->variants > 1) && cname->common_options[opt_enum])
+                               continue;
+
+                       if (sep) {
+                               printf(",");
+                               printf("\n.br\n");
+                               printf(" ");
+                       }
+
+                       /* space alignment without short opt */
+                       printf("   ");
+
+                       printf(" \\fB%s\\fP", man_long_opt_name(cmd->name, opt_enum));
+
+                       if (cmd->optional_opt_args[oo].def.val_bits) {
+                               printf(" ");
+                               print_def_man(&cmd->optional_opt_args[oo].def, 1);
+                       }
+                       sep = 1;
+               }
+
+               if (sep) {
+                       printf(",");
+                       printf("\n.br\n");
+                       printf(" ");
+                       /* space alignment without short opt */
+                       printf("   ");
+               }
+               printf(" COMMON_OPTIONS");
+               printf(" ]\n");
+               printf(".RE\n");
+               printf(".br\n");
+       }
+
+ op_count:
+       if (!cmd->op_count)
+               goto done;
+
+       printf(".RS 4\n");
+       printf("[");
+
+       if (cmd->op_count) {
+               for (op = 0; op < cmd->op_count; op++) {
+                       if (cmd->optional_pos_args[op].def.val_bits) {
+                               printf(" ");
+                               print_def_man(&cmd->optional_pos_args[op].def, 1);
+                       }
+               }
+       }
+
+       printf(" ]\n");
+       printf(".RE\n");
+
+ done:
+       printf("\n");
+}
+
+/*
+ * common options listed in the usage section.
+ *
+ * For commands with only one variant, this is only
+ * the options which are common to all lvm commands
+ * (in lvm_all, see is_lvm_all_opt).
+ *
+ * For commands with more than one variant, this
+ * is the set of options common to all variants
+ * (in cname->common_options), (which obviously
+ * includes the options common to all lvm commands.)
+ *
+ * List ordering:
+ * options with short+long names, alphabetically,
+ * then options with only long names, alphabetically
+ */
+
+void print_man_usage_common(struct command *cmd)
+{
+       struct command_name *cname;
+       int i, sep, ro, rp, oo, op, opt_enum;
+
+       if (!(cname = find_command_name(cmd->name)))
+               return;
+
+       sep = 0;
+
+       printf(".RS 4\n");
+       printf("[");
+
+       /* print those with short opts */
+       for (i = 0; i < ARG_COUNT; i++) {
+               opt_enum = opt_names_alpha[i]->opt_enum;
+
+               if (!cname->common_options[opt_enum])
+                       continue;
+
+               if (!opt_names[opt_enum].short_opt)
+                       continue;
+
+               if ((cname->variants < 2) && !is_lvm_all_opt(opt_enum))
+                       continue;
+
+               if (sep) {
+                       printf(",");
+                       printf("\n.br\n");
+                       printf(" ");
+               }
+
+               for (oo = 0; oo < cmd->oo_count; oo++) {
+                       if (cmd->optional_opt_args[oo].opt != opt_enum)
+                               continue;
+
+                       printf(" \\fB-%c\\fP|\\fB%s\\fP",
+                               opt_names[opt_enum].short_opt,
+                               man_long_opt_name(cmd->name, opt_enum));
+
+                       if (cmd->optional_opt_args[oo].def.val_bits) {
+                               printf(" ");
+                               print_def_man(&cmd->optional_opt_args[oo].def, 1);
+                       }
+                       sep = 1;
+                       break;
+               }
+
+       }
+
+       /* print those without short opts */
+       for (i = 0; i < ARG_COUNT; i++) {
+               opt_enum = opt_names_alpha[i]->opt_enum;
+
+               if (!cname->common_options[opt_enum])
+                       continue;
+
+               if (opt_names[opt_enum].short_opt)
+                       continue;
+
+               if ((cname->variants < 2) && !is_lvm_all_opt(opt_enum))
+                       continue;
+
+               if (sep) {
+                       printf(",");
+                       printf("\n.br\n");
+                       printf(" ");
+               }
+
+               for (oo = 0; oo < cmd->oo_count; oo++) {
+                       if (cmd->optional_opt_args[oo].opt != opt_enum)
+                               continue;
+
+                       /* space alignment without short opt */
+                       printf("   ");
+
+                       printf(" \\fB%s\\fP", man_long_opt_name(cmd->name, opt_enum));
+
+                       if (cmd->optional_opt_args[oo].def.val_bits) {
+                               printf(" ");
+                               print_def_man(&cmd->optional_opt_args[oo].def, 1);
+                       }
+                       sep = 1;
+                       break;
+               }
+       }
+
+       printf(" ]\n");
+       return;
+}
+
+/*
+ * Format of description, when different command names have
+ * different descriptions:
+ *
+ * "#cmdname1"
+ * "text foo goes here"
+ * "a second line of text."
+ * "#cmdname2"
+ * "text bar goes here"
+ * "another line of text."
+ *
+ * When called for cmdname2, this function should just print:
+ *
+ * "text bar goes here"
+ * "another line of text."
+ */
+
+static void print_man_option_desc(struct command_name *cname, int opt_enum)
+{
+       const char *desc = opt_names[opt_enum].desc;
+       char buf[DESC_LINE];
+       int started_cname = 0;
+       int line_count = 0;
+       int di, bi = 0;
+
+       if (desc[0] != '#') {
+               printf("%s", desc);
+               return;
+       }
+
+       for (di = 0; di < strlen(desc); di++) {
+               buf[bi++] = desc[di];
+
+               if (bi == DESC_LINE) {
+                       log_error("Parsing command defs: print_man_option_desc line too long");
+                       exit(EXIT_FAILURE);
+               }
+
+               if (buf[bi-1] != '\n')
+                       continue;
+
+               if (buf[0] != '#') {
+                       if (started_cname) {
+                               printf("%s", buf);
+                               line_count++;
+                       }
+
+                       memset(buf, 0, sizeof(buf));
+                       bi = 0;
+                       continue;
+               }
+
+               /* Line starting with #cmdname */
+
+               /*
+                * Must be starting a new command name.
+                * If no lines have been printed, multiple command names
+                * are using the same text. If lines have been printed,
+                * then the start of a new command name means the end
+                * of text for the current command name.
+                */
+               if (line_count && started_cname)
+                       return;
+
+               if (!strncmp(buf + 1, cname->name, strlen(cname->name))) {
+                       /* The start of our command name. */
+                       started_cname = 1;
+                       memset(buf, 0, sizeof(buf));
+                       bi = 0;
+               } else {
+                       /* The start of another command name. */
+                       memset(buf, 0, sizeof(buf));
+                       bi = 0;
+               }
+       }
+
+       if (bi && started_cname)
+               printf("%s", buf);
+}
+
+/*
+ * Print a list of all options names for a given
+ * command name, listed by:
+ * options with short+long names, alphabetically,
+ * then options with only long names, alphabetically
+ */
+
+void print_man_all_options_list(struct command_name *cname)
+{
+       int opt_enum, val_enum;
+       int sep = 0;
+       int i;
+
+       /* print those with both short and long opts */
+       for (i = 0; i < ARG_COUNT; i++) {
+               opt_enum = opt_names_alpha[i]->opt_enum;
+
+
+               if (!cname->all_options[opt_enum])
+                       continue;
+
+               if (!opt_names[opt_enum].short_opt)
+                       continue;
+
+               if (sep)
+                       printf("\n.br\n");
+
+               printf(" \\fB-%c\\fP|\\fB%s\\fP",
+                       opt_names[opt_enum].short_opt,
+                       man_long_opt_name(cname->name, opt_enum));
+
+               val_enum = opt_names[opt_enum].val_enum;
+
+               if (!val_names[val_enum].fn) {
+                       /* takes no arg */
+               } else if (!val_names[val_enum].usage) {
+                       printf(" ");
+                       printf("\\fI");
+                       printf("%s", val_names[val_enum].name);
+                       printf("\\fP");
+               } else {
+                       printf(" ");
+                       print_val_man(val_names[val_enum].usage);
+               }
+
+               sep = 1;
+       }
+
+       /* print those without short opts */
+       for (i = 0; i < ARG_COUNT; i++) {
+               opt_enum = opt_names_alpha[i]->opt_enum;
+
+               if (!cname->all_options[opt_enum])
+                       continue;
+
+               if (opt_names[opt_enum].short_opt)
+                       continue;
+
+               if (sep)
+                       printf("\n.br\n");
+
+               /* space alignment without short opt */
+               printf("   ");
+
+               printf(" \\fB%s\\fP", man_long_opt_name(cname->name, opt_enum));
+
+               val_enum = opt_names[opt_enum].val_enum;
+
+               if (!val_names[val_enum].fn) {
+                       /* takes no arg */
+               } else if (!val_names[val_enum].usage) {
+                       printf(" ");
+                       printf("\\fI");
+                       printf("%s", val_names[val_enum].name);
+                       printf("\\fP");
+               } else {
+                       printf(" ");
+                       print_val_man(val_names[val_enum].usage);
+               }
+
+               sep = 1;
+       }
+}
+
+/*
+ * All options used for a given command name, along with descriptions.
+ * listed in order of:
+ * 1. options that are not common to all lvm commands, alphabetically
+ * 2. options common to all lvm commands, alphabetically
+ */
+
+void print_man_all_options_desc(struct command_name *cname)
+{
+       int opt_enum, val_enum;
+       int print_common = 0;
+       int sep = 0;
+       int i;
+
+ again:
+       /*
+        * Loop 1: print options that are not common to all lvm commands.
+        * Loop 2: print options common to all lvm commands (lvm_all)
+        */
+
+       for (i = 0; i < ARG_COUNT; i++) {
+               opt_enum = opt_names_alpha[i]->opt_enum;
+
+               if (!cname->all_options[opt_enum])
+                       continue;
+
+               if (!print_common && is_lvm_all_opt(opt_enum))
+                       continue;
+
+               if (print_common && !is_lvm_all_opt(opt_enum))
+                       continue;
+
+               printf("\n.TP\n");
+
+               if (opt_names[opt_enum].short_opt) {
+                       printf("\\fB-%c\\fP|\\fB%s\\fP",
+                              opt_names[opt_enum].short_opt,
+                              man_long_opt_name(cname->name, opt_enum));
+               } else {
+                       printf("\\fB%s\\fP", man_long_opt_name(cname->name, opt_enum));
+               }
+
+               val_enum = opt_names[opt_enum].val_enum;
+
+               if (!val_names[val_enum].fn) {
+                       /* takes no arg */
+               } else if (!val_names[val_enum].usage) {
+                       printf(" ");
+                       printf("\\fI");
+                       printf("%s", val_names[val_enum].name);
+                       printf("\\fP");
+               } else {
+                       printf(" ");
+                       print_val_man(val_names[val_enum].usage);
+               }
+
+               if (opt_names[opt_enum].desc) {
+                       printf("\n");
+                       printf(".br\n");
+                       print_man_option_desc(cname, opt_enum);
+               }
+
+               sep = 1;
+       }
+
+       if (!print_common) {
+               print_common = 1;
+               goto again;
+       }
+}
+
+void print_desc_man(const char *desc)
+{
+       char buf[DESC_LINE] = {0};
+       int di = 0;
+       int bi = 0;
+
+       for (di = 0; di < strlen(desc); di++) {
+               if (desc[di] == '\0')
+                       break;
+               if (desc[di] == '\n')
+                       continue;
+
+               if (!strncmp(&desc[di], "DESC:", 5)) {
+                       if (bi) {
+                               printf("%s\n", buf);
+                               printf(".br\n");
+                               memset(buf, 0, sizeof(buf));
+                               bi = 0;
+                       }
+                       di += 5;
+                       continue;
+               }
+
+               if (!bi && desc[di] == ' ')
+                       continue;
+
+               buf[bi++] = desc[di];
+
+               if (bi == (DESC_LINE - 1))
+                       break;
+       }
+
+       if (bi) {
+               printf("%s\n", buf);
+               printf(".br\n");
+       }
+}
+
+static char *upper_command_name(char *str)
+{
+       static char str_upper[32];
+       int i = 0;
+
+       while (*str) {
+               str_upper[i++] = toupper(*str);
+               str++;
+       }
+       str_upper[i] = '\0';
+       return str_upper;
+}
+
+static void include_description_file(char *name, char *des_file)
+{
+       char buf[1024 * 1024];
+       int fd;
+
+       memset(buf, 0, sizeof(buf));
+       
+       fd = open(des_file, O_RDONLY);
+
+       if (fd < 0)
+               return;
+
+       read(fd, buf, sizeof(buf) - 1);
+
+       printf(".SH DESCRIPTION\n");
+       printf("%s\n", buf);
+
+       close(fd);
+}
+
+void print_man(char *name, char *des_file, int include_primary, int include_secondary)
+{
+       struct command_name *cname;
+       struct command *cmd, *prev_cmd = NULL;
+       char *lvmname = name;
+       const char *desc;
+       int i, j, ro, rp, oo, op;
+
+       if (!strncmp(name, "lvm-", 4))
+               name += 4;
+
+       cname = find_command_name(name);
+
+       printf(".TH %s 8 \"LVM TOOLS #VERSION#\" \"Sistina Software UK\"\n",
+               upper_command_name(lvmname));
+
+       for (i = 0; i < COMMAND_COUNT; i++) {
+
+               cmd = &commands[i];
+
+               if (prev_cmd && strcmp(prev_cmd->name, cmd->name)) {
+                       printf("Common options:\n");
+                       printf(".\n");
+                       print_man_usage_common(prev_cmd);
+
+                       printf("\n");
+                       printf(".SH OPTIONS\n");
+                       printf(".br\n");
+                       print_man_all_options_desc(cname);
+
+                       prev_cmd = NULL;
+               }
+
+               if ((cmd->cmd_flags & CMD_FLAG_SECONDARY_SYNTAX) && !include_secondary)
+                       continue;
+
+               if (!(cmd->cmd_flags & CMD_FLAG_SECONDARY_SYNTAX) && !include_primary)
+                       continue;
+
+               if (name && strcmp(name, cmd->name))
+                       continue;
+
+               if (!prev_cmd || strcmp(prev_cmd->name, cmd->name)) {
+                       printf(".SH NAME\n");
+                       printf(".\n");
+                       if (cname->desc)
+                               printf("%s \\- %s\n", lvmname, cname->desc);
+                       else
+                               printf("%s\n", lvmname);
+                       printf(".P\n");
+
+                       printf(".\n");
+                       printf(".SH SYNOPSIS\n");
+                       printf(".br\n");
+                       printf(".P\n");
+                       printf(".\n");
+                       prev_cmd = cmd;
+
+                       if (!(cname = find_command_name(cmd->name)))
+                               return;
+
+                       if (cname->variant_has_ro && cname->variant_has_rp)
+                               printf("\\fB%s\\fP \\fIrequired_option_args\\fP \\fIrequired_position_args\\fP\n", lvmname);
+                       else if (cname->variant_has_ro && !cname->variant_has_rp)
+                               printf("\\fB%s\\fP \\fIrequired_option_args\\fP\n", lvmname);
+                       else if (!cname->variant_has_ro && cname->variant_has_rp)
+                               printf("\\fB%s\\fP \\fIrequired_position_args\\fP\n", lvmname);
+                       else if (!cname->variant_has_ro && !cname->variant_has_rp)
+                               printf("\\fB%s\\fP\n", lvmname);
+
+                       printf(".br\n");
+
+                       if (cname->variant_has_oo) {
+                               printf("    [ \\fIoptional_option_args\\fP ]\n");
+                               printf(".br\n");
+                       }
+
+                       if (cname->variant_has_op) {
+                               printf("    [ \\fIoptional_position_args\\fP ]\n");
+                               printf(".br\n");
+                       }
+
+                       printf(".P\n");
+                       printf("\n");
+
+                       /* listing them all when there's only 1 or 2 is just repetative */
+                       if (cname->variants > 2) {
+                               printf(".P\n");
+                               print_man_all_options_list(cname);
+                               printf("\n");
+                               printf(".P\n");
+                               printf("\n");
+                       }
+
+                       if (des_file) {
+                               include_description_file(lvmname, des_file);
+                               printf(".P\n");
+                       }
+
+                       printf(".SH USAGE\n");
+                       printf(".br\n");
+                       printf(".P\n");
+                       printf(".\n");
+               }
+
+               if (cmd->desc) {
+                       print_desc_man(cmd->desc);
+                       printf(".P\n");
+               }
+
+               print_man_usage(lvmname, cmd);
+
+               if (i == (COMMAND_COUNT - 1)) {
+                       printf("Common options:\n");
+                       printf(".\n");
+                       print_man_usage_common(cmd);
+
+                       printf("\n");
+                       printf(".SH OPTIONS\n");
+                       printf(".br\n");
+                       print_man_all_options_desc(cname);
+
+               }
+
+               printf("\n");
+               continue;
+       }
+}
+
+int main(int argc, char *argv[])
+{
+       memset(&commands, 0, sizeof(commands));
+
+       if (argc < 2) {
+               log_error("Usage: %s <command> [/path/to/description-file]", argv[0]);
+               exit(EXIT_FAILURE);
+       }
+
+       define_commands();
+
+       print_man(argv[1], (argc > 2) ? argv[2] : NULL, 1, 1);
+
+       return 0;
+}
+
+#endif
index c9be260b281ab008a1f60825eb8ccd29f52ac870..b3fae030ce288aa6655afd0f907d754a144a85d6 100644 (file)
@@ -22,21 +22,33 @@ struct cmd_context;
 typedef int (*command_fn) (struct cmd_context *cmd, int argc, char **argv);
 
 /* new per-command-line-id functions */
-typedef int (*command_line_fn) (struct cmd_context *cmd, int argc, char **argv);
+typedef int (*command_id_fn) (struct cmd_context *cmd, int argc, char **argv);
 
 struct command_function {
-       int command_line_enum;
-       command_line_fn fn;
+       int command_enum;
+       command_id_fn fn;
 };
 
+#define MAX_COMMAND_NAMES 64
+
 struct command_name {
        const char *name;
        const char *desc; /* general command description from commands.h */
        unsigned int flags;
+       command_fn fn; /* old style */
 
        /* union of {required,optional}_opt_args for all commands with this name */
-       int valid_args[ARG_COUNT];
+       int valid_args[ARG_COUNT]; /* used for getopt */
        int num_args;
+
+       /* the following are for generating help and man page output */
+       int common_options[ARG_COUNT]; /* options common to all defs */
+       int all_options[ARG_COUNT];    /* union of options from all defs */
+       int variants;        /* number of command defs with this command name */
+       int variant_has_ro;  /* do variants use required_opt_args ? */
+       int variant_has_rp;  /* do variants use required_pos_args ? */
+       int variant_has_oo;  /* do variants use optional_opt_args ? */
+       int variant_has_op;  /* do variants use optional_pos_args ? */
 };
 
 /*
@@ -158,14 +170,13 @@ struct cmd_rule {
 /* a register of the lvm commands */
 struct command {
        const char *name;
-       const char *desc; /* specific command description from command-lines.h */
-       const char *usage; /* excludes common options like --help, --debug */
-       const char *usage_common; /* includes commmon options like --help, --debug */
-       const char *command_line_id;
-       int command_line_enum; /* <command_line_id>_CMD */
+       const char *desc; /* specific command description from command-lines.in */
+       const char *command_id; /* ID string in command-lines.in */
+       int command_enum; /* <command_id>_CMD */
+       int command_index; /* position in commands[] */
 
-       command_fn fn;                      /* old style */
        struct command_function *functions; /* new style */
+       command_fn fn;                      /* old style */
 
        unsigned int cmd_flags; /* CMD_FLAG_ */
 
@@ -198,4 +209,9 @@ struct command {
        int pos_count; /* temp counter used by create-command */
 };
 
+int define_commands(void);
+int command_id_to_enum(const char *str);
+void print_usage(struct command *cmd);
+void print_usage_common(struct command_name *cname, struct command *cmd);
+
 #endif
index b75d0581d7d4358538ecba7ab34d06c98d328bc7..1c00b76f156c90cfea0c5c049cbf85f95b0b46fa 100644 (file)
@@ -1016,9 +1016,7 @@ static int _lvchange_properties_check(struct cmd_context *cmd,
 {
        if (!lv_is_visible(lv)) {
                if (lv_is_named_arg)
-                       log_error("Operation not permitted (%s %d) on hidden LV %s.",
-                                 cmd->command->command_line_id, cmd->command->command_line_enum,
-                                 display_lvname(lv));
+                       log_error("Operation not permitted on hidden LV %s.", display_lvname(lv));
                return 0;
        }
 
@@ -1129,9 +1127,7 @@ static int _lvchange_activate_check(struct cmd_context *cmd,
 {
        if (!lv_is_visible(lv)) {
                if (lv_is_named_arg)
-                       log_error("Operation not permitted (%s %d) on hidden LV %s.",
-                                 cmd->command->command_line_id, cmd->command->command_line_enum,
-                                 display_lvname(lv));
+                       log_error("Operation not permitted on hidden LV %s.", display_lvname(lv));
                return 0;
        }
 
@@ -1185,9 +1181,7 @@ static int _lvchange_refresh_check(struct cmd_context *cmd,
 {
        if (!lv_is_visible(lv)) {
                if (lv_is_named_arg)
-                       log_error("Operation not permitted (%s %d) on hidden LV %s.",
-                                 cmd->command->command_line_id, cmd->command->command_line_enum,
-                                 display_lvname(lv));
+                       log_error("Operation not permitted on hidden LV %s.", display_lvname(lv));
                return 0;
        }
 
@@ -1367,9 +1361,7 @@ static int _lvchange_persistent_check(struct cmd_context *cmd,
 {
        if (!lv_is_visible(lv)) {
                if (lv_is_named_arg)
-                       log_error("Operation not permitted (%s %d) on hidden LV %s.",
-                                 cmd->command->command_line_id, cmd->command->command_line_enum,
-                                 display_lvname(lv));
+                       log_error("Operation not permitted on hidden LV %s.", display_lvname(lv));
                return 0;
        }
 
@@ -1385,8 +1377,8 @@ int lvchange_persistent_cmd(struct cmd_context *cmd, int argc, char **argv)
 
 int lvchange(struct cmd_context *cmd, int argc, char **argv)
 {
-       log_error(INTERNAL_ERROR "Missing function for command definition %s.",
-                 cmd->command->command_line_id);
+       log_error(INTERNAL_ERROR "Missing function for command definition %d:%s.",
+                 cmd->command->command_index, cmd->command->command_id);
        return ECMD_FAILED;
 }
 
index 2ccf26495b1b6ba8ba1e73948d6805f8352ca538..75bdcb97eb651365927cb520292b3c96ae5bfa59 100644 (file)
@@ -17,7 +17,6 @@
 #include "polldaemon.h"
 #include "lv_alloc.h"
 #include "lvconvert_poll.h"
-#include "command-lines-count.h"
 
 typedef enum {
        /* Split:
@@ -3764,7 +3763,7 @@ static int _lvconvert_to_pool_single(struct cmd_context *cmd,
        int to_thinpool = 0;
        int to_cachepool = 0;
 
-       switch (cmd->command->command_line_enum) {
+       switch (cmd->command->command_enum) {
        case lvconvert_to_thinpool_CMD:
                to_thinpool = 1;
                break;
@@ -3813,7 +3812,7 @@ int lvconvert_to_pool_noarg_cmd(struct cmd_context *cmd, int argc, char **argv)
        char *pool_data_name;
        int i, p;
 
-       switch (cmd->command->command_line_enum) {
+       switch (cmd->command->command_enum) {
        case lvconvert_to_thinpool_noarg_CMD:
                pool_data_name = (char *)arg_str_value(cmd, thinpool_ARG, NULL);
                new_command = get_command(lvconvert_to_thinpool_CMD);
@@ -3827,9 +3826,9 @@ int lvconvert_to_pool_noarg_cmd(struct cmd_context *cmd, int argc, char **argv)
                return 0;
        };
 
-       log_debug("Changing command line id %s %d to standard form %s %d",
-                 cmd->command->command_line_id, cmd->command->command_line_enum,
-                 new_command->command_line_id, new_command->command_line_enum);
+       log_debug("Changing command %d:%s to standard form %d:%s",
+                 cmd->command->command_index, cmd->command->command_id,
+                 new_command->command_index, new_command->command_id);
 
        /* Make the LV the first position arg. */
 
@@ -4092,7 +4091,7 @@ int lvconvert_swap_pool_metadata_noarg_cmd(struct cmd_context *cmd, int argc, ch
        struct command *new_command;
        char *pool_name;
 
-       switch (cmd->command->command_line_enum) {
+       switch (cmd->command->command_enum) {
        case lvconvert_swap_thinpool_metadata_CMD:
                pool_name = (char *)arg_str_value(cmd, thinpool_ARG, NULL);
                break;
@@ -4106,9 +4105,9 @@ int lvconvert_swap_pool_metadata_noarg_cmd(struct cmd_context *cmd, int argc, ch
 
        new_command = get_command(lvconvert_swap_pool_metadata_CMD);
 
-       log_debug("Changing command line id %s %d to standard form %s %d",
-                 cmd->command->command_line_id, cmd->command->command_line_enum,
-                 new_command->command_line_id, new_command->command_line_enum);
+       log_debug("Changing command %d:%s to standard form %d:%s",
+                 cmd->command->command_index, cmd->command->command_id,
+                 new_command->command_index, new_command->command_id);
 
        /* Make the LV the first position arg. */
 
@@ -4172,7 +4171,7 @@ static int _lvconvert_split_cachepool_single(struct cmd_context *cmd,
                return ECMD_FAILED;
        }
 
-       switch (cmd->command->command_line_enum) {
+       switch (cmd->command->command_enum) {
        case lvconvert_split_and_keep_cachepool_CMD:
                ret = _lvconvert_split_and_keep_cachepool(cmd, cache_lv, cachepool_lv);
                break;
@@ -4193,7 +4192,7 @@ static int _lvconvert_split_cachepool_single(struct cmd_context *cmd,
 
 int lvconvert_split_cachepool_cmd(struct cmd_context *cmd, int argc, char **argv)
 {
-       if (cmd->command->command_line_enum == lvconvert_split_and_remove_cachepool_CMD) {
+       if (cmd->command->command_enum == lvconvert_split_and_remove_cachepool_CMD) {
                cmd->handles_missing_pvs = 1;
                cmd->partial_activation = 1;
        }
@@ -4272,8 +4271,7 @@ static int _lvconvert_raid_types_check(struct cmd_context *cmd, struct logical_v
        case thinpool_LVT:
        case cachepool_LVT:
        case snapshot_LVT:
-               log_error("Operation not permitted (%s %d) on LV %s type %s.",
-                         cmd->command->command_line_id, cmd->command->command_line_enum,
+               log_error("Operation not permitted on LV %s type %s.",
                          display_lvname(lv), lvtype ? lvtype->name : "unknown");
                return 0;
        }
@@ -4281,9 +4279,7 @@ static int _lvconvert_raid_types_check(struct cmd_context *cmd, struct logical_v
        return 1;
 
  fail_hidden:
-       log_error("Operation not permitted (%s %d) on hidden LV %s.",
-                 cmd->command->command_line_id, cmd->command->command_line_enum,
-                 display_lvname(lv));
+       log_error("Operation not permitted on hidden LV %s.", display_lvname(lv));
        return 0;
 }
 
@@ -4342,9 +4338,7 @@ static int _lvconvert_visible_check(struct cmd_context *cmd, struct logical_volu
                        int lv_is_named_arg)
 {
        if (!lv_is_visible(lv)) {
-               log_error("Operation not permitted (%s %d) on hidden LV %s.",
-                         cmd->command->command_line_id, cmd->command->command_line_enum,
-                         display_lvname(lv));
+               log_error("Operation not permitted on hidden LV %s.", display_lvname(lv));
                return 0;
        }
 
@@ -4547,8 +4541,8 @@ int lvconvert_merge_cmd(struct cmd_context *cmd, int argc, char **argv)
 
 int lvconvert(struct cmd_context *cmd, int argc, char **argv)
 {
-       log_error(INTERNAL_ERROR "Missing function for command definition %s.",
-                 cmd->command->command_line_id);
+       log_error(INTERNAL_ERROR "Missing function for command definition %d:%s.",
+                 cmd->command->command_index, cmd->command->command_id);
        return ECMD_FAILED;
 }
 
index 4039dd9e69e6579f1f470176a631696fff8d07ad..121a9dd434f32c4785d9a8518cb39171e7ca88d9 100644 (file)
@@ -49,7 +49,6 @@ extern char *optarg;
 #  define OPTIND_INIT 1
 #endif
 
-#include "command-lines-count.h"
 
 /*
  * Table of valid --option values.
@@ -69,16 +68,6 @@ static struct arg_props _arg_props[ARG_COUNT + 1] = {
 #undef arg
 };
 
-/*
- * Table of valid command names
- */
-#define MAX_COMMAND_NAMES 64
-struct command_name command_names[MAX_COMMAND_NAMES] = {
-#define xx(a, b, c...) { # a, b, c },
-#include "commands.h"
-#undef xx
-};
-
 /*
  * Table of LV properties
  */
@@ -97,11 +86,20 @@ static struct lv_types _lv_types[LVT_COUNT + 1] = {
 #undef lvt
 };
 
+/*
+ * Table of command names
+ */
+struct command_name command_names[MAX_COMMAND_NAMES] = {
+#define xx(a, b, c...) { # a, b, c, a},
+#include "commands.h"
+#undef xx
+};
 
 /*
- * Table of valid command lines
+ * Table of commands (as defined in command-lines.in)
  */
-static struct command commands[COMMAND_COUNT];
+struct command commands[COMMAND_COUNT];
+
 static struct cmdline_context _cmdline;
 
 /*
@@ -111,7 +109,7 @@ static struct cmdline_context _cmdline;
  * to use these functions instead of the old per-command-name function.
  * For now, any command id not included here uses the old command fn.
  */
-struct command_function command_functions[COMMAND_ID_COUNT] = {
+struct command_function command_functions[CMD_COUNT] = {
        { lvmconfig_general_CMD, lvmconfig },
        { lvchange_properties_CMD, lvchange_properties_cmd },
        { lvchange_resync_CMD, lvchange_resync_cmd },
@@ -1061,7 +1059,7 @@ static void _set_valid_args_for_command_name(int ci)
        command_names[ci].num_args = num_args;
 }
 
-static struct command_name *_find_command_name(const char *name)
+static struct command_name *find_command_name(const char *name)
 {
        int i;
        
@@ -1074,39 +1072,50 @@ static struct command_name *_find_command_name(const char *name)
        return NULL;
 }
 
-static struct command_function *_find_command_function(int command_line_enum)
+static struct command_function *_find_command_id_function(int command_enum)
 {
        int i;
 
-       if (!command_line_enum)
+       if (!command_enum)
                return NULL;
 
-       for (i = 0; i < COMMAND_ID_COUNT; i++) {
-               if (command_functions[i].command_line_enum == command_line_enum)
+       for (i = 0; i < CMD_COUNT; i++) {
+               if (command_functions[i].command_enum == command_enum)
                        return &command_functions[i];
        }
        return NULL;
 }
 
-static void _define_commands(void)
-{
-/* command-lines.h defines command[] structs, generated from command-lines.in */
-#include "command-lines.h" /* generated from command-lines.in */
-}
-
 void lvm_register_commands(void)
 {
        int i;
 
        memset(&commands, 0, sizeof(commands));
 
-       _define_commands();
+       /*
+        * populate commands[] array with command definitions
+        * by parsing command-lines.in/command-lines-input.h
+        */
+       if (!define_commands()) {
+               log_error("Failed to parse command definitions.");
+               return;
+       }
 
        _cmdline.commands = commands;
        _cmdline.num_commands = COMMAND_COUNT;
 
-       for (i = 0; i < COMMAND_COUNT; i++)
-               commands[i].functions = _find_command_function(commands[i].command_line_enum);
+       for (i = 0; i < COMMAND_COUNT; i++) {
+               commands[i].command_enum = command_id_to_enum(commands[i].command_id);
+
+               /* new style */
+               commands[i].functions = _find_command_id_function(commands[i].command_enum);
+
+               /* old style */
+               if (!commands[i].functions) {
+                       struct command_name *cname = find_command_name(commands[i].name);
+                       commands[i].fn = cname->fn;
+               }
+       }
 
        _cmdline.command_names = command_names;
 
@@ -1139,7 +1148,7 @@ struct command *get_command(int cmd_enum)
        int i;
 
        for (i = 0; i < COMMAND_COUNT; i++) {
-               if (commands[i].command_line_enum == cmd_enum)
+               if (commands[i].command_enum == cmd_enum)
                        return &commands[i];
        }
 
@@ -1283,194 +1292,6 @@ static int _command_required_pos_matches(struct cmd_context *cmd, int ci, int rp
        return 0;
 }
 
-
-#define HELP_LINE_SIZE 1024
-
-static void _print_usage(const char *usage_str, int only_required)
-{
-       char buf[HELP_LINE_SIZE];
-       int optional_ui = 0;
-       int optional_pos_ui = 0;
-       int ui;
-       int bi;
-
-       if (!usage_str || !strlen(usage_str))
-               return;
-
-       /*
-        * copy the required opt_args/pos_args
-        *
-        * The optional portions of the usage string are enclosed
-        * in [] and follow the required portions.
-        *
-        * The optional portion begins with [ followed by a space,
-        * i.e. "[ " to distinguish the option usage which may
-        * include [ in cases like --option Number[units].
-        */
-
-       memset(buf, 0, sizeof(buf));
-       bi = 0;
-
-       for (ui = 0; ui < strlen(usage_str); ui++) {
-               if (!bi && ((usage_str[ui] == ' ') || (usage_str[ui] == '\n')))
-                       continue;
-
-               /* The first "[ " indicates the start of the optional opt_args. */
-               if ((usage_str[ui] == '[') && (usage_str[ui+1] == ' ')) {
-                       optional_ui = ui;
-                       break;
-               }
-
-               if (usage_str[ui] == '\0')
-                       break;
-
-               if (usage_str[ui] == '(') {
-                       buf[bi++] = '\n';
-                       buf[bi++] = '\t';
-               }
-
-               buf[bi++] = usage_str[ui];
-
-               if (usage_str[ui] == ')') {
-                       buf[bi++] = '\n';
-                       buf[bi++] = '\t';
-               }
-
-               if (usage_str[ui] == ',') {
-                       buf[bi++] = '\n';
-                       buf[bi++] = '\t';
-                       buf[bi++] = ' ';
-               }
-
-               if (bi == (HELP_LINE_SIZE - 1))
-                       break;
-       }
-
-       /*
-        * print the required opt_args/pos_args
-        */
-
-       if (bi)
-               log_print("%s", buf);
-
-       if (only_required)
-               return;
-
-       /*
-        * copy the optional opt_args
-        */
-
-       if (!optional_ui)
-               goto out;
-
-       memset(buf, 0, sizeof(buf));
-       bi = 0;
-
-       for (ui = optional_ui; ui < strlen(usage_str); ui++) {
-
-               /* The second "[ " indicates the start of the optional pos_args. */
-               if ((ui > optional_ui) && (usage_str[ui] == '[') && (usage_str[ui+1] == ' ')) {
-                       optional_pos_ui = ui;
-                       break;
-               }
-
-               if (usage_str[ui] == '\0')
-                       break;
-               if (usage_str[ui] == '\n')
-                       break;
-
-               if (!bi)
-                       buf[bi++] = '\t';
-
-               buf[bi++] = usage_str[ui];
-
-               if (usage_str[ui] == ',') {
-                       buf[bi++] = '\n';
-                       buf[bi++] = '\t';
-                       buf[bi++] = ' ';
-               }
-
-               if (bi == (HELP_LINE_SIZE - 1))
-                       break;
-       }
-
-       /*
-        * print the optional opt_args
-        */
-
-       if (bi)
-               log_print("%s", buf);
-
-       /*
-        * copy the optional pos_args
-        */
-
-       if (!optional_pos_ui)
-               goto out;
-
-       memset(buf, 0, sizeof(buf));
-       bi = 0;
-
-       for (ui = optional_pos_ui; ui < strlen(usage_str); ui++) {
-               if (usage_str[ui] == '\0')
-                       break;
-               if (usage_str[ui] == '\n')
-                       break;
-
-               if (!bi)
-                       buf[bi++] = '\t';
-
-               buf[bi++] = usage_str[ui];
-
-               if (bi == (HELP_LINE_SIZE - 1))
-                       break;
-       }
-
-       /*
-        * print the optional pos_args
-        */
-
-       if (bi)
-               log_print("%s", buf);
- out:
-       return;
-}
-
-static void _print_description(int ci)
-{
-       const char *desc = _cmdline.commands[ci].desc;
-       char buf[HELP_LINE_SIZE] = {0};
-       int di = 0;
-       int bi = 0;
-
-       for (di = 0; di < strlen(desc); di++) {
-               if (!strncmp(&desc[di], "DESC:", 5)) {
-                       if (bi) {
-                               buf[bi] = '\0';
-                               log_print("%s", buf);
-                               memset(buf, 0, sizeof(buf));
-                               bi = 0;
-                       }
-                       /* skip DESC: */
-                       di += 5;
-                       continue;
-               }
-
-               if (!bi && desc[di] == ' ')
-                       continue;
-
-               buf[bi++] = desc[di];
-
-               if (bi == (HELP_LINE_SIZE - 1))
-                       break;
-       }
-
-       if (bi) {
-               buf[bi] = '\0';
-               log_print("%s", buf);
-       }
-}
-
 /*
  * Match what the user typed with a one specific command definition/prototype
  * from commands[].  If nothing matches, it's not a valid command.  The match
@@ -1683,7 +1504,7 @@ static struct command *_find_command(struct cmd_context *cmd, const char *path,
                log_error("Failed to find a matching command definition.");
                if (close_ro) {
                        log_warn("Closest command usage is:");
-                       _print_usage(_cmdline.commands[close_i].usage, 1);
+                       print_usage(&_cmdline.commands[close_i]);
                }
                return NULL;
        }
@@ -1698,8 +1519,7 @@ static struct command *_find_command(struct cmd_context *cmd, const char *path,
 
        if (best_unused_count) {
                for (i = 0; i < best_unused_count; i++) {
-                       log_error("Invalid option for command (%s %d): %s.",
-                                 commands[best_i].command_line_id, best_i,
+                       log_error("Invalid option for command: %s.",
                                  arg_long_option_name(best_unused_options[i]));
                }
                return NULL;
@@ -1729,8 +1549,7 @@ static struct command *_find_command(struct cmd_context *cmd, const char *path,
                        break;
 
                if (count >= (commands[best_i].rp_count + commands[best_i].op_count)) {
-                       log_error("Invalid positional argument for command (%s %d): %s.",
-                                 commands[best_i].command_line_id, best_i, argv[count]);
+                       log_error("Invalid positional argument for command: %s.", argv[count]);
 
                        /* FIXME: to warn/ignore, clear so it can't be used when processing. */
                        /*
@@ -1774,22 +1593,21 @@ out:
                        if (opts_match_count && (rule->rule == RULE_INVALID)) {
                                memset(buf, 0, sizeof(buf));
                                opt_array_to_str(cmd, rule->check_opts, rule->check_opts_count, buf, sizeof(buf));
-                               log_error("Invalid options for command (%s %d): %s",
-                                         commands[best_i].command_line_id, best_i, buf);
+                               log_error("Invalid options for command: %s", buf);
                                return NULL;
                        }
 
                        if (opts_unmatch_count && (rule->rule == RULE_REQUIRE)) {
                                memset(buf, 0, sizeof(buf));
                                opt_array_to_str(cmd, rule->check_opts, rule->check_opts_count, buf, sizeof(buf));
-                               log_error("Required options for command (%s %d): %s",
-                                         commands[best_i].command_line_id, best_i, buf);
+                               log_error("Required options for command: %s", buf);
                                return NULL;
                        }
                }
        }
 
-       log_debug("command line id: %s %d", commands[best_i].command_line_id, best_i);
+       log_debug("Using command index %d id %s enum %d.",
+                 best_i, commands[best_i].command_id, commands[best_i].command_enum);
 
        return &commands[best_i];
 }
@@ -1801,8 +1619,8 @@ static void _short_usage(const char *name)
 
 static int _usage(const char *name, int help_count)
 {
-       struct command_name *cname = _find_command_name(name);
-       const char *usage_common = NULL;
+       struct command_name *cname = find_command_name(name);
+       struct command *cmd;
        int i;
 
        if (!cname) {
@@ -1812,28 +1630,20 @@ static int _usage(const char *name, int help_count)
 
        log_print("%s - %s\n", name, cname->desc);
 
-       for (i = 0; i < _cmdline.num_commands; i++) {
+       for (i = 0; i < COMMAND_COUNT; i++) {
                if (strcmp(_cmdline.commands[i].name, name))
                        continue;
 
                if ((_cmdline.commands[i].cmd_flags & CMD_FLAG_SECONDARY_SYNTAX) && (help_count < 3))
                        continue;
 
-               if (strlen(_cmdline.commands[i].desc))
-                       _print_description(i);
-
-               usage_common = _cmdline.commands[i].usage_common;
-
-               _print_usage(_cmdline.commands[i].usage, 0);
-               log_print(" "); /* for built-in \n */
+               print_usage(&_cmdline.commands[i]);
+               cmd = &_cmdline.commands[i];
+               printf("\n");
        }
 
        /* Common options are printed once for all variants of a command name. */
-       if (usage_common) {
-               log_print("Common options:");
-               _print_usage(usage_common, 0);
-               log_print(" "); /* for built-in \n */
-       }
+       print_usage_common(cname, cmd);
 
        if (help_count > 1) {
                /*
@@ -1957,7 +1767,7 @@ static int _find_arg(const char *cmd_name, int goval)
        int arg_enum;
        int i;
 
-       if (!(cname = _find_command_name(cmd_name)))
+       if (!(cname = find_command_name(cmd_name)))
                return -1;
 
        for (i = 0; i < cname->num_args; i++) {
@@ -1989,7 +1799,7 @@ static int _process_command_line(struct cmd_context *cmd, int *argc, char ***arg
        int goval;    /* the number returned from getopt_long identifying what it found */
        int i;
 
-       if (!(cname = _find_command_name(cmd->name)))
+       if (!(cname = find_command_name(cmd->name)))
                return_0;
 
        if (!(cmd->opt_arg_values = dm_pool_zalloc(cmd->mem, sizeof(*cmd->opt_arg_values) * ARG_COUNT))) {
@@ -2686,7 +2496,7 @@ int lvm_run_command(struct cmd_context *cmd, int argc, char **argv)
 
        log_debug("Parsing: %s", cmd->cmd_line);
 
-       if (!(cmd->cname = _find_command_name(cmd->name))) {
+       if (!(cmd->cname = find_command_name(cmd->name))) {
                log_error("Command name not found.\n");
                return EINVALID_CMD_LINE;
        }
@@ -2857,7 +2667,7 @@ int lvm_run_command(struct cmd_context *cmd, int argc, char **argv)
        }
 
        if (cmd->command->functions)
-               /* A command-line--specific function is used */
+               /* A command-line-specific function is used */
                ret = cmd->command->functions->fn(cmd, argc, argv);
        else
                /* The old style command-name function is used */
@@ -3388,3 +3198,4 @@ int lvm2_main(int argc, char **argv)
        lvm_fin(cmd);
        return lvm_return_code(ret);
 }
+
index 2c0096fbd83e83c154165a3e9d3da6b9604c5d45..3b479894b23d8a965b242a186c2d92dbec132c3e 100644 (file)
@@ -2692,8 +2692,8 @@ static int _check_lv_types(struct cmd_context *cmd, struct logical_volume *lv, i
                return 1;
 
        if (!val_bit_is_set(cmd->command->required_pos_args[pos-1].def.val_bits, lv_VAL)) {
-               log_error(INTERNAL_ERROR "Command (%s %d) arg position %d does not permit an LV (%llx)",
-                         cmd->command->command_line_id, cmd->command->command_line_enum,
+               log_error(INTERNAL_ERROR "Command %d:%s arg position %d does not permit an LV (%llx)",
+                         cmd->command->command_index, cmd->command->command_id,
                          pos, (unsigned long long)cmd->command->required_pos_args[pos-1].def.val_bits);
                return 0;
        }
@@ -3109,9 +3109,7 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
                if (!_check_lv_types(cmd, lvl->lv, lv_arg_pos)) {
                        /* FIXME: include this result in report log? */
                        if (lv_is_named_arg) {
-                               log_error("Operation not permitted (%s %d) on LV %s.",
-                                         cmd->command->command_line_id, cmd->command->command_line_enum,
-                                         display_lvname(lvl->lv));
+                               log_error("Operation not permitted on LV %s.", display_lvname(lvl->lv));
                                ret_max = ECMD_FAILED;
                        }
                        continue;
@@ -3120,9 +3118,7 @@ int process_each_lv_in_vg(struct cmd_context *cmd, struct volume_group *vg,
                if (!_check_lv_rules(cmd, lvl->lv)) {
                        /* FIXME: include this result in report log? */
                        if (lv_is_named_arg) {
-                               log_error("Operation not permitted (%s %d) on LV %s.",
-                                         cmd->command->command_line_id, cmd->command->command_line_enum,
-                                         display_lvname(lvl->lv));
+                               log_error("Operation not permitted on LV %s.", display_lvname(lvl->lv));
                                ret_max = ECMD_FAILED;
                        } 
                        continue;
index 392490f6b7bcddbbbbf85dc2c1f1b6e11a045512..4e1d87f01d713c3fe8f3380f753479f0603532ca 100644 (file)
 #define CMD_LEN 256
 #define MAX_ARGS 64
 
+/* define the enums for each unique ID in command defs in command-lines.in */
+enum {
+#define cmd(a, b) a ,
+#include "cmds.h"
+#undef cmd
+};
+
 /* define the enums for the values accepted by command line --options, foo_VAL */
 enum {
 #define val(a, b, c, d) a ,
@@ -84,6 +91,7 @@ enum {
 };
 
 #include "command.h"
+#include "command-count.h"
 
 #define ARG_COUNTABLE 0x00000001       /* E.g. -vvvv */
 #define ARG_GROUPABLE 0x00000002       /* E.g. --addtag */
This page took 0.184875 seconds and 5 git commands to generate.