1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-01-03 05:18:29 +03:00

ccmd: split into multiple files

This commit is contained in:
David Teigland 2017-01-12 14:44:58 -06:00
parent 013c080756
commit 15d9f2850e
6 changed files with 3238 additions and 3174 deletions

View File

@ -1,3 +1,4 @@
#
# Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
# Copyright (C) 2004-2012 Red Hat, Inc. All rights reserved.
@ -140,6 +141,8 @@ all: device-mapper
CFLAGS_lvm.o += $(EXTRA_EXEC_CFLAGS)
CFLAGS_lvmcmdline.o += $(VALGRIND_CFLAGS)
INCLUDES += -I$(top_builddir)/tools
lvm: $(OBJECTS) lvm.o $(top_builddir)/lib/liblvm-internal.a
$(CC) $(CFLAGS) $(LDFLAGS) $(EXTRA_EXEC_LDFLAGS) $(ELDFLAGS) -o $@ $(OBJECTS) lvm.o \
$(LVMLIBS) $(READLINE_LIBS) $(LIBS) -rdynamic
@ -173,12 +176,35 @@ 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: create-commands.c
$(CC) create-commands.c -o ccmd
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
command-lines.h: ccmd
./ccmd --output struct command-lines.in > command-lines.h
./ccmd --output count command-lines.in > command-lines-count.h
.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
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};" \
) > $@
$(SOURCES:%.c=%.d): command-lines.h command-lines-count.h
ifneq ("$(CFLOW_CMD)", "")
CFLOW_SOURCES = $(addprefix $(srcdir)/, $(SOURCES))

1130
tools/ccmd-main.c Normal file

File diff suppressed because it is too large Load Diff

997
tools/ccmd-man.c Normal file
View File

@ -0,0 +1,997 @@
#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;
}
}

936
tools/ccmd-util.c Normal file
View File

@ -0,0 +1,936 @@
#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:
;
}
}
}

144
tools/ccmd.h Normal file
View File

@ -0,0 +1,144 @@
#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

File diff suppressed because it is too large Load Diff