1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-09-27 05:44:18 +03:00

Compare commits

..

1 Commits

Author SHA1 Message Date
David Teigland
f4ef8d9c90 commands: new method for defining commands
. Define a prototype for every lvm command.
. Match every user command with one definition.
. Generate help text and man pages from them.

The new file command-lines.in defines a prototype for every
unique lvm command.  A unique lvm command is a unique
combination of: command name + required option args +
required positional args.  Each of these prototypes also
includes the optional option args and optional positional
args that the command will accept, a description, and a
unique string ID for the definition.  Any valid command
will match one of the prototypes.

Here's an example of the lvresize command definitions from
command-lines.in, there are three unique lvresize commands:

lvresize --size SizeMB LV
OO: --alloc Alloc, --autobackup Bool, --force,
--nofsck, --nosync, --noudevsync, --reportformat String, --resizefs,
--stripes Number, --stripesize SizeKB, --poolmetadatasize SizeMB
OP: PV ...
ID: lvresize_by_size
DESC: Resize an LV by a specified size.

lvresize LV PV ...
OO: --alloc Alloc, --autobackup Bool, --force,
--nofsck, --nosync, --noudevsync,
--reportformat String, --resizefs, --stripes Number, --stripesize SizeKB
ID: lvresize_by_pv
DESC: Resize an LV by specified PV extents.
FLAGS: SECONDARY_SYNTAX

lvresize --poolmetadatasize SizeMB LV_thinpool
OO: --alloc Alloc, --autobackup Bool, --force,
--nofsck, --nosync, --noudevsync,
--reportformat String, --stripes Number, --stripesize SizeKB
OP: PV ...
ID: lvresize_pool_metadata_by_size
DESC: Resize a pool metadata SubLV by a specified size.

The three commands have separate definitions because they have
different required parameters.  Required parameters are specified
on the first line of the definition.  Optional options are
listed after OO, and optional positional args are listed after OP.

This data is used to generate corresponding command definition
structures for lvm in command-lines.h.  usage/help output is also
auto generated, so it is always in sync with the definitions.

Example of the corresponding generated structure in
command-lines.h for the first lvresize prototype
(these structures are never edited directly):

