Commit dc7af9f0 authored by unknown's avatar unknown

Bug fixes and new functionality added in my_getopt and myisamchk


include/my_getopt.h:
  Removed a member from my_getopt struct.
myisam/myisamchk.c:
  pdated myisamchk. More features in use from my_getopt
mysys/my_getopt.c:
  Fixed a bug in handle_options(). Short options were not tested
  whether existed when given from the command line. Fixed a bug
  in getopt_ll, got division by zero in some cases. Added new functions
  my_print_help() and my_print_variables() to be used by mysql server
  and most clients.
parent 9adfd2e8
......@@ -42,7 +42,6 @@ struct my_option
longlong sub_size; /* Subtract this from given value */
long block_size; /* Value should be a mult. of this */
int app_type; /* To be used by an application */
my_bool opt_is_var; /* If true, the option is a variable */
};
extern int handle_options (int *argc, char ***argv,
......@@ -50,3 +49,5 @@ extern int handle_options (int *argc, char ***argv,
my_bool (*get_one_option)(int,
const struct my_option *,
char *));
extern void my_print_help(const struct my_option *options);
extern void my_print_variables(const struct my_option *options);
......@@ -152,71 +152,145 @@ enum options {
static struct my_option my_long_options[] =
{
{"analyze", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'a', 0, 0, 0, 0, 0, 0, 0},
{"block-search", "", 0, 0, 0, GET_LONG, REQUIRED_ARG, 'b', 0, 0, 0, 0, 0, 0, 0},
{"backup", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'B', 0, 0, 0, 0, 0, 0, 0},
{"character-sets-dir", "", (gptr*) &set_charset_name, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0, 0, 1},
{"check", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'c', 0, 0, 0, 0, 0, 0, 0},
{"check-only-changed", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'C', 0, 0, 0, 0, 0, 0, 0},
{"correct-checksum", "", 0, 0, 0, GET_NO_ARG, NO_ARG, OPT_CORRECT_CHECKSUM, 0, 0, 0, 0, 0, 0, 0},
{"analyze",
"Analyze distribution of keys. Will make some joins in MySQL faster. You can check the calculated distribution.", 0, 0, 0, GET_NO_ARG, NO_ARG, 'a', 0, 0,
0, 0, 0, 0},
{"block-search", "No help available.", 0, 0, 0, GET_LONG, REQUIRED_ARG, 'b',
0, 0, 0, 0, 0, 0},
{"backup", "Make a backup of the .MYD file as 'filename-time.BAK'", 0, 0, 0,
GET_NO_ARG, NO_ARG, 'B', 0, 0, 0, 0, 0, 0},
{"character-sets-dir", "Directory where character sets are.",
(gptr*) &set_charset_name, 0, 0, GET_STR, REQUIRED_ARG, OPT_CHARSETS_DIR, 0,
0, 0, 0, 0, 0},
{"check", "Check table for errors.", 0, 0, 0, GET_NO_ARG, NO_ARG, 'c', 0, 0,
0, 0, 0, 0},
{"check-only-changed",
"Check only tables that has changed since last check.", 0, 0, 0, GET_NO_ARG,
NO_ARG, 'C', 0, 0, 0, 0, 0, 0},
{"correct-checksum", "Correct checksum information for table.", 0, 0, 0,
GET_NO_ARG, NO_ARG, OPT_CORRECT_CHECKSUM, 0, 0, 0, 0, 0, 0},
#ifndef DBUG_OFF
{"debug", "", 0, 0, 0, GET_STR, OPT_ARG, '#', 0, 0, 0, 0, 0, 0, 0},
{"debug", "Output debug log. Often this is 'd:t:o,filename'.", 0, 0, 0,
GET_STR, OPT_ARG, '#', 0, 0, 0, 0, 0, 0},
#endif
{"description", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'd', 0, 0, 0, 0, 0, 0, 0},
{"data-file-length", "", 0, 0, 0, GET_LONG, REQUIRED_ARG, 'D', 0, 0, 0, 0, 0, 0, 0},
{"extend-check", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'e', 0, 0, 0, 0, 0, 0, 0},
{"fast", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'F', 0, 0, 0, 0, 0, 0, 0},
{"force", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'f', 0, 0, 0, 0, 0, 0, 0},
{"help", "", 0, 0, 0, GET_NO_ARG, NO_ARG, '?', 0, 0, 0, 0, 0, 0, 0},
{"information", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'i', 0, 0, 0, 0, 0, 0, 0},
{"keys-used", "", 0, 0, 0, GET_LONG, REQUIRED_ARG, 'k', 0, 0, 0, 0, 0, 0, 0},
{"medium-check", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'm', 0, 0, 0, 0, 0, 0, 0},
{"quick", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'q', 0, 0, 0, 0, 0, 0, 0},
{"read-only", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'T', 0, 0, 0, 0, 0, 0, 0},
{"recover", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'r', 0, 0, 0, 0, 0, 0, 0},
{"safe-recover", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'o', 0, 0, 0, 0, 0, 0, 0},
{"start-check-pos", "", 0, 0, 0, GET_LONG, REQUIRED_ARG, OPT_START_CHECK_POS, 0, 0, 0, 0, 0, 0, 0},
{"set-auto-increment", "", 0, 0, 0, GET_LONG, OPT_ARG, 'A', 0, 0, 0, 0, 0, 0, 0},
{"set-character-set", "", 0, 0, 0, GET_STR, REQUIRED_ARG, OPT_SET_CHARSET, 0, 0, 0, 0, 0, 0, 0},
{"set-variable", "", 0, 0, 0, GET_STR, REQUIRED_ARG, 'O', 0, 0, 0, 0, 0, 0, 0},
{"silent", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 's', 0, 0, 0, 0, 0, 0, 0},
{"sort-index", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'S', 0, 0, 0, 0, 0, 0, 0},
{"sort-records", "", 0, 0, 0, GET_LONG, REQUIRED_ARG, 'R', 0, 0, 0, 0, 0, 0, 0},
{"sort-recover", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'n', 0, 0, 0, 0, 0, 0, 0},
{"tmpdir", "", 0, 0, 0, GET_STR, REQUIRED_ARG, 't', 0, 0, 0, 0, 0, 0, 0},
{"update-state", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'U', 0, 0, 0, 0, 0, 0, 0},
{"unpack", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'u', 0, 0, 0, 0, 0, 0, 0},
{"verbose", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'v', 0, 0, 0, 0, 0, 0, 0},
{"version", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'V', 0, 0, 0, 0, 0, 0, 0},
{"wait", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'w', 0, 0, 0, 0, 0, 0, 0},
/* variables begin here */
{ "key_buffer_size", "", (gptr*) &check_param.use_buffers, (gptr*) &check_param.use_buffers, 0, GET_LONG, REQUIRED_ARG, OPT_KEY_BUFFER_SIZE, (long) USE_BUFFER_INIT, (long) MALLOC_OVERHEAD, (long) ~0L, (long) MALLOC_OVERHEAD, (long) IO_SIZE, 0, 1},
{ "myisam_block_size", "", (gptr*) &opt_myisam_block_size, (gptr*) &opt_myisam_block_size, 0, GET_LONG, REQUIRED_ARG, OPT_MYISAM_BLOCK_SIZE, MI_KEY_BLOCK_LENGTH, MI_MIN_KEY_BLOCK_LENGTH, MI_MAX_KEY_BLOCK_LENGTH, 0, MI_MIN_KEY_BLOCK_LENGTH, 0, 1},
{ "read_buffer_size", "", (gptr*) &check_param.read_buffer_length, (gptr*) &check_param.read_buffer_length, 0, GET_LONG, REQUIRED_ARG, OPT_READ_BUFFER_SIZE, (long) READ_BUFFER_INIT, (long) MALLOC_OVERHEAD, (long) ~0L, (long) MALLOC_OVERHEAD, (long) 1L, 0, 1},
{ "write_buffer_size", "", (gptr*) &check_param.write_buffer_length, (gptr*) &check_param.write_buffer_length, 0, GET_LONG, REQUIRED_ARG, OPT_WRITE_BUFFER_SIZE, (long) READ_BUFFER_INIT, (long) MALLOC_OVERHEAD, (long) ~0L, (long) MALLOC_OVERHEAD, (long) 1L, 0, 1},
{ "sort_buffer_size", "", (gptr*) &check_param.sort_buffer_length, (gptr*) &check_param.sort_buffer_length, 0, GET_LONG, REQUIRED_ARG, OPT_SORT_BUFFER_SIZE, (long) SORT_BUFFER_INIT, (long) (MIN_SORT_BUFFER + MALLOC_OVERHEAD), (long) ~0L, (long) MALLOC_OVERHEAD, (long) 1L, 0, 1},
{ "sort_key_blocks", "", (gptr*) &check_param.sort_key_blocks, (gptr*) &check_param.sort_key_blocks, 0, GET_LONG, REQUIRED_ARG, OPT_SORT_KEY_BLOCKS, BUFFERS_WHEN_SORTING, 4L, 100L, 0L, 1L, 0, 1},
{ "decode_bits", "", (gptr*) &decode_bits, (gptr*) &decode_bits, 0, GET_LONG, REQUIRED_ARG, OPT_DECODE_BITS, 9L, 4L, 17L, 0L, 1L, 0, 1},
{ "ft_min_word_len", "", (gptr*) &ft_min_word_len, (gptr*) &ft_min_word_len, 0, GET_LONG, REQUIRED_ARG, OPT_FT_MIN_WORD_LEN, 4, 1, HA_FT_MAXLEN, 0, 1, 0, 1},
{ "ft_max_word_len", "", (gptr*) &ft_max_word_len, (gptr*) &ft_max_word_len, 0, GET_LONG, REQUIRED_ARG, OPT_FT_MAX_WORD_LEN, HA_FT_MAXLEN, 10, HA_FT_MAXLEN, 0, 1, 0, 1},
{ "ft_max_word_len_for_sort", "", (gptr*) &ft_max_word_len_for_sort, (gptr*) &ft_max_word_len_for_sort, 0, GET_LONG, REQUIRED_ARG, OPT_FT_MAX_WORD_LEN_FOR_SORT, 20, 4, HA_FT_MAXLEN, 0, 1, 0, 1},
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
{"description", "Prints some information about table.", 0, 0, 0, GET_NO_ARG,
NO_ARG, 'd', 0, 0, 0, 0, 0, 0},
{"data-file-length",
"Max length of data file (when recreating data-file when it's full).",
(gptr*) &check_param.max_data_file_length,
(gptr*) &check_param.max_data_file_length, 0, GET_LONG, REQUIRED_ARG, 'D',
0, 0, 0, 0, 0, 0},
{"extend-check",
"Try to recover every possible row from the data file. Normally this will also find a lot of garbage rows; Don't use this option if you are not totally desperate.", 0, 0, 0, GET_NO_ARG, NO_ARG, 'e', 0, 0, 0, 0, 0, 0},
{"fast", "Check only tables that hasn't been closed properly.", 0, 0, 0,
GET_NO_ARG, NO_ARG, 'F', 0, 0, 0, 0, 0, 0},
{"force",
"Restart with -r if there are any errors in the table. States will be updated as with --update-state.", 0, 0, 0, GET_NO_ARG, NO_ARG, 'f', 0, 0, 0, 0, 0,
0},
{"help", "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, '?', 0,
0, 0, 0, 0, 0},
{"information", "Print statistics information about table that is checked.",
0, 0, 0, GET_NO_ARG, NO_ARG, 'i', 0, 0, 0, 0, 0, 0},
{"keys-used", "Tell MyISAM to update only some specific keys. # is a bit mask of which keys to use. This can be used to get faster inserts!",
(gptr*) &check_param.keys_in_use, (gptr*) &check_param.keys_in_use, 0,
GET_LONG, REQUIRED_ARG, 'k', 0, 0, 0, 0, 0, 0},
{"medium-check",
"Faster than extended-check, but only finds 99.99% of all errors. Should be good enough for most cases.", 0, 0, 0, GET_NO_ARG, NO_ARG, 'm', 0, 0, 0, 0, 0,
0},
{"quick", "Faster repair by not modifying the data file.", 0, 0, 0,
GET_NO_ARG, NO_ARG, 'q', 0, 0, 0, 0, 0, 0},
{"read-only", "Don't mark table as checked.", 0, 0, 0, GET_NO_ARG, NO_ARG,
'T', 0, 0, 0, 0, 0, 0},
{"recover",
"Can fix almost anything except unique keys that aren't unique.", 0, 0, 0,
GET_NO_ARG, NO_ARG, 'r', 0, 0, 0, 0, 0, 0},
{"safe-recover",
"Uses old recovery method; Slower than '-r' but can handle a couple of cases where '-r' reports that it can't fix the data file.", 0, 0, 0, GET_NO_ARG,
NO_ARG, 'o', 0, 0, 0, 0, 0, 0},
{"start-check-pos", "No help available.", 0, 0, 0, GET_LONG, REQUIRED_ARG,
OPT_START_CHECK_POS, 0, 0, 0, 0, 0, 0},
{"set-auto-increment",
"Force auto_increment to start at this or higher value. If no value is given, then sets the next auto_increment value to the highest used value for the auto key + 1.", (gptr*) &check_param.auto_increment_value,
(gptr*) &check_param.auto_increment_value, 0, GET_LONG, OPT_ARG, 'A', 0, 0,
0, 0, 0, 0},
{"set-character-set", "Change the character set used by the index", 0, 0, 0,
GET_STR, REQUIRED_ARG, OPT_SET_CHARSET, 0, 0, 0, 0, 0, 0},
{"set-variable", "Change the value of a variable. Please note that this option is depricated; you can set variables directly with --variable-name=value.",
0, 0, 0, GET_STR, REQUIRED_ARG, 'O', 0, 0, 0, 0, 0, 0},
{"silent",
"Only print errors. One can use two -s to make myisamchk very silent.", 0,
0, 0, GET_NO_ARG, NO_ARG, 's', 0, 0, 0, 0, 0, 0},
{"sort-index",
"Sort index blocks. This speeds up 'read-next' in applications.", 0, 0, 0,
GET_NO_ARG, NO_ARG, 'S', 0, 0, 0, 0, 0, 0},
{"sort-records",
"Sort records according to an index. This makes your data much more localized and may speed up things. (It may be VERY slow to do a sort the first time!)",
(gptr*) &check_param.opt_sort_key, (gptr*) &check_param.opt_sort_key, 0,
GET_LONG, REQUIRED_ARG, 'R', 0, 0, 0, 0, 0, 0},
{"sort-recover",
"Force recovering with sorting even if the temporary file was very big.",
0, 0, 0, GET_NO_ARG, NO_ARG, 'n', 0, 0, 0, 0, 0, 0},
{"tmpdir", "Path for temporary files.", (gptr*) &check_param.tmpdir, 0, 0,
GET_STR, REQUIRED_ARG, 't', 0, 0, 0, 0, 0, 0},
{"update-state", "Mark tables as crashed if any errors were found.", 0, 0,
0, GET_NO_ARG, NO_ARG, 'U', 0, 0, 0, 0, 0, 0},
{"unpack", "Unpack file packed with myisampack.", 0, 0, 0, GET_NO_ARG,
NO_ARG, 'u', 0, 0, 0, 0, 0, 0},
{"verbose",
"Print more information. This can be used with --describe and --check. Use many -v for more verbosity!", 0, 0, 0, GET_NO_ARG, NO_ARG, 'v', 0, 0, 0, 0, 0,
0},
{"version", "Print version and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 'V', 0,
0, 0, 0, 0, 0},
{"wait", "Wait if table is locked.", 0, 0, 0, GET_NO_ARG, NO_ARG, 'w', 0, 0,
0, 0, 0, 0},
{ "key_buffer_size", "", (gptr*) &check_param.use_buffers,
(gptr*) &check_param.use_buffers, 0, GET_LONG, REQUIRED_ARG,
OPT_KEY_BUFFER_SIZE, (long) USE_BUFFER_INIT, (long) MALLOC_OVERHEAD,
(long) ~0L, (long) MALLOC_OVERHEAD, (long) IO_SIZE, 0},
{ "myisam_block_size", "", (gptr*) &opt_myisam_block_size,
(gptr*) &opt_myisam_block_size, 0, GET_LONG, REQUIRED_ARG,
OPT_MYISAM_BLOCK_SIZE, MI_KEY_BLOCK_LENGTH, MI_MIN_KEY_BLOCK_LENGTH,
MI_MAX_KEY_BLOCK_LENGTH, 0, MI_MIN_KEY_BLOCK_LENGTH, 0},
{ "read_buffer_size", "", (gptr*) &check_param.read_buffer_length,
(gptr*) &check_param.read_buffer_length, 0, GET_LONG, REQUIRED_ARG,
OPT_READ_BUFFER_SIZE, (long) READ_BUFFER_INIT, (long) MALLOC_OVERHEAD,
(long) ~0L, (long) MALLOC_OVERHEAD, (long) 1L, 0},
{ "write_buffer_size", "", (gptr*) &check_param.write_buffer_length,
(gptr*) &check_param.write_buffer_length, 0, GET_LONG, REQUIRED_ARG,
OPT_WRITE_BUFFER_SIZE, (long) READ_BUFFER_INIT, (long) MALLOC_OVERHEAD,
(long) ~0L, (long) MALLOC_OVERHEAD, (long) 1L, 0},
{ "sort_buffer_size", "", (gptr*) &check_param.sort_buffer_length,
(gptr*) &check_param.sort_buffer_length, 0, GET_LONG, REQUIRED_ARG,
OPT_SORT_BUFFER_SIZE, (long) SORT_BUFFER_INIT,
(long) (MIN_SORT_BUFFER + MALLOC_OVERHEAD), (long) ~0L,
(long) MALLOC_OVERHEAD, (long) 1L, 0},
{ "sort_key_blocks", "", (gptr*) &check_param.sort_key_blocks,
(gptr*) &check_param.sort_key_blocks, 0, GET_LONG, REQUIRED_ARG,
OPT_SORT_KEY_BLOCKS, BUFFERS_WHEN_SORTING, 4L, 100L, 0L, 1L, 0},
{ "decode_bits", "", (gptr*) &decode_bits, (gptr*) &decode_bits, 0,
GET_LONG, REQUIRED_ARG, OPT_DECODE_BITS, 9L, 4L, 17L, 0L, 1L, 0},
{ "ft_min_word_len", "", (gptr*) &ft_min_word_len, (gptr*) &ft_min_word_len,
0, GET_LONG, REQUIRED_ARG, OPT_FT_MIN_WORD_LEN, 4, 1, HA_FT_MAXLEN, 0, 1,
0},
{ "ft_max_word_len", "", (gptr*) &ft_max_word_len, (gptr*) &ft_max_word_len,
0, GET_LONG, REQUIRED_ARG, OPT_FT_MAX_WORD_LEN, HA_FT_MAXLEN, 10,
HA_FT_MAXLEN, 0, 1, 0},
{ "ft_max_word_len_for_sort", "", (gptr*) &ft_max_word_len_for_sort,
(gptr*) &ft_max_word_len_for_sort, 0, GET_LONG, REQUIRED_ARG,
OPT_FT_MAX_WORD_LEN_FOR_SORT, 20, 4, HA_FT_MAXLEN, 0, 1, 0},
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};
static void print_version(void)
{
printf("%s Ver 2.2 for %s at %s\n", my_progname, SYSTEM_TYPE,
printf("%s Ver 2.3 for %s at %s\n", my_progname, SYSTEM_TYPE,
MACHINE_TYPE);
}
static void usage(void)
{
uint i;
print_version();
puts("By Monty, for your professional use");
puts("This software comes with NO WARRANTY: see the PUBLIC for details.\n");
......@@ -297,17 +371,9 @@ static void usage(void)
data much more localized and may speed up things\n\
(It may be VERY slow to do a sort the first time!)");
print_defaults("my",load_default_groups);
printf("\nThe variables you can set are:\n");
for (i=0; my_long_options[i].name ; i++)
{
if (!my_long_options[i].opt_is_var)
continue;
#ifdef TO_BE_FIXED
printf("%-20s current value: %lu\n", my_long_options[i].name,
*my_long_options[i].value);
#endif
}
print_defaults("my", load_default_groups);
putchar('\n');
my_print_variables(my_long_options);
}
......@@ -322,46 +388,82 @@ get_one_option(int optid,
switch (optid) {
case 'a':
if (argument && *argument == '0')
check_param.testflag&= ~T_STATISTICS;
else
check_param.testflag|= T_STATISTICS;
break;
case 'A':
if (argument)
check_param.auto_increment_value=strtoull(argument, NULL, 0);
check_param.auto_increment_value= strtoull(argument, NULL, 0);
else
check_param.auto_increment_value=0; /* Set to max used value */
check_param.auto_increment_value= 0; /* Set to max used value */
check_param.testflag|= T_AUTO_INC;
break;
case 'b':
check_param.search_after_block=strtoul(argument, NULL, 10);
check_param.search_after_block= strtoul(argument, NULL, 10);
break;
case 'B':
if (argument && *argument == '0')
check_param.testflag&= ~T_BACKUP_DATA;
else
check_param.testflag|= T_BACKUP_DATA;
break;
case 'c':
if (argument && *argument == '0')
check_param.testflag&= ~T_CHECK;
else
check_param.testflag|= T_CHECK;
break;
case 'C':
if (argument && *argument == '0')
{
check_param.testflag&= ~T_CHECK;
check_param.testflag&= ~T_CHECK_ONLY_CHANGED;
}
else
check_param.testflag|= T_CHECK | T_CHECK_ONLY_CHANGED;
break;
case 'D':
check_param.max_data_file_length=strtoll(argument, NULL, 10);
break;
case 's': /* silent */
if (argument && *argument == '0')
{
if (check_param.testflag & T_VERY_SILENT)
check_param.testflag&= ~T_VERY_SILENT;
check_param.testflag&= ~T_SILENT;
}
else
{
if (check_param.testflag & T_SILENT)
check_param.testflag|=T_VERY_SILENT;
check_param.testflag|= T_VERY_SILENT;
check_param.testflag|= T_SILENT;
check_param.testflag&= ~T_WRITE_LOOP;
}
break;
case 'w':
if (argument && *argument == '0')
check_param.testflag&= ~T_WAIT_FOREVER;
else
check_param.testflag|= T_WAIT_FOREVER;
break;
case 'd': /* description if isam-file */
if (argument && *argument == '0')
check_param.testflag&= ~T_DESCRIPT;
else
check_param.testflag|= T_DESCRIPT;
break;
case 'e': /* extend check */
if (argument && *argument == '0')
check_param.testflag&= ~T_EXTEND;
else
check_param.testflag|= T_EXTEND;
break;
case 'i':
if (argument && *argument == '0')
check_param.testflag&= ~T_INFO;
else
check_param.testflag|= T_INFO;
break;
case 'f':
......@@ -369,12 +471,18 @@ get_one_option(int optid,
check_param.testflag|= T_FORCE_CREATE | T_UPDATE_STATE;
break;
case 'F':
check_param.testflag|=T_FAST;
if (argument && *argument == '0')
check_param.testflag&= ~T_FAST;
else
check_param.testflag|= T_FAST;
break;
case 'k':
check_param.keys_in_use= (ulonglong) strtoll(argument, NULL, 10);
break;
case 'm':
if (argument && *argument == '0')
check_param.testflag&= ~T_MEDIUM;
else
check_param.testflag|= T_MEDIUM; /* Medium check */
break;
case 'r': /* Repair table */
......@@ -387,22 +495,34 @@ get_one_option(int optid,
break;
case 'n':
check_param.testflag= (check_param.testflag & ~T_REP) | T_REP_BY_SORT;
check_param.force_sort=1;
check_param.force_sort= 1;
break;
case 'q':
if (argument && *argument == '0')
check_param.opt_rep_quick--;
else
check_param.opt_rep_quick++;
break;
case 'u':
if (argument && *argument == '0')
{
check_param.testflag&= ~T_UNPACK;
check_param.testflag&= ~T_REP_BY_SORT;
}
else
check_param.testflag|= T_UNPACK | T_REP_BY_SORT;
break;
case 'v': /* Verbose */
if (argument && *argument == '0')
check_param.testflag&= ~T_VERBOSE;
else
check_param.testflag|= T_VERBOSE;
check_param.verbose++;
break;
case 'R': /* Sort records */
old_testflag=check_param.testflag;
old_testflag= check_param.testflag;
check_param.testflag|= T_SORT_RECORDS;
check_param.opt_sort_key=(uint) atoi(argument) - 1;
check_param.opt_sort_key= (uint) atoi(argument) - 1;
if (check_param.opt_sort_key >= MI_MAX_KEY)
{
fprintf(stderr,
......@@ -412,16 +532,25 @@ get_one_option(int optid,
}
break;
case 'S': /* Sort index */
old_testflag=check_param.testflag;
old_testflag= check_param.testflag;
if (argument && *argument == '0')
check_param.testflag&= ~T_SORT_INDEX;
else
check_param.testflag|= T_SORT_INDEX;
break;
case 't':
check_param.tmpdir=argument;
check_param.tmpdir= argument;
break;
case 'T':
if (argument && *argument == '0')
check_param.testflag&= ~T_READONLY;
else
check_param.testflag|= T_READONLY;
break;
case 'U':
if (argument && *argument == '0')
check_param.testflag&= ~T_UPDATE_STATE;
else
check_param.testflag|= T_UPDATE_STATE;
break;
case '#':
......@@ -431,14 +560,14 @@ get_one_option(int optid,
print_version();
exit(0);
case OPT_CORRECT_CHECKSUM:
if (*argument && *argument == '0')
if (argument && *argument == '0')
check_param.testflag&= ~T_CALC_CHECKSUM;
else
check_param.testflag|=T_CALC_CHECKSUM;
check_param.testflag|= T_CALC_CHECKSUM;
break;
#ifdef DEBUG /* Only useful if debugging */
case OPT_START_CHECK_POS:
check_param.start_check_pos=strtoull(argument, NULL, 0);
check_param.start_check_pos= strtoull(argument, NULL, 0);
break;
#endif
case '?':
......
......@@ -29,8 +29,15 @@ static my_bool compare_strings (register const char *s, register const char *t,
static longlong getopt_ll (char *arg, const struct my_option *optp, int *err);
static void init_variables(const struct my_option *options);
#define DISABLE_OPTION_COUNT 2
static const char *special_opt_prefix[]=
{"skip", "disable", "enable", "maximum", 0};
/* Return error values from handle_options */
#define ERR_UNKNOWN_OPTION 1
#define ERR_AMBIGUOUS_OPTION 2
#define ERR_NO_ARGUMENT_ALLOWED 3
......@@ -41,9 +48,6 @@ static void init_variables(const struct my_option *options);
#define ERR_UNKNOWN_SUFFIX 8
#define ERR_NO_PTR_TO_VARIABLE 9
static const char *special_opt_prefix[]=
{"skip", "disable", "enable", "maximum", 0};
/*
function: handle_options
......@@ -63,54 +67,51 @@ int handle_options(int *argc, char ***argv,
{
uint opt_found, argvpos= 0, length, spec_len, i;
int err;
my_bool end_of_options= 0, must_be_var, set_maximum_value;
my_bool end_of_options= 0, must_be_var, set_maximum_value, special_used;
char *progname= *(*argv), **pos, *optend, *prev_found;
const struct my_option *optp;
LINT_INIT(opt_found);
(*argc)--; /* Skip the program name */
(*argv)++; /* --- || ---- */
init_variables(longopts);
for (pos= *argv; *pos; pos++)
{
char *cur_arg= *pos;
if (*cur_arg == '-' && *(cur_arg + 1) && !end_of_options) /* must be opt */
if (cur_arg[0] == '-' && cur_arg[1] && !end_of_options) /* must be opt */
{
char *argument= 0;
must_be_var= 0;
set_maximum_value= 0;
special_used= 0;
/* check for long option, or --set-variable (-O) */
if (*(cur_arg + 1) == '-' || *(cur_arg + 1) == 'O')
{
if (*(cur_arg + 1) == 'O' ||
!compare_strings(cur_arg, "--set-variable", 14))
cur_arg++; /* skip '-' */
if (*cur_arg == 'O')
{
must_be_var= 1;
if (*(cur_arg + 1) == 'O')
{
cur_arg+= 2;
if (!(*cur_arg))
if (!(*++cur_arg)) /* If not -Ovar=# */
{
/* the argument must be in next argv */
if (!(*(pos + 1)))
if (!*++pos)
{
fprintf(stderr, "%s: Option '-O' requires an argument\n",
progname);
return ERR_ARGUMENT_REQUIRED;
}
pos++;
cur_arg= *pos;
(*argc)--;
}
}
else /* Option argument begins with string '--set-variable' */
else if (*cur_arg == '-') /* check for long option, or --set-variable */
{
cur_arg+= 14;
if (*cur_arg == '=')
if (!compare_strings(cur_arg, "-set-variable", 13))
{
cur_arg++;
if (!(*cur_arg))
must_be_var= 1;
if (cur_arg[13] == '=')
{
cur_arg+= 14;
if (!*cur_arg)
{
fprintf(stderr,
"%s: Option '--set-variable' requires an argument\n",
......@@ -118,40 +119,39 @@ int handle_options(int *argc, char ***argv,
return ERR_ARGUMENT_REQUIRED;
}
}
else if (*cur_arg) /* garbage, or another option. break out */
{
cur_arg-= 14;
else if (cur_arg[14]) /* garbage, or another option. break out */
must_be_var= 0;
}
else
{
/* the argument must be in next argv */
if (!(*(pos + 1)))
if (!*++pos)
{
fprintf(stderr,
"%s: Option '--set-variable' requires an argument\n",
progname);
return ERR_ARGUMENT_REQUIRED;
}
pos++;
cur_arg= *pos;
(*argc)--;
}
}
}
else if (!must_be_var)
{
/* '--' means end of options, look no further */
if (!*(cur_arg + 2))
if (!*++cur_arg) /* skip the double dash */
{
/* '--' means end of options, look no further */
end_of_options= 1;
(*argc)--;
continue;
}
cur_arg+= 2; /* skip the double dash */
}
for (optend= cur_arg; *optend && *optend != '='; optend++) ;
optend= strcend(cur_arg, '=');
length= optend - cur_arg;
if (*optend == '=')
optend++;
else
optend=0;
/*
Find first the right option. Return error in case of an ambiguous,
or unknown option
......@@ -165,7 +165,7 @@ int handle_options(int *argc, char ***argv,
*/
if (!must_be_var)
{
if (*optend == '=')
if (optend)
must_be_var= 1;
for (i= 0; special_opt_prefix[i]; i++)
{
......@@ -176,6 +176,7 @@ int handle_options(int *argc, char ***argv,
/*
We were called with a special prefix, we can reuse opt_found
*/
special_used= 1;
cur_arg += (spec_len + 1);
if ((opt_found= findopt(cur_arg, length - (spec_len + 1),
&optp, &prev_found)))
......@@ -189,9 +190,9 @@ int handle_options(int *argc, char ***argv,
return ERR_AMBIGUOUS_OPTION;
}
if (i < DISABLE_OPTION_COUNT)
optend= (char*) "=0";
optend= (char*) "0";
else if (!compare_strings(special_opt_prefix[i],"enable",6))
optend= (char*) "=1";
optend= (char*) "1";
else if (!compare_strings(special_opt_prefix[i],"maximum",7))
{
set_maximum_value= 1;
......@@ -233,81 +234,81 @@ int handle_options(int *argc, char ***argv,
return ERR_AMBIGUOUS_OPTION;
}
}
if (must_be_var && !optp->opt_is_var)
if (must_be_var && !optp->value)
{
fprintf(stderr, "%s: the argument '%s' is not an variable\n",
progname, *pos);
return ERR_MUST_BE_VARIABLE;
}
if (optp->arg_type == NO_ARG && *optend == '=')
if (optp->arg_type == NO_ARG && optend && !special_used)
{
fprintf(stderr, "%s: option '--%s' cannot take an argument\n",
progname, optp->name);
return ERR_NO_ARGUMENT_ALLOWED;
}
else if (optp->arg_type == REQUIRED_ARG && !*optend)
else if (optp->arg_type == REQUIRED_ARG && !optend)
{
/* Check if there are more arguments after this one */
if (!(*(pos + 1)))
if (!*++pos)
{
fprintf(stderr, "%s: option '--%s' requires an argument\n",
progname, optp->name);
return ERR_ARGUMENT_REQUIRED;
}
pos++;
argument= *pos;
(*argc)--;
}
else if (*optend == '=')
argument= *(optend + 1) ? optend + 1 : (char*) "";
else
argument= optend;
}
else /* must be short option */
{
my_bool skip;
for (skip= 0, optend= (cur_arg + 1); *optend && !skip; optend++)
for (optend= cur_arg; *optend; optend++, opt_found= 0)
{
for (optp= longopts; optp->id ; optp++)
for (optp= longopts; optp->id; optp++)
{
if (optp->id == (int) (uchar) *optend)
{
/* Option recognized. Find next what to do with it */
opt_found= 1;
if (optp->arg_type == REQUIRED_ARG || optp->arg_type == OPT_ARG)
{
if (*(optend + 1))
{
argument= (optend + 1);
/*
The rest of the option is option argument
This is in effect a jump out of this loop
*/
skip= 1;
// The rest of the option is option argument
argument= optend + 1;
// This is in effect a jump out of the outer loop
optend= (char*) " ";
}
else if (optp->arg_type == REQUIRED_ARG)
{
/* Check if there are more arguments after this one */
if (!(*(pos + 1)))
if (!*++pos)
{
fprintf(stderr, "%s: option '-%c' requires an argument\n",
progname, optp->id);
return ERR_ARGUMENT_REQUIRED;
}
pos++;
argument= *pos;
(*argc)--;
/* the other loop will break, because *optend + 1 == 0 */
}
}
else
{
/* we are hitting many options in 1 argv */
if (*(optend + 1))
get_one_option(optp->id, optp, 0);
}
get_one_option(optp->id, optp, argument);
break;
}
}
if (!opt_found)
{
fprintf(stderr,
"%s: unknown option '-%c'\n", progname, *cur_arg);
return ERR_UNKNOWN_OPTION;
}
}
(*argc)--; /* option handled (short), decrease argument count */
continue;
}
if (optp->opt_is_var)
if (optp->value)
{
gptr *result_pos= (set_maximum_value) ?
optp->u_max_value : optp->value;
......@@ -349,6 +350,7 @@ int handle_options(int *argc, char ***argv,
list the option found, if any. In case of ambiguous option, store
the name in ffname argument
*/
static int findopt (char *optpat, uint length,
const struct my_option **opt_res,
char **ffname)
......@@ -378,6 +380,7 @@ static int findopt (char *optpat, uint length,
Works like strncmp, other than 1.) considers '-' and '_' the same.
2.) Returns -1 if strings differ, 0 if they are equal
*/
static my_bool compare_strings(register const char *s, register const char *t,
uint length)
{
......@@ -401,6 +404,7 @@ static my_bool compare_strings(register const char *s, register const char *t,
that those values are honored.
In case of an error, set error value in *err.
*/
static longlong getopt_ll (char *arg, const struct my_option *optp, int *err)
{
char *endchar;
......@@ -423,11 +427,14 @@ static longlong getopt_ll (char *arg, const struct my_option *optp, int *err)
}
if (num < (longlong) optp->min_value)
num= (longlong) optp->min_value;
else if (num > 0 && (ulonglong) num > (ulonglong) (ulong) optp->max_value)
else if (num > 0 && (ulonglong) num > (ulonglong) (ulong) optp->max_value
&& optp->max_value) // if max value is not set -> no upper limit
num= (longlong) (ulong) optp->max_value;
num= ((num - (longlong) optp->sub_size) / (ulonglong) optp->block_size);
return (longlong) (num * (ulonglong) optp->block_size);
num= ((num - (longlong) optp->sub_size) / (optp->block_size ?
(ulonglong) optp->block_size :
1L));
return (longlong) (num * (optp->block_size ? (ulonglong) optp->block_size :
1L));
}
......@@ -436,11 +443,12 @@ static longlong getopt_ll (char *arg, const struct my_option *optp, int *err)
initialize all variables to their default values
*/
static void init_variables(const struct my_option *options)
{
for ( ; options->name ; options++)
for (; options->name; options++)
{
if (options->opt_is_var)
if (options->value)
{
if (options->var_type == GET_LONG)
*((long*) options->u_max_value)= *((long*) options->value)=
......@@ -451,3 +459,120 @@ static void init_variables(const struct my_option *options)
}
}
}
/*
function: my_print_options
Print help for all options and variables.
*/
void my_print_help(const struct my_option *options)
{
uint col, name_space= 22, comment_space= 57;
const char *line_end;
const struct my_option *optp;
for (optp= options; optp->id; optp++)
{
if (optp->id < 256)
{
printf(" -%c, ", optp->id);
col= 6;
}
else
{
printf(" ");
col= 2;
}
printf("--%s", optp->name);
col+= 2 + strlen(optp->name);
if (optp->var_type == GET_STR)
{
printf("=name ");
col+= 6;
}
else if (optp->var_type == GET_NO_ARG)
{
putchar(' ');
col++;
}
else
{
printf("=# ");
col+= 3;
}
if (col > name_space)
{
putchar('\n');
col= 0;
}
for (; col < name_space; col++)
putchar(' ');
if (optp->comment && *optp->comment)
{
const char *comment= optp->comment, *end= strend(comment);
while ((uint) (end - comment) > comment_space)
{
for (line_end= comment + comment_space; *line_end != ' '; line_end--);
for (; comment != line_end; comment++)
putchar(*comment);
comment++; // skip the space, as a newline will take it's place now
putchar('\n');
for (col= 0; col < name_space; col++)
putchar(' ');
}
printf("%s", comment);
}
putchar('\n');
}
}
/*
function: my_print_options
Print variables.
*/
void my_print_variables(const struct my_option *options)
{
uint name_space= 34, length;
char buff[255];
const struct my_option *optp;
printf("Variables (--variable-name=value) Default value\n");
printf("--------------------------------- -------------\n");
for (optp= options; optp->id; optp++)
{
if (optp->value)
{
printf("%s", optp->name);
length= strlen(optp->name);
for (; length < name_space; length++)
putchar(' ');
if (optp->var_type == GET_STR)
{
if (!optp->def_value && !*((char**) optp->value))
printf("(No default value)\n");
else
printf("%s\n", *((char**) optp->value));
}
else if (optp->var_type == GET_LONG)
{
if (!optp->def_value && !*((long*) optp->value))
printf("(No default value)\n");
else
printf("%lu\n", *((long*) optp->value));
}
else
{
if (!optp->def_value && !*((longlong*) optp->value))
printf("(No default value)\n");
else
printf("%s\n", llstr(*((longlong*) optp->value), buff));
}
}
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment