Commit c4f1ced9 authored by unknown's avatar unknown

New functionality to my_getopt. myisamchk now uses my_getopt

only.


include/my_getopt.h:
  Added u_max_value as for user definable maximum value for
  a variable in my_getopt.
myisam/myisamchk.c:
  myisamchk now uses my_getopt struct for variables also.
  Variables can be set with -O var=val, --set-variable=var=val and
  --variable=val now.
mysys/getvar.c:
  my_set_changeable_var moved to my_getopt.c
mysys/my_getopt.c:
  Added special prefix --maximum[-variable-name=...] for user
  definable maximum values for variables, among other things.
parent 5b968bb8
...@@ -23,14 +23,15 @@ struct my_optarg ...@@ -23,14 +23,15 @@ struct my_optarg
}; };
enum get_opt_var_type { GET_NO_ARG, GET_INT, GET_LL, GET_STR }; enum get_opt_var_type { GET_NO_ARG, GET_LONG, GET_LL, GET_STR };
enum get_opt_arg_type { NO_ARG, OPT_ARG, REQUIRED_ARG }; enum get_opt_arg_type { NO_ARG, OPT_ARG, REQUIRED_ARG };
struct my_option struct my_option
{ {
const char *name; /* Name of the option */ const char *name; /* Name of the option */
const char *comment; /* option comment, for autom. --help */ const char *comment; /* option comment, for autom. --help */
char *value; /* The variable value */ gptr *value; /* The variable value */
gptr *u_max_value; /* The user def. max variable value */
const char **str_values; /* Pointer to possible values */ const char **str_values; /* Pointer to possible values */
enum get_opt_var_type var_type; enum get_opt_var_type var_type;
enum get_opt_arg_type arg_type; enum get_opt_arg_type arg_type;
...@@ -41,6 +42,6 @@ struct my_option ...@@ -41,6 +42,6 @@ struct my_option
longlong sub_size; /* Subtract this from given value */ longlong sub_size; /* Subtract this from given value */
long block_size; /* Value should be a mult. of this */ long block_size; /* Value should be a mult. of this */
int app_type; /* To be used by an application */ int app_type; /* To be used by an application */
my_bool changeable_var; /* If true, the option is a variable */ my_bool opt_is_var; /* If true, the option is a variable */
}; };
...@@ -142,31 +142,6 @@ int main(int argc, char **argv) ...@@ -142,31 +142,6 @@ int main(int argc, char **argv)
#endif #endif
} /* main */ } /* main */
static CHANGEABLE_VAR changeable_vars[] = {
{ "key_buffer_size",(long*) &check_param.use_buffers,(long) USE_BUFFER_INIT,
(long) MALLOC_OVERHEAD, (long) ~0L,(long) MALLOC_OVERHEAD,(long) IO_SIZE },
{ "myisam_block_size", (long*) &opt_myisam_block_size,
MI_KEY_BLOCK_LENGTH, MI_MIN_KEY_BLOCK_LENGTH, MI_MAX_KEY_BLOCK_LENGTH,
0, MI_MIN_KEY_BLOCK_LENGTH },
{ "read_buffer_size", (long*) &check_param.read_buffer_length,(long) READ_BUFFER_INIT,
(long) MALLOC_OVERHEAD,(long) ~0L,(long) MALLOC_OVERHEAD,(long) 1L },
{ "write_buffer_size", (long*) &check_param.write_buffer_length,(long) READ_BUFFER_INIT,
(long) MALLOC_OVERHEAD,(long) ~0L,(long) MALLOC_OVERHEAD,(long) 1L },
{ "sort_buffer_size",(long*) &check_param.sort_buffer_length,(long) SORT_BUFFER_INIT,
(long) (MIN_SORT_BUFFER+MALLOC_OVERHEAD),(long) ~0L,
(long) MALLOC_OVERHEAD,(long) 1L },
{ "sort_key_blocks",(long*) &check_param.sort_key_blocks,BUFFERS_WHEN_SORTING,4L,100L,0L,
1L },
{ "decode_bits",(long*) &decode_bits,9L,4L,17L,0L,1L },
{ "ft_min_word_len", (long*) &ft_min_word_len,
4, 1, HA_FT_MAXLEN, 0, 1 },
{ "ft_max_word_len", (long*) &ft_max_word_len,
HA_FT_MAXLEN, 10, HA_FT_MAXLEN, 0, 1 },
{ "ft_max_word_len_for_sort",(long*) &ft_max_word_len_for_sort,
20, 4, HA_FT_MAXLEN, 0, 1 },
{ NullS,(long*) 0,0L,0L,0L,0L,0L,} };
enum options { enum options {
OPT_CHARSETS_DIR=256, OPT_SET_CHARSET,OPT_START_CHECK_POS, OPT_CHARSETS_DIR=256, OPT_SET_CHARSET,OPT_START_CHECK_POS,
OPT_CORRECT_CHECKSUM, OPT_KEY_BUFFER_SIZE, OPT_MYISAM_BLOCK_SIZE, OPT_CORRECT_CHECKSUM, OPT_KEY_BUFFER_SIZE, OPT_MYISAM_BLOCK_SIZE,
...@@ -177,63 +152,63 @@ enum options { ...@@ -177,63 +152,63 @@ enum options {
static struct my_option my_long_options[] = static struct my_option my_long_options[] =
{ {
{"analyze", "", 0, 0, GET_NO_ARG, NO_ARG, 'a', 0, 0, 0, 0, 0, 0, 0}, {"analyze", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'a', 0, 0, 0, 0, 0, 0, 0},
{"block-search", "", 0, 0, GET_LL, REQUIRED_ARG, 'b', 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, GET_NO_ARG, NO_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", "", 0, 0, GET_STR, REQUIRED_ARG, OPT_CHARSETS_DIR, 0, 0, 0, 0, 0, 0, 0}, {"character-sets-dir", "", 0, 0, 0, GET_STR, REQUIRED_ARG, OPT_CHARSETS_DIR, 0, 0, 0, 0, 0, 0, 0},
{"check", "", 0, 0, GET_NO_ARG, NO_ARG, 'c', 0, 0, 0, 0, 0, 0, 0}, {"check", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'c', 0, 0, 0, 0, 0, 0, 0},
{"check-only-changed", "", 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, GET_NO_ARG, NO_ARG, OPT_CORRECT_CHECKSUM, 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},
#ifndef DBUG_OFF #ifndef DBUG_OFF
{"debug", "", 0, 0, GET_STR, OPT_ARG, '#', 0, 0, 0, 0, 0, 0, 0}, {"debug", "", 0, 0, 0, GET_STR, OPT_ARG, '#', 0, 0, 0, 0, 0, 0, 0},
#endif #endif
{"description", "", 0, 0, GET_NO_ARG, NO_ARG, 'd', 0, 0, 0, 0, 0, 0, 0}, {"description", "", 0, 0, 0, GET_NO_ARG, NO_ARG, 'd', 0, 0, 0, 0, 0, 0, 0},
{"data-file-length", "", 0, 0, GET_LL, REQUIRED_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, GET_NO_ARG, NO_ARG, 'e', 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, GET_NO_ARG, NO_ARG, 'F', 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, 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, GET_NO_ARG, NO_ARG, '?', 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, GET_NO_ARG, NO_ARG, 'i', 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, GET_LL, REQUIRED_ARG, 'k', 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, GET_NO_ARG, NO_ARG, 'm', 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, GET_NO_ARG, NO_ARG, 'q', 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, GET_NO_ARG, NO_ARG, 'T', 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, GET_NO_ARG, NO_ARG, 'r', 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, GET_NO_ARG, NO_ARG, 'o', 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, GET_LL, REQUIRED_ARG, OPT_START_CHECK_POS, 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, GET_LL, OPT_ARG, 'A', 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, GET_STR, REQUIRED_ARG, OPT_SET_CHARSET, 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, GET_STR, REQUIRED_ARG, 'O', 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, GET_NO_ARG, NO_ARG, 's', 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, 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, GET_INT, REQUIRED_ARG, 'R', 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, GET_NO_ARG, NO_ARG, 'n', 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, GET_STR, REQUIRED_ARG, 't', 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, GET_NO_ARG, NO_ARG, 'U', 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, 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, GET_NO_ARG, NO_ARG, 'v', 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, 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, GET_NO_ARG, NO_ARG, 'w', 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 */ /* variables begin here */
{ "key_buffer_size", "", 0, 0, GET_LL, REQUIRED_ARG, OPT_KEY_BUFFER_SIZE, 0, 0, 0, 0, 0, 0, 1}, { "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", "", 0, 0, GET_LL, REQUIRED_ARG, OPT_MYISAM_BLOCK_SIZE, 0, 0, 0, 0, 0, 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", "", 0, 0, GET_LL, REQUIRED_ARG, OPT_READ_BUFFER_SIZE, 0, 0, 0, 0, 0, 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", "", 0, 0, GET_LL, REQUIRED_ARG, OPT_WRITE_BUFFER_SIZE, 0, 0, 0, 0, 0, 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", "", 0, 0, GET_LL, REQUIRED_ARG, OPT_SORT_BUFFER_SIZE, 0, 0, 0, 0, 0, 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", "", 0, 0, GET_LL, REQUIRED_ARG, OPT_SORT_KEY_BLOCKS, 0, 0, 0, 0, 0, 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", "", 0, 0, GET_LL, REQUIRED_ARG, OPT_DECODE_BITS, 0, 0, 0, 0, 0, 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", "", 0, 0, GET_LL, REQUIRED_ARG, OPT_FT_MIN_WORD_LEN, 0, 0, 0, 0, 0, 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", "", 0, 0, GET_LL, REQUIRED_ARG, OPT_FT_MAX_WORD_LEN, 0, 0, 0, 0, 0, 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", "", 0, 0, GET_LL, REQUIRED_ARG, OPT_FT_MAX_WORD_LEN_FOR_SORT, 0, 0, 0, 0, 0, 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, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
}; };
static void print_version(void) static void print_version(void)
{ {
printf("%s Ver 2.1 for %s at %s\n", my_progname, SYSTEM_TYPE, printf("%s Ver 2.2 for %s at %s\n", my_progname, SYSTEM_TYPE,
MACHINE_TYPE); MACHINE_TYPE);
} }
...@@ -323,10 +298,14 @@ static void usage(void) ...@@ -323,10 +298,14 @@ static void usage(void)
print_defaults("my",load_default_groups); print_defaults("my",load_default_groups);
printf("\nPossible variables for option --set-variable (-O) are:\n"); printf("\nPossible variables for option --set-variable (-O) are:\n");
for (i=0; changeable_vars[i].name ; i++) for (i=0; my_long_options[i].name ; i++)
printf("%-20s current value: %lu\n", {
changeable_vars[i].name, if (!my_long_options[i].opt_is_var)
*changeable_vars[i].varptr); continue;
printf("%-20s current value: %lu\n", my_long_options[i].name,
*my_long_options[i].value);
}
} }
...@@ -417,27 +396,6 @@ static my_bool get_one_option(int optid, const struct my_option *opt, ...@@ -417,27 +396,6 @@ static my_bool get_one_option(int optid, const struct my_option *opt,
check_param.testflag|= T_VERBOSE; check_param.testflag|= T_VERBOSE;
check_param.verbose++; check_param.verbose++;
break; break;
case 'O':
/* this is a temporary fix for variables to work until my_getopt */
/* can my_set_changeable_vars */
case OPT_KEY_BUFFER_SIZE:
case OPT_MYISAM_BLOCK_SIZE:
case OPT_READ_BUFFER_SIZE:
case OPT_WRITE_BUFFER_SIZE:
case OPT_SORT_BUFFER_SIZE:
case OPT_SORT_KEY_BLOCKS:
case OPT_DECODE_BITS:
case OPT_FT_MIN_WORD_LEN:
case OPT_FT_MAX_WORD_LEN:
case OPT_FT_MAX_WORD_LEN_FOR_SORT:
end= buff;
end= strmov(strmov(strmov(end, opt->name), "="), argument);
if (set_changeable_var(buff, changeable_vars))
{
usage();
exit(1);
}
break;
case 'R': /* Sort records */ case 'R': /* Sort records */
old_testflag=check_param.testflag; old_testflag=check_param.testflag;
check_param.testflag|= T_SORT_RECORDS; check_param.testflag|= T_SORT_RECORDS;
...@@ -492,11 +450,10 @@ static my_bool get_one_option(int optid, const struct my_option *opt, ...@@ -492,11 +450,10 @@ static my_bool get_one_option(int optid, const struct my_option *opt,
static void get_options(register int *argc,register char ***argv) static void get_options(register int *argc,register char ***argv)
{ {
int c,option_index=0; int c, option_index=0;
load_defaults("my",load_default_groups,argc,argv); load_defaults("my", load_default_groups, argc, argv);
default_argv= *argv; default_argv= *argv;
set_all_changeable_vars(changeable_vars);
if (isatty(fileno(stdout))) if (isatty(fileno(stdout)))
check_param.testflag|=T_WRITE_LOOP; check_param.testflag|=T_WRITE_LOOP;
......
...@@ -109,78 +109,3 @@ my_bool set_changeable_var(my_string str,CHANGEABLE_VAR *vars) ...@@ -109,78 +109,3 @@ my_bool set_changeable_var(my_string str,CHANGEABLE_VAR *vars)
} }
DBUG_RETURN(1); DBUG_RETURN(1);
} }
my_bool my_set_changeable_var(my_string str, const struct my_option *vars)
{
char endchar;
my_string end;
DBUG_ENTER("my_set_changeable_var");
DBUG_PRINT("enter",("%s",str));
if (str)
{
if (!(end=strchr(str,'=')))
fprintf(stderr,"Can't find '=' in expression '%s' to option -O\n",str);
else
{
uint length,found_count=0;
const struct my_option *var, *found;
my_string var_end;
const char *name;
longlong num;
/* Skip end space from variable */
for (var_end=end ; end > str && isspace(var_end[-1]) ; var_end--) ;
length=(uint) (var_end-str);
/* Skip start space from argument */
for (end++ ; isspace(*end) ; end++) ;
for (var= vars, found= 0; (name= var->name); var++)
{
if (var->changeable_var)
{
if (!my_casecmp(name, str, length))
{
found= var; found_count++;
if (!name[length])
{
found_count=1;
break;
}
}
}
}
if (found_count == 0)
{
fprintf(stderr,"No variable match for: -O '%s'\n",str);
DBUG_RETURN(1);
}
if (found_count > 1)
{
fprintf(stderr,"Variable prefix '%*s' is not unique\n",length,str);
DBUG_RETURN(1);
}
num=strtoll(end, (char **)NULL, 10); endchar=strend(end)[-1];
if (endchar == 'k' || endchar == 'K')
num*=1024;
else if (endchar == 'm' || endchar == 'M')
num*=1024L*1024L;
else if (endchar == 'g' || endchar == 'G')
num*=1024L*1024L*1024L;
else if (!isdigit(endchar))
{
fprintf(stderr,"Unknown prefix used for variable value '%s'\n",str);
DBUG_RETURN(1);
}
if (num < (longlong) found->min_value)
num=(longlong) found->min_value;
else if (num > 0 && (ulonglong) num > (ulonglong) (ulong) found->max_value)
num=(longlong) (ulong) found->max_value;
num=((num- (longlong) found->sub_size) / (ulonglong) found->block_size);
/* (*found->varptr)= (long) (num*(ulonglong) found->block_size);*/
DBUG_RETURN(0);
}
}
DBUG_RETURN(1);
}
...@@ -21,17 +21,31 @@ ...@@ -21,17 +21,31 @@
#include <my_getopt.h> #include <my_getopt.h>
#include <assert.h> #include <assert.h>
static int sortopt (int *argc, char ***argv);
static int findopt (char *optpat, uint length, static int findopt (char *optpat, uint length,
const struct my_option **opt_res, const struct my_option **opt_res,
char **ffname); char **ffname);
static my_bool compare_strings (register const char *s, register const char *t,
uint length);
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 #define DISABLE_OPTION_COUNT 2
static char *special_opt_prefix[] = {"skip", "disable", "enable", 0}; #define ERR_UNKNOWN_OPTION 1
#define ERR_AMBIGUOUS_OPTION 2
#define ERR_NO_ARGUMENT_ALLOWED 3
#define ERR_ARGUMENT_REQUIRED 4
#define ERR_VAR_PREFIX_NOT_UNIQUE 5
#define ERR_UNKNOWN_VARIABLE 6
#define ERR_MUST_BE_VARIABLE 7
#define ERR_UNKNOWN_SUFFIX 8
static char *special_opt_prefix[]= {"skip", "disable", "enable", "maximum", 0};
/*
function: handle_options
/* function: handle_options
Sort options; put options first, until special end of options (--), or Sort options; put options first, until special end of options (--), or
until end of argv. Parse options; check that the given option matches with until end of argv. Parse options; check that the given option matches with
one of the options in struct 'my_option', return error in case of ambiguous one of the options in struct 'my_option', return error in case of ambiguous
...@@ -44,25 +58,29 @@ extern int handle_options (int *argc, char ***argv, ...@@ -44,25 +58,29 @@ extern int handle_options (int *argc, char ***argv,
const struct my_option *, const struct my_option *,
char *)) char *))
{ {
uint opt_found, argvpos = 0, length, spec_len, i; uint opt_found, argvpos= 0, length, spec_len, i;
my_bool end_of_options = 0, must_be_var = 0; int err;
char *progname = *(*argv), **pos, *optend, *prev_found; my_bool end_of_options= 0, must_be_var, set_maximum_value;
char *progname= *(*argv), **pos, *optend, *prev_found;
const struct my_option *optp; const struct my_option *optp;
(*argc)--; (*argc)--; /* Skip the program name */
(*argv)++; (*argv)++; /* --- || ---- */
for (pos = *argv; *pos; pos++) init_variables(longopts);
for (pos= *argv; *pos; pos++)
{ {
char *cur_arg= *pos; char *cur_arg= *pos;
if (*cur_arg == '-' && *(cur_arg + 1) && !end_of_options) // must be opt. if (*cur_arg == '-' && *(cur_arg + 1) && !end_of_options) // must be opt.
{ {
char *argument = 0; char *argument= 0;
must_be_var= 0; must_be_var= 0;
set_maximum_value= 0;
// check for long option, or --set-variable (-O) // check for long option, or --set-variable (-O)
if (*(cur_arg + 1) == '-' || *(cur_arg + 1) == 'O') if (*(cur_arg + 1) == '-' || *(cur_arg + 1) == 'O')
{ {
if (*(cur_arg + 1) == 'O' || !strncmp(cur_arg, "--set-variable", 14)) if (*(cur_arg + 1) == 'O' ||
!compare_strings(cur_arg, "--set-variable", 14))
{ {
must_be_var= 1; must_be_var= 1;
...@@ -76,7 +94,7 @@ extern int handle_options (int *argc, char ***argv, ...@@ -76,7 +94,7 @@ extern int handle_options (int *argc, char ***argv,
{ {
fprintf(stderr, "%s: Option '-O' requires an argument\n", fprintf(stderr, "%s: Option '-O' requires an argument\n",
progname); progname);
return 4; return ERR_ARGUMENT_REQUIRED;
} }
pos++; pos++;
cur_arg= *pos; cur_arg= *pos;
...@@ -94,7 +112,7 @@ extern int handle_options (int *argc, char ***argv, ...@@ -94,7 +112,7 @@ extern int handle_options (int *argc, char ***argv,
fprintf(stderr, fprintf(stderr,
"%s: Option '--set-variable' requires an argument\n", "%s: Option '--set-variable' requires an argument\n",
progname); progname);
return 4; return ERR_ARGUMENT_REQUIRED;
} }
} }
else if (*cur_arg) // garbage, or another option. break out else if (*cur_arg) // garbage, or another option. break out
...@@ -110,7 +128,7 @@ extern int handle_options (int *argc, char ***argv, ...@@ -110,7 +128,7 @@ extern int handle_options (int *argc, char ***argv,
fprintf(stderr, fprintf(stderr,
"%s: Option '--set-variable' requires an argument\n", "%s: Option '--set-variable' requires an argument\n",
progname); progname);
return 4; return ERR_ARGUMENT_REQUIRED;
} }
pos++; pos++;
cur_arg= *pos; cur_arg= *pos;
...@@ -122,36 +140,38 @@ extern int handle_options (int *argc, char ***argv, ...@@ -122,36 +140,38 @@ extern int handle_options (int *argc, char ***argv,
{ {
if (!*(cur_arg + 2)) // '--' means end of options, look no further if (!*(cur_arg + 2)) // '--' means end of options, look no further
{ {
end_of_options = 1; end_of_options= 1;
(*argc)--; (*argc)--;
continue; continue;
} }
cur_arg+= 2; // skip the double dash cur_arg+= 2; // skip the double dash
} }
for (optend = cur_arg; *optend && *optend != '='; optend++) ; for (optend= cur_arg; *optend && *optend != '='; optend++) ;
length = optend - cur_arg; length= optend - cur_arg;
/* /*
Find first the right option. Return error in case of an ambiguous, Find first the right option. Return error in case of an ambiguous,
or unknown option or unknown option
*/ */
optp = longopts; optp= longopts;
if (!(opt_found = findopt(cur_arg, length, &optp, &prev_found))) if (!(opt_found= findopt(cur_arg, length, &optp, &prev_found)))
{ {
/* /*
Didn't find any matching option. Let's see if someone called Didn't find any matching option. Let's see if someone called
option with a special option prefix option with a special option prefix
*/ */
if (*optend != '=' && !must_be_var) if (!must_be_var)
{ {
for (i = 0; special_opt_prefix[i]; i++) if (*optend == '=')
must_be_var= 1;
for (i= 0; special_opt_prefix[i]; i++)
{ {
spec_len = strlen(special_opt_prefix[i]); spec_len= strlen(special_opt_prefix[i]);
if (!strncmp(special_opt_prefix[i], cur_arg, spec_len) && if (!compare_strings(special_opt_prefix[i], cur_arg, spec_len) &&
cur_arg[spec_len] == '-') cur_arg[spec_len] == '-')
{ {
// We were called with a special prefix, we can reuse opt_found // We were called with a special prefix, we can reuse opt_found
cur_arg += (spec_len + 1); cur_arg += (spec_len + 1);
if ((opt_found = findopt(cur_arg, length - (spec_len + 1), if ((opt_found= findopt(cur_arg, length - (spec_len + 1),
&optp, &prev_found))) &optp, &prev_found)))
{ {
if (opt_found > 1) if (opt_found > 1)
...@@ -160,12 +180,17 @@ extern int handle_options (int *argc, char ***argv, ...@@ -160,12 +180,17 @@ extern int handle_options (int *argc, char ***argv,
"%s: ambiguous option '--%s-%s' (--%s-%s)\n", "%s: ambiguous option '--%s-%s' (--%s-%s)\n",
progname, special_opt_prefix[i], cur_arg, progname, special_opt_prefix[i], cur_arg,
special_opt_prefix[i], prev_found); special_opt_prefix[i], prev_found);
return 2; return ERR_AMBIGUOUS_OPTION;
} }
if (i < DISABLE_OPTION_COUNT) if (i < DISABLE_OPTION_COUNT)
optend= "=0"; optend= "=0";
else // enable else if (!compare_strings(special_opt_prefix[i],"enable",6))
optend= "=1"; optend= "=1";
else if (!compare_strings(special_opt_prefix[i],"maximum",7))
{
set_maximum_value= 1;
must_be_var= 1;
}
break; // note break from the inner loop, main loop continues break; // note break from the inner loop, main loop continues
} }
} }
...@@ -177,13 +202,13 @@ extern int handle_options (int *argc, char ***argv, ...@@ -177,13 +202,13 @@ extern int handle_options (int *argc, char ***argv,
{ {
fprintf(stderr, fprintf(stderr,
"%s: unknown variable '%s'\n", progname, cur_arg); "%s: unknown variable '%s'\n", progname, cur_arg);
return 7; return ERR_UNKNOWN_VARIABLE;
} }
else else
{ {
fprintf(stderr, fprintf(stderr,
"%s: unknown option '--%s'\n", progname, cur_arg); "%s: unknown option '--%s'\n", progname, cur_arg);
return 1; return ERR_UNKNOWN_OPTION;
} }
} }
} }
...@@ -193,26 +218,26 @@ extern int handle_options (int *argc, char ***argv, ...@@ -193,26 +218,26 @@ extern int handle_options (int *argc, char ***argv,
{ {
fprintf(stderr, "%s: variable prefix '%s' is not unique\n", fprintf(stderr, "%s: variable prefix '%s' is not unique\n",
progname, cur_arg); progname, cur_arg);
return 6; return ERR_VAR_PREFIX_NOT_UNIQUE;
} }
else else
{ {
fprintf(stderr, "%s: ambiguous option '--%s' (%s, %s)\n", fprintf(stderr, "%s: ambiguous option '--%s' (%s, %s)\n",
progname, cur_arg, prev_found, optp->name); progname, cur_arg, prev_found, optp->name);
return 2; return ERR_AMBIGUOUS_OPTION;
} }
} }
if (must_be_var && !optp->changeable_var) if (must_be_var && !optp->opt_is_var)
{ {
fprintf(stderr, "%s: the argument to -O must be a variable\n", fprintf(stderr, "%s: the argument to -O must be a variable\n",
progname); progname);
return 8; return ERR_MUST_BE_VARIABLE;
} }
if (optp->arg_type == NO_ARG && *optend == '=') if (optp->arg_type == NO_ARG && *optend == '=')
{ {
fprintf(stderr, "%s: option '--%s' cannot take an argument\n", fprintf(stderr, "%s: option '--%s' cannot take an argument\n",
progname, optp->name); progname, optp->name);
return 3; return ERR_NO_ARGUMENT_ALLOWED;
} }
else if (optp->arg_type == REQUIRED_ARG && !*optend) else if (optp->arg_type == REQUIRED_ARG && !*optend)
{ {
...@@ -221,21 +246,21 @@ extern int handle_options (int *argc, char ***argv, ...@@ -221,21 +246,21 @@ extern int handle_options (int *argc, char ***argv,
{ {
fprintf(stderr, "%s: option '--%s' requires an argument\n", fprintf(stderr, "%s: option '--%s' requires an argument\n",
progname, optp->name); progname, optp->name);
return 4; return ERR_ARGUMENT_REQUIRED;
} }
pos++; pos++;
argument = *pos; argument= *pos;
(*argc)--; (*argc)--;
} }
else if (*optend == '=') else if (*optend == '=')
argument = *(optend + 1) ? optend + 1 : ""; argument= *(optend + 1) ? optend + 1 : "";
} }
else // must be short option else // must be short option
{ {
my_bool skip; my_bool skip;
for (skip = 0, optend = (cur_arg + 1); *optend && !skip; optend++) for (skip= 0, optend= (cur_arg + 1); *optend && !skip; optend++)
{ {
for (optp = longopts; optp->id ; optp++) for (optp= longopts; optp->id ; optp++)
{ {
if (optp->id == (int) (uchar) *optend) if (optp->id == (int) (uchar) *optend)
{ {
...@@ -244,12 +269,12 @@ extern int handle_options (int *argc, char ***argv, ...@@ -244,12 +269,12 @@ extern int handle_options (int *argc, char ***argv,
{ {
if (*(optend + 1)) if (*(optend + 1))
{ {
argument = (optend + 1); argument= (optend + 1);
/* /*
The rest of the option is option argument The rest of the option is option argument
This is in effect a jump out of this loop This is in effect a jump out of this loop
*/ */
skip = 1; skip= 1;
} }
else if (optp->arg_type == REQUIRED_ARG) else if (optp->arg_type == REQUIRED_ARG)
{ {
...@@ -258,10 +283,10 @@ extern int handle_options (int *argc, char ***argv, ...@@ -258,10 +283,10 @@ extern int handle_options (int *argc, char ***argv,
{ {
fprintf(stderr, "%s: option '-%c' requires an argument\n", fprintf(stderr, "%s: option '-%c' requires an argument\n",
progname, optp->id); progname, optp->id);
return 4; return ERR_ARGUMENT_REQUIRED;
} }
pos++; pos++;
argument = *pos; argument= *pos;
(*argc)--; (*argc)--;
} }
} }
...@@ -272,16 +297,34 @@ extern int handle_options (int *argc, char ***argv, ...@@ -272,16 +297,34 @@ extern int handle_options (int *argc, char ***argv,
} }
} }
} }
if (optp->opt_is_var)
{
gptr *result_pos= (set_maximum_value) ?
optp->u_max_value : optp->value;
if (optp->var_type == GET_LONG)
*((long*) result_pos)= (long) getopt_ll(argument, optp, &err);
else if (optp->var_type == GET_LL)
*((longlong*) result_pos)= getopt_ll(argument, optp, &err);
else if (optp->var_type == GET_STR)
*((char**) result_pos)= argument;
if (err)
return ERR_UNKNOWN_SUFFIX;
}
else
get_one_option(optp->id, optp, argument); get_one_option(optp->id, optp, argument);
(*argc)--; // option handled (shortorlong), decrease argument count (*argc)--; // option handled (shortorlong), decrease argument count
} }
else // non-option found else // non-option found
(*argv)[argvpos++] = cur_arg; (*argv)[argvpos++]= cur_arg;
} }
return 0; return 0;
} }
/* function: findopt
/*
function: findopt
Arguments: opt_pattern, length of opt_pattern, opt_struct, first found Arguments: opt_pattern, length of opt_pattern, opt_struct, first found
name (ffname) name (ffname)
...@@ -297,13 +340,13 @@ static int findopt (char *optpat, uint length, ...@@ -297,13 +340,13 @@ static int findopt (char *optpat, uint length,
int count; int count;
struct my_option *opt= (struct my_option *) *opt_res; struct my_option *opt= (struct my_option *) *opt_res;
for (count = 0; opt->id; opt++) for (count= 0; opt->id; opt++)
{ {
if (!strncmp(opt->name, optpat, length)) // match found if (!compare_strings(opt->name, optpat, length)) // match found
{ {
(*opt_res) = opt; (*opt_res)= opt;
if (!count) if (!count)
*ffname = (char *) opt->name; // we only need to know one prev *ffname= (char *) opt->name; // we only need to know one prev
if (length == strlen(opt->name)) // exact match if (length == strlen(opt->name)) // exact match
return 1; return 1;
count++; count++;
...@@ -311,3 +354,84 @@ static int findopt (char *optpat, uint length, ...@@ -311,3 +354,84 @@ static int findopt (char *optpat, uint length,
} }
return count; return count;
} }
/*
function: compare_strings
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)
{
char const *end= s + length;
for (;s != end ; s++, t++)
{
if ((*s != '-' ? *s : '_') != (*t != '-' ? *t : '_'))
return 1;
}
return 0;
}
/*
function: getopt_ll
Evaluates and returns the value that user gave as an argument
to a variable. Recognizes (case insensitive) K as KILO, M as MEGA
and G as GIGA bytes. Some values must be in certain blocks, as
defined in the given my_option struct, this function will check
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;
longlong num;
*err= 0;
num= strtoll(arg, &endchar, 10);
if (*endchar == 'k' || *endchar == 'K')
num*= 1024L;
else if (*endchar == 'm' || *endchar == 'M')
num*= 1024L * 1024L;
else if (*endchar == 'g' || *endchar == 'G')
num*= 1024L * 1024L * 1024L;
else if (*endchar)
{
fprintf(stderr,
"Unknown suffix '%c' used for variable '%s' (value '%s')\n",
*endchar, optp->name, arg);
*err= 1;
}
if (num < (longlong) optp->min_value)
num= (longlong) optp->min_value;
else if (num > 0 && (ulonglong) num > (ulonglong) (ulong) optp->max_value)
num= (longlong) (ulong) optp->max_value;
num= ((num - (longlong) optp->sub_size) / (ulonglong) optp->block_size);
return (longlong) (num * (ulonglong) optp->block_size);
}
/*
function: init_variables
initialize all variables to their default values
*/
static void init_variables(const struct my_option *options)
{
for ( ; options->name ; options++)
{
if (options->opt_is_var)
{
if (options->var_type == GET_LONG)
*((long*) options->u_max_value)= *((long*) options->value)=
options->def_value;
else if (options->var_type == GET_LL)
*((longlong*) options->u_max_value)= *((longlong*) options->value)=
options->def_value;
}
}
}
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