commands[83].name = "lvresize";
commands[83].command_line_id = "lvresize_by_size";
commands[83].command_line_enum = lvresize_by_size_CMD;
commands[83].fn = lvresize;
commands[83].ro_count = 1;
commands[83].rp_count = 1;
commands[83].oo_count = 22;
commands[83].op_count = 1;
commands[83].cmd_flags = 0;
commands[83].desc = "DESC: Resize an LV by a specified size.";
commands[83].usage = "lvresize --size Number[m|unit] LV"
" [ --resizefs, --poolmetadatasize Number[m|unit], COMMON_OPTIONS ]"
" [ PV ... ]";
commands[83].usage_common =
" [ --alloc contiguous|cling|cling_by_tags|normal|anywhere|inherit, --nosync, --reportformat String, --autobackup y|n, --stripes Number, --stripesize Number[k|unit], --nofsck, --commandprofile String, --config String, --debug, --driverloaded y|n, --help, --profile String, --quiet, --verbose, --version, --yes, --test, --force, --noudevsync ]";
commands[83].required_opt_args[0].opt = size_ARG;
commands[83].required_opt_args[0].def.val_bits = val_enum_to_bit(sizemb_VAL);
commands[83].required_pos_args[0].pos = 1;
commands[83].required_pos_args[0].def.val_bits = val_enum_to_bit(lv_VAL);
commands[83].optional_opt_args[0].opt = commandprofile_ARG;
commands[83].optional_opt_args[0].def.val_bits = val_enum_to_bit(string_VAL);
commands[83].optional_opt_args[1].opt = config_ARG;
commands[83].optional_opt_args[1].def.val_bits = val_enum_to_bit(string_VAL);
commands[83].optional_opt_args[2].opt = debug_ARG;
commands[83].optional_opt_args[3].opt = driverloaded_ARG;
commands[83].optional_opt_args[3].def.val_bits = val_enum_to_bit(bool_VAL);
commands[83].optional_opt_args[4].opt = help_ARG;
commands[83].optional_opt_args[5].opt = profile_ARG;
commands[83].optional_opt_args[5].def.val_bits = val_enum_to_bit(string_VAL);
commands[83].optional_opt_args[6].opt = quiet_ARG;
commands[83].optional_opt_args[7].opt = verbose_ARG;
commands[83].optional_opt_args[8].opt = version_ARG;
commands[83].optional_opt_args[9].opt = yes_ARG;
commands[83].optional_opt_args[10].opt = test_ARG;
commands[83].optional_opt_args[11].opt = alloc_ARG;
commands[83].optional_opt_args[11].def.val_bits = val_enum_to_bit(alloc_VAL);
commands[83].optional_opt_args[12].opt = autobackup_ARG;
commands[83].optional_opt_args[12].def.val_bits = val_enum_to_bit(bool_VAL);
commands[83].optional_opt_args[13].opt = force_ARG;
commands[83].optional_opt_args[14].opt = nofsck_ARG;
commands[83].optional_opt_args[15].opt = nosync_ARG;
commands[83].optional_opt_args[16].opt = noudevsync_ARG;
commands[83].optional_opt_args[17].opt = reportformat_ARG;
commands[83].optional_opt_args[17].def.val_bits = val_enum_to_bit(string_VAL);
commands[83].optional_opt_args[18].opt = resizefs_ARG;
commands[83].optional_opt_args[19].opt = stripes_ARG;
commands[83].optional_opt_args[19].def.val_bits = val_enum_to_bit(number_VAL);
commands[83].optional_opt_args[20].opt = stripesize_ARG;
commands[83].optional_opt_args[20].def.val_bits = val_enum_to_bit(sizekb_VAL);
commands[83].optional_opt_args[21].opt = poolmetadatasize_ARG;
commands[83].optional_opt_args[21].def.val_bits = val_enum_to_bit(sizemb_VAL);
commands[83].optional_pos_args[0].pos = 2;
commands[83].optional_pos_args[0].def.val_bits = val_enum_to_bit(pv_VAL);
commands[83].optional_pos_args[0].def.flags = ARG_DEF_FLAG_MAY_REPEAT;

Every user-entered command is compared against the set of
command structures, and matched with one.  An error is
reported if an entered command does not have the required
parameters for any definition.  The closest match is printed
as a suggestion, and running lvresize --help will display
the usage for each possible lvresize command.

The prototype syntax used for help/man output includes
required --option and positional args on the first line,
and optional --option and positional args enclosed in [ ]
on subsequent lines.

  command_name <required_opt_args> <required_pos_args>
          [ <optional_opt_args> ]
          [ <optional_pos_args> ]

$ lvresize --help
  lvresize - Resize a logical volume

  Resize an LV by a specified size.
  lvresize --size Number[m|unit] LV
        [ --resizefs,
          --poolmetadatasize Number[m|unit],
          COMMON_OPTIONS ]
        [ PV ... ]

  Resize a pool metadata SubLV by a specified size.
  lvresize --poolmetadatasize Number[m|unit] LV_thinpool
        [ COMMON_OPTIONS ]
        [ PV ... ]

  Common options:
        [ --alloc contiguous|cling|cling_by_tags|normal|anywhere|inherit,
          --nosync,
          --reportformat String,
          --autobackup y|n,
          --stripes Number,
          --stripesize Number[k|unit],
          --nofsck,
          --commandprofile String,
          --config String,
          --debug,
          --driverloaded y|n,
          --help,
          --profile String,
          --quiet,
          --verbose,
          --version,
          --yes,
          --test,
          --force,
          --noudevsync ]

  (Use --help --help for usage notes.)

$ lvresize --poolmetadatasize 4
  Failed to find a matching command definition.
  Closest command usage is:
  lvresize --poolmetadatasize Number[m|unit] LV_thinpool

Command definitions that are not to be advertised/suggested
have the flag SECONDARY_SYNTAX.  These commands will not be
printed in the normal help output.

Man page prototypes are also generated from the same original
command definitions, and are always in sync with the code
and help text.

Very early in command execution, a matching command definition
is found.  lvm then knows the operation being done, and that
the provided args conform to the definition.  This will allow
lots of ad hoc checking/validation to be removed throughout
the code.

Each command definition can also be routed to a specific
function to implement it.  The function is associated with
an enum value for the command definition (generated from
the ID string.)  These per-command-definition implementation
functions have not yet been created, so all commands
currently fall back to the existing per-command-name
implementation functions.

Using per-command-definition functions will allow lots of
code to be removed which tries to figure out what the
command is meant to do.  This is currently based on ad hoc
and complicated option analysis.  When using the new
functions, what the command is doing is already known
from the associated command definition.

So, this first phase validates every user-entered command
against the set of command prototypes, then calls the existing
implementation.  The second phase can associate an implementation
function with each definition, and take further advantage of the
known operation to avoid the complicated option analysis.
2016-10-31 12:56:43 -05:00
4 changed files with 29 additions and 245 deletions

View File

@@ -121,42 +121,25 @@
# There are no consistent rules to follow and the behaviors are
# unpredictable; each possible variation and combination needs
# to be tested individually to see what it means.
#
#
# Another capability we might want to add here is a way to express
# rules, per definition, of what arg combinations are allowed or
# required, e.g.
#
# if --foo is set, then --bar cannot be set could be encoded as:
# RULE_OPT_INVALID_OPT: --foo --bar
# RULE_OPT_INCOMPAT_OPT: --foo --bar
#
# if --foo is set, then --bar is required could be encoded as:
# RULE_OPT_REQUIRES_OPT: --foo --bar
#
# if --foo is set, then positional arg 1 is required
# (the type of value in that arg is specified by the command def):
# RULE_OPT_REQUIRES_POS: --foo 1
#
# Another thing to add is more details about accpeted LVs.
# Checks encoded here can be done in the generic process_each code.
# LV_TYPE: thinpool, mirror (one must be true)
# LV_PROP: lv_is_pvmove, lv_is_merging (all must be true)
#
# The rules could also specify validation for positional LV args:
#
# if --foo is set, then specified lv checks must pass:
# RULE_OPT_REQUIRES_LV_CHECK: --foo lv_is_merging_origin
#
# if --foo is set, then specified lv checks must not pass:
# RULE_OPT_INVALID_LV_CHECK: --foo lv_is_merging_origin
#
# command def requires specified lv checks must pass:
# RULE_OPT_REQUIRES_LV_CHECK: * lv_is_merging_origin
#
# command def requires specified lv checks must not pass:
# RULE_OPT_INVALID_LV_CHECK: * lv_is_merging_origin
#
#
# To implement would require a rule structure, and an array of
# rule structures would be added to struct command, to be filled
# in like the args arrays are.
#
#
@@ -291,7 +274,8 @@ OO_LVCONVERT_RAID: --mirrors SNumber, --stripes_long Number,
OO_LVCONVERT_POOL: --poolmetadata LV, --poolmetadatasize SizeMB,
--poolmetadataspare Bool, --readahead Readahead, --chunksize SizeKB
OO_LVCONVERT: --alloc Alloc, --background, --force, --noudevsync
OO_LVCONVERT: --alloc Alloc, --background, --force, --noudevsync,
--usepolicies
---
@@ -390,7 +374,6 @@ FLAGS: SECONDARY_SYNTAX
lvconvert --type thin-pool LV_linear_striped_raid_cache
OO: --stripes_long Number, --stripesize SizeKB,
--discards Discards, --zero Bool, OO_LVCONVERT_POOL, OO_LVCONVERT
OP: PV ...
ID: lvconvert_to_thinpool
DESC: Convert LV to type thin-pool.
@@ -408,7 +391,6 @@ FLAGS: SECONDARY_SYNTAX
lvconvert --type cache-pool LV_linear_striped_raid
OO: OO_LVCONVERT_POOL, OO_LVCONVERT,
--cachemode CacheMode, --cachepolicy String, --cachesettings String
OP: PV ...
ID: lvconvert_to_cachepool
DESC: Convert LV to type cache-pool.
@@ -517,8 +499,7 @@ DESC: Combine LV with a previously split snapshot LV.
# and the LV type is known.
lvconvert --repair LV_raid_mirror_thinpool
OO: --usepolicies, OO_LVCONVERT
OP: PV ...
OO: OO_LVCONVERT
ID: lvconvert_repair_pvs_or_thinpool
DESC: Replace failed PVs in a raid or mirror LV.
DESC: Repair a thin pool.
@@ -1188,7 +1169,7 @@ DESC: Display PV information.
pvscan --cache_long
OO: --ignorelockingfailure, --reportformat ReportFmt, --background,
--activate Active, --major Number, --minor Number
--activate Active, --major Number, --minor Number,
OP: PV|String ...
ID: pvscan_cache
DESC: Populate the lvmetad cache by scanning PVs.
@@ -1225,7 +1206,7 @@ OO_VGCHANGE_META: --addtag Tag, --deltag Tag,
--logicalvolume Number, --maxphysicalvolumes Number, --alloc Alloc, --uuid,
--clustered Bool, --pvmetadatacopies MetadataCopiesPV, --vgmetadatacopies MetadataCopiesVG,
--physicalextentsize SizeMB, --resizeable Bool, --systemid String, --locktype LockType,
--profile String, --detachprofile, --metadataprofile String
--profile String, --detachprofile, --metadataprofile String,
vgchange OO_VGCHANGE_META
OO: OO_VGCHANGE
@@ -1439,19 +1420,15 @@ DESC: Split a VG by PVs in a specified LV.
# built-in and deprecated commands
# use lvmconfig
config
OO: OO_CONFIG
OP: String ...
ID: lvmconfig_general
FLAGS: SECONDARY_SYNTAX
# use lvmconfig
dumpconfig
OO: OO_CONFIG
OP: String ...
ID: lvmconfig_general
FLAGS: SECONDARY_SYNTAX
devtypes
OO: --aligned, --binary, --nameprefixes, --noheadings,
@@ -1481,10 +1458,8 @@ ID: help_general
version
ID: version_general
# deprecated
pvdata
ID: pvdata_general
FLAGS: SECONDARY_SYNTAX
segtypes
ID: segtypes_general
@@ -1495,25 +1470,17 @@ ID: systemid_general
tags
ID: tags_general
# deprecated
lvmchange
ID: lvmchange_general
FLAGS: SECONDARY_SYNTAX
# deprecated
lvmdiskscan
OO: --lvmpartition, --readonly
ID: lvmdiskscan_general
FLAGS: SECONDARY_SYNTAX
# deprecated
lvmsadc
ID: lvmsadc_general
FLAGS: SECONDARY_SYNTAX
# deprecated
lvmsar
OO: --full, --stdin
ID: lvmsar_general
FLAGS: SECONDARY_SYNTAX

View File

@@ -165,43 +165,6 @@ struct command {
/* used for processing current position */
int pos_count;
/* struct cmd_rule rules[CMD_RULES]; */
};
#if 0
/*
* if rule.opt is set, then rule.type specifies if rule.check values
* are required or invalid.
*
* if (arg_is_set(rule.opt) &&
* (rule.type & RULE_OPT_INVALID_OPT) && arg_is_set(rule.check.opt)) {
* log_error("option %s and option %s cannot be used together");
* }
*
* if (arg_is_set(rule.opt) &&
* (rule.type & RULE_OPT_REQUIRES_LV_CHECK) && !lv_check(lv, rule.check.bits, &fail_bits)) {
* log_error("LV %s must be %s", lv, lv_check_to_str(fail_bits));
* }
*
* if (arg_is_set(rule.opt) &&
* (rule.type & RULE_OPT_INVALID_LV_CHECK) && lv_check(lv, rule.check.bits, &fail_bits)) {
* log_error("LV %s must not be %s", lv, lv_check_to_str(fail_bits));
* }
*
*/
struct cmd_rule {
int opt; /* foo_ARG, or INT_MAX for command def in general */
int type; /* RULE_ specifies how to require/prohibit check value */
union {
int opt;
int pos;
uint64_t bits;
} check;
};
#endif
#endif

View File

@@ -116,13 +116,8 @@ static struct opt_name opt_names[ARG_COUNT + 1] = {
struct cmd_name {
const char *name;
const char *desc;
int common_options[ARG_COUNT + 1];
int all_options[ARG_COUNT + 1];
int variants;
int variant_has_ro;
int variant_has_rp;
int variant_has_oo;
int variant_has_op;
int common_options[ARG_COUNT + 1];
};
/* create table of command names, e.g. vgcreate */
@@ -1256,7 +1251,7 @@ static int is_lvm_all_opt(int opt)
static void factor_common_options(void)
{
int cn, opt_enum, ci, oo, ro, found;
int cn, opt_enum, ci, oo, found;
struct command *cmd;
for (cn = 0; cn < MAX_CMD_NAMES; cn++) {
@@ -1280,24 +1275,6 @@ static void factor_common_options(void)
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++) {
@@ -1538,21 +1515,11 @@ static void print_val_man(const char *str)
}
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) {
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
@@ -1622,7 +1589,7 @@ static void print_def_man(struct arg_def *def, int usage)
printf(" ...");
}
static char *man_long_opt_name(const char *cmdname, int opt_enum)
static char *man_long_opt_name(struct command *cmd, int opt_enum)
{
static char long_opt_name[64];
@@ -1645,13 +1612,13 @@ static char *man_long_opt_name(const char *cmdname, int opt_enum)
strncpy(long_opt_name, "--[raid]writebehind", 63);
break;
case vgmetadatacopies_ARG:
if (!strncmp(cmdname, "vg", 2))
if (!strncmp(cmd->name, "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))
if (!strncmp(cmd->name, "pv", 2))
strncpy(long_opt_name, "--[pv]metadatacopies", 63);
else
strncpy(long_opt_name, "--pvmetadatacopies", 63);
@@ -1712,10 +1679,10 @@ void print_man_usage(struct command *cmd)
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));
man_long_opt_name(cmd, opt_enum));
} else {
printf(" ");
printf(" \\fB%s\\fP", man_long_opt_name(cmd->name, opt_enum));
printf(" \\fB%s\\fP", man_long_opt_name(cmd, opt_enum));
}
if (cmd->required_opt_args[ro].def.val_bits) {
@@ -1740,7 +1707,7 @@ void print_man_usage(struct command *cmd)
}
printf(" ");
printf(" \\fB%s\\fP", man_long_opt_name(cmd->name, opt_enum));
printf(" \\fB%s\\fP", man_long_opt_name(cmd, opt_enum));
if (cmd->required_opt_args[ro].def.val_bits) {
printf(" ");
@@ -1754,7 +1721,7 @@ void print_man_usage(struct command *cmd)
printf(".RE\n");
}
/* print required position args on a new line after the onereq set */
/* print required positional 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++) {
@@ -1787,7 +1754,7 @@ void print_man_usage(struct command *cmd)
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));
man_long_opt_name(cmd, opt_enum));
} else {
printf(" \\fB%s\\fP", opt_names[cmd->required_opt_args[ro].opt].long_opt);
}
@@ -1799,7 +1766,7 @@ void print_man_usage(struct command *cmd)
}
}
/* print required position args on the same line as the required options */
/* print required positional 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) {
@@ -1853,7 +1820,7 @@ void print_man_usage(struct command *cmd)
printf(" \\fB-%c\\fP|\\fB%s\\fP",
opt_names[opt_enum].short_opt,
man_long_opt_name(cmd->name, opt_enum));
man_long_opt_name(cmd, opt_enum));
if (cmd->optional_opt_args[oo].def.val_bits) {
printf(" ");
@@ -1891,7 +1858,7 @@ void print_man_usage(struct command *cmd)
/* space alignment without short opt */
printf(" ");
printf(" \\fB%s\\fP", man_long_opt_name(cmd->name, opt_enum));
printf(" \\fB%s\\fP", man_long_opt_name(cmd, opt_enum));
if (cmd->optional_opt_args[oo].def.val_bits) {
printf(" ");
@@ -1980,7 +1947,7 @@ void print_man_usage_common(struct command *cmd)
printf(" \\fB-%c\\fP|\\fB%s\\fP",
opt_names[opt_enum].short_opt,
man_long_opt_name(cmd->name, opt_enum));
man_long_opt_name(cmd, opt_enum));
if (cmd->optional_opt_args[oo].def.val_bits) {
printf(" ");
@@ -2016,7 +1983,7 @@ void print_man_usage_common(struct command *cmd)
/* space alignment without short opt */
printf(" ");
printf(" \\fB%s\\fP", man_long_opt_name(cmd->name, opt_enum));
printf(" \\fB%s\\fP", man_long_opt_name(cmd, opt_enum));
if (cmd->optional_opt_args[oo].def.val_bits) {
printf(" ");
@@ -2044,7 +2011,7 @@ void print_man_usage_common(struct command *cmd)
printf(" \\fB-%c\\fP|\\fB%s\\fP",
opt_names[opt_enum].short_opt,
man_long_opt_name(cmd->name, opt_enum));
man_long_opt_name(cmd, opt_enum));
if (lvm_all.optional_opt_args[oo].def.val_bits) {
printf(" ");
@@ -2069,7 +2036,7 @@ void print_man_usage_common(struct command *cmd)
/* space alignment without short opt */
printf(" ");
printf(" \\fB%s\\fP", man_long_opt_name(cmd->name, opt_enum));
printf(" \\fB%s\\fP", man_long_opt_name(cmd, opt_enum));
if (lvm_all.optional_opt_args[oo].def.val_bits) {
printf(" ");
@@ -2080,77 +2047,6 @@ void print_man_usage_common(struct command *cmd)
printf(" ]\n");
}
void print_man_all_options(struct cmd_name *cname)
{
int opt_enum, val_enum;
int sep = 0;
/* print those with short opts */
for (opt_enum = 0; opt_enum < ARG_COUNT; 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 (opt_enum = 0; opt_enum < ARG_COUNT; 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;
}
}
#define DESC_LINE 256
void print_desc_man(const char *desc)
@@ -2206,7 +2102,6 @@ static char *upper_command_name(char *str)
void print_man_command(void)
{
struct cmd_name *cname;
struct command *cmd, *prev_cmd = NULL;
const char *desc;
int i, j, ro, rp, oo, op;
@@ -2251,47 +2146,6 @@ void print_man_command(void)
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(cname);
printf("\n");
printf(".P\n");
printf("\n");
}
printf(".SH USAGE\n");
printf(".br\n");
printf(".P\n");
printf(".\n");
}
if (cmd->desc) {

View File

@@ -113,7 +113,7 @@ val(mirrorlog_VAL, mirrorlog_arg, "MirrorLog", "core|disk")
val(sizekb_VAL, size_kb_arg, "SizeKB", "Number[k|unit]")
val(sizemb_VAL, size_mb_arg, "SizeMB", "Number[m|unit]")
val(numsigned_VAL, int_arg_with_sign, "SNumber", "[+|-]Number")
val(numsignedper_VAL, int_arg_with_sign_and_percent, "SNumberP", "[+|-]Number[%VG|%PVS|%FREE]")
val(numsignedper_VAL, int_arg_with_sign_and_percent, "SNumberP", "[+|-]Number[%{VG|PVS|FREE}]")
val(permission_VAL, permission_arg, "Permission", "rw|r")
val(metadatatype_VAL, metadatatype_arg, "MetadataType", "lvm2|lvm1")
val(units_VAL, string_arg, "Units", "hHbBsSkKmMgGtTpPeE")