aboutsummaryrefslogtreecommitdiff
path: root/dep/mysqllite/mysys/my_getopt.c
diff options
context:
space:
mode:
Diffstat (limited to 'dep/mysqllite/mysys/my_getopt.c')
-rw-r--r--dep/mysqllite/mysys/my_getopt.c620
1 files changed, 376 insertions, 244 deletions
diff --git a/dep/mysqllite/mysys/my_getopt.c b/dep/mysqllite/mysys/my_getopt.c
index b0e7175d0b9..51c45ff1309 100644
--- a/dep/mysqllite/mysys/my_getopt.c
+++ b/dep/mysqllite/mysys/my_getopt.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002-2006 MySQL AB
+/* Copyright (C) 2002-2006 MySQL AB, 2008-2009 Sun Microsystems, Inc
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -28,24 +28,15 @@ typedef void (*init_func_p)(const struct my_option *option, void *variable,
static void default_reporter(enum loglevel level, const char *format, ...);
my_error_reporter my_getopt_error_reporter= &default_reporter;
-static int findopt(char *optpat, uint length,
- const struct my_option **opt_res,
- const char **ffname);
-my_bool getopt_compare_strings(const char *s,
- const char *t,
- uint length);
+static int findopt(char *, uint, const struct my_option **, const char **);
+my_bool getopt_compare_strings(const char *, const char *, uint);
static longlong getopt_ll(char *arg, const struct my_option *optp, int *err);
-static ulonglong getopt_ull(char *arg, const struct my_option *optp,
- int *err);
+static ulonglong getopt_ull(char *, const struct my_option *, int *);
static double getopt_double(char *arg, const struct my_option *optp, int *err);
-static void init_variables(const struct my_option *options,
- init_func_p init_one_value);
-static void init_one_value(const struct my_option *option, void *variable,
- longlong value);
-static void fini_one_value(const struct my_option *option, void *variable,
- longlong value);
-static int setval(const struct my_option *opts, void *value, char *argument,
- my_bool set_maximum_value);
+static void init_variables(const struct my_option *, init_func_p);
+static void init_one_value(const struct my_option *, void *, longlong);
+static void fini_one_value(const struct my_option *, void *, longlong);
+static int setval(const struct my_option *, void *, char *, my_bool);
static char *check_struct_option(char *cur_arg, char *key_name);
/*
@@ -60,6 +51,7 @@ enum enum_special_opt
{ OPT_SKIP, OPT_DISABLE, OPT_ENABLE, OPT_MAXIMUM, OPT_LOOSE};
char *disabled_my_option= (char*) "0";
+char *enabled_my_option= (char*) "1";
/*
This is a flag that can be set in client programs. 0 means that
@@ -91,16 +83,6 @@ static void default_reporter(enum loglevel level,
fflush(stderr);
}
-/*
- function: handle_options
-
- Sort options; put options first, until special end of options (--), or
- 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
- or unknown option. Check that option was given an argument if it requires
- one. Call function 'get_one_option()' once for each option.
-*/
-
static my_getopt_value getopt_get_addr;
void my_getopt_register_get_addr(my_getopt_value func_addr)
@@ -108,11 +90,70 @@ void my_getopt_register_get_addr(my_getopt_value func_addr)
getopt_get_addr= func_addr;
}
+/**
+ Handle command line options.
+ Sort options.
+ Put options first, until special end of options (--),
+ or until the end of argv. Parse options, check that the given option
+ matches with one of the options in struct 'my_option'.
+ Check that option was given an argument if it requires one
+ Call the optional 'get_one_option()' function once for each option.
+
+ Note that handle_options() can be invoked multiple times to
+ parse a command line in several steps.
+ In this case, use the global flag @c my_getopt_skip_unknown to indicate
+ that options unknown in the current step should be preserved in the
+ command line for later parsing in subsequent steps.
+
+ For 'long' options (--a_long_option), @c my_getopt_skip_unknown is
+ fully supported. Command line parameters such as:
+ - "--a_long_option"
+ - "--a_long_option=value"
+ - "--a_long_option value"
+ will be preserved as is when the option is not known.
+
+ For 'short' options (-S), support for @c my_getopt_skip_unknown
+ comes with some limitation, because several short options
+ can also be specified together in the same command line argument,
+ as in "-XYZ".
+
+ The first use case supported is: all short options are declared.
+ handle_options() will be able to interpret "-XYZ" as one of:
+ - an unknown X option
+ - "-X -Y -Z", three short options with no arguments
+ - "-X -YZ", where Y is a short option with argument Z
+ - "-XYZ", where X is a short option with argument YZ
+ based on the full short options specifications.
+
+ The second use case supported is: no short option is declared.
+ handle_options() will reject "-XYZ" as unknown, to be parsed later.
+
+ The use case that is explicitly not supported is to provide
+ only a partial list of short options to handle_options().
+ This function can not be expected to extract some option Y
+ in the middle of the string "-XYZ" in these conditions,
+ without knowing if X will be declared an option later.
+
+ Note that this limitation only impacts parsing of several
+ short options from the same command line argument,
+ as in "mysqld -anW5".
+ When each short option is properly separated out in the command line
+ argument, for example in "mysqld -a -n -w5", the code would actually
+ work even with partial options specs given at each stage.
+
+ @param [in, out] argc command line options (count)
+ @param [in, out] argv command line options (values)
+ @param [in] longopts descriptor of all valid options
+ @param [in] get_one_option optional callback function to process each option,
+ can be NULL.
+ @return error in case of ambiguous or unknown options,
+ 0 on success.
+*/
int handle_options(int *argc, char ***argv,
const struct my_option *longopts,
my_get_one_option get_one_option)
{
- uint opt_found, argvpos= 0, length;
+ uint UNINIT_VAR(opt_found), argvpos= 0, length;
my_bool end_of_options= 0, must_be_var, set_maximum_value,
option_is_loose;
char **pos, **pos_end, *optend, *opt_str, key_name[FN_REFLEN];
@@ -120,8 +161,8 @@ int handle_options(int *argc, char ***argv,
const struct my_option *optp;
void *value;
int error, i;
+ my_bool is_cmdline_arg= 1;
- LINT_INIT(opt_found);
/* handle_options() assumes arg0 (program name) always exists */
DBUG_ASSERT(argc && *argc >= 1);
DBUG_ASSERT(argv && *argv);
@@ -129,10 +170,35 @@ int handle_options(int *argc, char ***argv,
(*argv)++; /* --- || ---- */
init_variables(longopts, init_one_value);
+ /*
+ Search for args_separator, if found, then the first part of the
+ arguments are loaded from configs
+ */
+ for (pos= *argv, pos_end=pos+ *argc; pos != pos_end ; pos++)
+ {
+ if (*pos == args_separator)
+ {
+ is_cmdline_arg= 0;
+ break;
+ }
+ }
+
for (pos= *argv, pos_end=pos+ *argc; pos != pos_end ; pos++)
{
char **first= pos;
char *cur_arg= *pos;
+ opt_found= 0;
+ if (!is_cmdline_arg && (cur_arg == args_separator))
+ {
+ is_cmdline_arg= 1;
+
+ /* save the separator too if skip unkown options */
+ if (my_getopt_skip_unknown)
+ (*argv)[argvpos++]= cur_arg;
+ else
+ (*argc)--;
+ continue;
+ }
if (cur_arg[0] == '-' && cur_arg[1] && !end_of_options) /* must be opt */
{
char *argument= 0;
@@ -141,78 +207,15 @@ int handle_options(int *argc, char ***argv,
option_is_loose= 0;
cur_arg++; /* skip '-' */
- if (*cur_arg == '-' || *cur_arg == 'O') /* check for long option, */
- { /* --set-variable, or -O */
- if (*cur_arg == 'O')
- {
- my_getopt_error_reporter(WARNING_LEVEL,
- "%s: Option '-O' is deprecated. "
- "Use --variable-name=value instead.",
- my_progname);
- must_be_var= 1;
-
- if (!(*++cur_arg)) /* If not -Ovar=# */
- {
- /* the argument must be in next argv */
- if (!*++pos)
- {
- if (my_getopt_print_errors)
- my_getopt_error_reporter(ERROR_LEVEL,
- "%s: Option '-O' requires an argument",
- my_progname);
- return EXIT_ARGUMENT_REQUIRED;
- }
- cur_arg= *pos;
- (*argc)--;
- }
- }
- else if (!getopt_compare_strings(cur_arg, "-set-variable", 13))
- {
- my_getopt_error_reporter(WARNING_LEVEL,
- "%s: Option '--set-variable' is deprecated. "
- "Use --variable-name=value instead.",
- my_progname);
-
- must_be_var= 1;
- if (cur_arg[13] == '=')
- {
- cur_arg+= 14;
- if (!*cur_arg)
- {
- if (my_getopt_print_errors)
- my_getopt_error_reporter(ERROR_LEVEL,
- "%s: Option '--set-variable' requires an argument",
- my_progname);
- return EXIT_ARGUMENT_REQUIRED;
- }
- }
- 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)
- {
- if (my_getopt_print_errors)
- my_getopt_error_reporter(ERROR_LEVEL,
- "%s: Option '--set-variable' requires an argument",
- my_progname);
- return EXIT_ARGUMENT_REQUIRED;
- }
- cur_arg= *pos;
- (*argc)--;
- }
- }
- else if (!must_be_var)
- {
- if (!*++cur_arg) /* skip the double dash */
- {
- /* '--' means end of options, look no further */
- end_of_options= 1;
- (*argc)--;
- continue;
- }
- }
+ if (*cur_arg == '-') /* check for long option, */
+ {
+ if (!*++cur_arg) /* skip the double dash */
+ {
+ /* '--' means end of options, look no further */
+ end_of_options= 1;
+ (*argc)--;
+ continue;
+ }
opt_str= check_struct_option(cur_arg, key_name);
optend= strcend(opt_str, '=');
length= (uint) (optend - opt_str);
@@ -258,7 +261,7 @@ int handle_options(int *argc, char ***argv,
my_getopt_error_reporter(ERROR_LEVEL,
"%s: ambiguous option '--%s-%s' (--%s-%s)",
my_progname, special_opt_prefix[i],
- cur_arg, special_opt_prefix[i],
+ opt_str, special_opt_prefix[i],
prev_found);
return EXIT_AMBIGUOUS_OPTION;
}
@@ -270,11 +273,11 @@ int handle_options(int *argc, char ***argv,
for example: --skip-option=0 -> option = TRUE
*/
optend= (optend && *optend == '0' && !(*(optend + 1))) ?
- (char*) "1" : disabled_my_option;
+ enabled_my_option : disabled_my_option;
break;
case OPT_ENABLE:
optend= (optend && *optend == '0' && !(*(optend + 1))) ?
- disabled_my_option : (char*) "1";
+ disabled_my_option : enabled_my_option;
break;
case OPT_MAXIMUM:
set_maximum_value= 1;
@@ -291,12 +294,7 @@ int handle_options(int *argc, char ***argv,
{
if (my_getopt_skip_unknown)
{
- /*
- preserve all the components of this unknown option, this may
- occurr when the user provides options like: "-O foo" or
- "--set-variable foo" (note that theres a space in there)
- Generally, these kind of options are to be avoided
- */
+ /* Preserve all the components of this unknown option. */
do {
(*argv)[argvpos++]= *first++;
} while (first <= pos);
@@ -362,14 +360,6 @@ int handle_options(int *argc, char ***argv,
}
return EXIT_OPTION_DISABLED;
}
- if (must_be_var && (optp->var_type & GET_TYPE_MASK) == GET_NO_ARG)
- {
- if (my_getopt_print_errors)
- my_getopt_error_reporter(ERROR_LEVEL,
- "%s: option '%s' cannot take an argument",
- my_progname, optp->name);
- return EXIT_NO_ARGUMENT_ALLOWED;
- }
error= 0;
value= optp->var_type & GET_ASK_ADDR ?
(*getopt_get_addr)(key_name, (uint) strlen(key_name), optp, &error) :
@@ -379,6 +369,11 @@ int handle_options(int *argc, char ***argv,
if (optp->arg_type == NO_ARG)
{
+ /*
+ Due to historical reasons GET_BOOL var_types still accepts arguments
+ despite the NO_ARG arg_type attribute. This can seems a bit unintuitive
+ and care should be taken when refactoring this code.
+ */
if (optend && (optp->var_type & GET_TYPE_MASK) != GET_BOOL)
{
if (my_getopt_print_errors)
@@ -393,7 +388,7 @@ int handle_options(int *argc, char ***argv,
Set bool to 1 if no argument or if the user has used
--enable-'option-name'.
*optend was set to '0' if one used --disable-option
- */
+ */
(*argc)--;
if (!optend || *optend == '1' ||
!my_strcasecmp(&my_charset_latin1, optend, "true"))
@@ -404,37 +399,26 @@ int handle_options(int *argc, char ***argv,
else
{
my_getopt_error_reporter(WARNING_LEVEL,
- "%s: ignoring option '--%s' due to "
- "invalid value '%s'",
+ "%s: ignoring option '--%s' "
+ "due to invalid value '%s'",
my_progname, optp->name, optend);
continue;
}
- if (get_one_option(optp->id, optp,
+ if (get_one_option && get_one_option(optp->id, optp,
*((my_bool*) value) ?
- (char*) "1" : disabled_my_option))
+ enabled_my_option : disabled_my_option))
return EXIT_ARGUMENT_INVALID;
continue;
}
argument= optend;
}
- else if (optp->arg_type == OPT_ARG &&
- (((optp->var_type & GET_TYPE_MASK) == GET_BOOL) ||
- (optp->var_type & GET_TYPE_MASK) == GET_ENUM))
- {
- if (optend == disabled_my_option)
- init_one_value(optp, value, 0);
- else
- {
- if (!optend) /* No argument -> enable option */
- init_one_value(optp, value, 1);
- else
- argument= optend;
- }
- }
else if (optp->arg_type == REQUIRED_ARG && !optend)
{
- /* Check if there are more arguments after this one */
- if (!*++pos)
+ /* Check if there are more arguments after this one,
+ Note: options loaded from config file that requires value
+ should always be in the form '--option=value'.
+ */
+ if (!is_cmdline_arg || !*++pos)
{
if (my_getopt_print_errors)
my_getopt_error_reporter(ERROR_LEVEL,
@@ -453,9 +437,9 @@ int handle_options(int *argc, char ***argv,
for (optend= cur_arg; *optend; optend++)
{
opt_found= 0;
- for (optp= longopts; optp->id; optp++)
+ for (optp= longopts; optp->name; optp++)
{
- if (optp->id == (int) (uchar) *optend)
+ if (optp->id && optp->id == (int) (uchar) *optend)
{
/* Option recognized. Find next what to do with it */
opt_found= 1;
@@ -471,7 +455,7 @@ int handle_options(int *argc, char ***argv,
optp->arg_type == NO_ARG)
{
*((my_bool*) optp->value)= (my_bool) 1;
- if (get_one_option(optp->id, optp, argument))
+ if (get_one_option && get_one_option(optp->id, optp, argument))
return EXIT_UNSPECIFIED_ERROR;
continue;
}
@@ -491,7 +475,7 @@ int handle_options(int *argc, char ***argv,
{
if (optp->var_type == GET_BOOL)
*((my_bool*) optp->value)= (my_bool) 1;
- if (get_one_option(optp->id, optp, argument))
+ if (get_one_option && get_one_option(optp->id, optp, argument))
return EXIT_UNSPECIFIED_ERROR;
continue;
}
@@ -511,40 +495,56 @@ int handle_options(int *argc, char ***argv,
}
if ((error= setval(optp, optp->value, argument,
set_maximum_value)))
- {
- my_getopt_error_reporter(ERROR_LEVEL,
- "%s: Error while setting value '%s' to '%s'",
- my_progname, argument, optp->name);
return error;
- }
- if (get_one_option(optp->id, optp, argument))
+ if (get_one_option && get_one_option(optp->id, optp, argument))
return EXIT_UNSPECIFIED_ERROR;
break;
}
}
if (!opt_found)
{
- if (my_getopt_print_errors)
- my_getopt_error_reporter(ERROR_LEVEL,
- "%s: unknown option '-%c'",
- my_progname, *optend);
- return EXIT_UNKNOWN_OPTION;
+ if (my_getopt_skip_unknown)
+ {
+ /*
+ We are currently parsing a single argv[] argument
+ of the form "-XYZ".
+ One or the argument found (say Y) is not an option.
+ Hack the string "-XYZ" to make a "-YZ" substring in it,
+ and push that to the output as an unrecognized parameter.
+ */
+ DBUG_ASSERT(optend > *pos);
+ DBUG_ASSERT(optend >= cur_arg);
+ DBUG_ASSERT(optend <= *pos + strlen(*pos));
+ DBUG_ASSERT(*optend);
+ optend--;
+ optend[0]= '-'; /* replace 'X' or '-' by '-' */
+ (*argv)[argvpos++]= optend;
+ /*
+ Do not continue to parse at the current "-XYZ" argument,
+ skip to the next argv[] argument instead.
+ */
+ optend= (char*) " ";
+ }
+ else
+ {
+ if (my_getopt_print_errors)
+ my_getopt_error_reporter(ERROR_LEVEL,
+ "%s: unknown option '-%c'",
+ my_progname, *optend);
+ return EXIT_UNKNOWN_OPTION;
+ }
}
}
- (*argc)--; /* option handled (short), decrease argument count */
+ if (opt_found)
+ (*argc)--; /* option handled (short), decrease argument count */
continue;
}
if ((error= setval(optp, value, argument, set_maximum_value)))
- {
- my_getopt_error_reporter(ERROR_LEVEL,
- "%s: Error while setting value '%s' to '%s'",
- my_progname, argument, optp->name);
return error;
- }
- if (get_one_option(optp->id, optp, argument))
+ if (get_one_option && get_one_option(optp->id, optp, argument))
return EXIT_UNSPECIFIED_ERROR;
- (*argc)--; /* option handled (short or long), decrease argument count */
+ (*argc)--; /* option handled (long), decrease argument count */
}
else /* non-option found */
(*argv)[argvpos++]= cur_arg;
@@ -602,6 +602,24 @@ static char *check_struct_option(char *cur_arg, char *key_name)
}
}
+/**
+ Parse a boolean command line argument
+
+ "ON", "TRUE" and "1" will return true,
+ other values will return false.
+
+ @param[in] argument The value argument
+ @return boolean value
+*/
+static my_bool get_bool_argument(const char *argument)
+{
+ if (!my_strcasecmp(&my_charset_latin1, argument, "true") ||
+ !my_strcasecmp(&my_charset_latin1, argument, "on"))
+ return 1;
+ else
+ return (my_bool) atoi(argument);
+}
+
/*
function: setval
@@ -612,75 +630,132 @@ static char *check_struct_option(char *cur_arg, char *key_name)
static int setval(const struct my_option *opts, void *value, char *argument,
my_bool set_maximum_value)
{
- int err= 0;
+ int err= 0, res= 0;
- if (value && argument)
- {
- void *result_pos= ((set_maximum_value) ? opts->u_max_value : value);
+ if (!argument)
+ argument= enabled_my_option;
- if (!result_pos)
+ if (value)
+ {
+ if (set_maximum_value && !(value= opts->u_max_value))
+ {
+ my_getopt_error_reporter(ERROR_LEVEL,
+ "%s: Maximum value of '%s' cannot be set",
+ my_progname, opts->name);
return EXIT_NO_PTR_TO_VARIABLE;
+ }
switch ((opts->var_type & GET_TYPE_MASK)) {
case GET_BOOL: /* If argument differs from 0, enable option, else disable */
- *((my_bool*) result_pos)= (my_bool) atoi(argument) != 0;
+ *((my_bool*) value)= get_bool_argument(argument);
break;
case GET_INT:
- *((int*) result_pos)= (int) getopt_ll(argument, opts, &err);
+ *((int*) value)= (int) getopt_ll(argument, opts, &err);
break;
case GET_UINT:
- *((uint*) result_pos)= (uint) getopt_ull(argument, opts, &err);
+ *((uint*) value)= (uint) getopt_ull(argument, opts, &err);
break;
case GET_LONG:
- *((long*) result_pos)= (long) getopt_ll(argument, opts, &err);
+ *((long*) value)= (long) getopt_ll(argument, opts, &err);
break;
case GET_ULONG:
- *((long*) result_pos)= (long) getopt_ull(argument, opts, &err);
+ *((long*) value)= (long) getopt_ull(argument, opts, &err);
break;
case GET_LL:
- *((longlong*) result_pos)= getopt_ll(argument, opts, &err);
+ *((longlong*) value)= getopt_ll(argument, opts, &err);
break;
case GET_ULL:
- *((ulonglong*) result_pos)= getopt_ull(argument, opts, &err);
+ *((ulonglong*) value)= getopt_ull(argument, opts, &err);
break;
case GET_DOUBLE:
- *((double*) result_pos)= getopt_double(argument, opts, &err);
+ *((double*) value)= getopt_double(argument, opts, &err);
break;
case GET_STR:
- *((char**) result_pos)= argument;
+ if (argument == enabled_my_option)
+ break; /* string options don't use this default of "1" */
+ *((char**) value)= argument;
break;
case GET_STR_ALLOC:
- if ((*((char**) result_pos)))
- my_free((*(char**) result_pos), MYF(MY_WME | MY_FAE));
- if (!(*((char**) result_pos)= my_strdup(argument, MYF(MY_WME))))
- return EXIT_OUT_OF_MEMORY;
+ if (argument == enabled_my_option)
+ break; /* string options don't use this default of "1" */
+ my_free(*((char**) value));
+ if (!(*((char**) value)= my_strdup(argument, MYF(MY_WME))))
+ {
+ res= EXIT_OUT_OF_MEMORY;
+ goto ret;
+ };
break;
case GET_ENUM:
- if (((*(int*)result_pos)=
- find_type(argument, opts->typelib, 2) - 1) < 0)
{
- /*
- Accept an integer representation of the enumerated item.
- */
- char *endptr;
- unsigned int arg= (unsigned int) strtol(argument, &endptr, 10);
- if (*endptr || arg >= opts->typelib->count)
- return EXIT_ARGUMENT_INVALID;
- *(int*)result_pos= arg;
+ int type= find_type(argument, opts->typelib, 2);
+ if (type == 0)
+ {
+ /*
+ Accept an integer representation of the enumerated item.
+ */
+ char *endptr;
+ ulong arg= strtoul(argument, &endptr, 10);
+ if (*endptr || arg >= opts->typelib->count)
+ {
+ res= EXIT_ARGUMENT_INVALID;
+ goto ret;
+ }
+ *(ulong*)value= arg;
+ }
+ else
+ *(ulong*)value= type - 1;
}
break;
case GET_SET:
- *((ulonglong*)result_pos)= find_typeset(argument, opts->typelib, &err);
+ *((ulonglong*)value)= find_typeset(argument, opts->typelib, &err);
if (err)
- return EXIT_ARGUMENT_INVALID;
+ {
+ /* Accept an integer representation of the set */
+ char *endptr;
+ ulonglong arg= (ulonglong) strtol(argument, &endptr, 10);
+ if (*endptr || (arg >> 1) >= (1ULL << (opts->typelib->count-1)))
+ {
+ res= EXIT_ARGUMENT_INVALID;
+ goto ret;
+ };
+ *(ulonglong*)value= arg;
+ err= 0;
+ }
break;
- default: /* dummy default to avoid compiler warnings */
+ case GET_FLAGSET:
+ {
+ char *error;
+ uint error_len;
+
+ *((ulonglong*)value)=
+ find_set_from_flags(opts->typelib, opts->typelib->count,
+ *(ulonglong *)value, opts->def_value,
+ argument, strlen(argument),
+ &error, &error_len);
+ if (error)
+ {
+ res= EXIT_ARGUMENT_INVALID;
+ goto ret;
+ };
+ }
+ break;
+ case GET_NO_ARG: /* get_one_option has taken care of the value already */
+ default: /* dummy default to avoid compiler warnings */
break;
}
if (err)
- return EXIT_UNKNOWN_SUFFIX;
+ {
+ res= EXIT_UNKNOWN_SUFFIX;
+ goto ret;
+ };
}
return 0;
+
+ret:
+ my_getopt_error_reporter(ERROR_LEVEL,
+ "%s: Error while setting value '%s' to '%s'",
+ my_progname, argument, opts->name);
+ return res;
}
@@ -859,7 +934,7 @@ longlong getopt_ll_limit_value(longlong num, const struct my_option *optp,
break;
}
- num= ((num - optp->sub_size) / block_size);
+ num= (num / block_size);
num= (longlong) (num * block_size);
if (num < optp->min_value)
@@ -870,7 +945,7 @@ longlong getopt_ll_limit_value(longlong num, const struct my_option *optp,
}
if (fix)
- *fix= adjusted;
+ *fix= old != num;
else if (adjusted)
my_getopt_error_reporter(WARNING_LEVEL,
"option '%s': signed value %s adjusted to %s",
@@ -942,7 +1017,7 @@ ulonglong getopt_ull_limit_value(ulonglong num, const struct my_option *optp,
}
if (fix)
- *fix= adjusted;
+ *fix= old != num;
else if (adjusted)
my_getopt_error_reporter(WARNING_LEVEL,
"option '%s': unsigned value %s adjusted to %s",
@@ -951,6 +1026,29 @@ ulonglong getopt_ull_limit_value(ulonglong num, const struct my_option *optp,
return num;
}
+double getopt_double_limit_value(double num, const struct my_option *optp,
+ my_bool *fix)
+{
+ my_bool adjusted= FALSE;
+ double old= num;
+ if (optp->max_value && num > (double) optp->max_value)
+ {
+ num= (double) optp->max_value;
+ adjusted= TRUE;
+ }
+ if (num < (double) optp->min_value)
+ {
+ num= (double) optp->min_value;
+ adjusted= TRUE;
+ }
+ if (fix)
+ *fix= adjusted;
+ else if (adjusted)
+ my_getopt_error_reporter(WARNING_LEVEL,
+ "option '%s': value %g adjusted to %g",
+ optp->name, old, num);
+ return num;
+}
/*
Get double value withing ranges
@@ -972,15 +1070,12 @@ static double getopt_double(char *arg, const struct my_option *optp, int *err)
num= my_strtod(arg, &end, &error);
if (end[0] != 0 || error)
{
- fprintf(stderr,
- "%s: ERROR: Invalid decimal value for option '%s'\n",
- my_progname, optp->name);
+ my_getopt_error_reporter(ERROR_LEVEL,
+ "Invalid decimal value for option '%s'\n", optp->name);
*err= EXIT_ARGUMENT_INVALID;
return 0.0;
}
- if (optp->max_value && num > (double) optp->max_value)
- num= (double) optp->max_value;
- return max(num, (double) optp->min_value);
+ return getopt_double_limit_value(num, optp, NULL);
}
/*
@@ -1004,7 +1099,7 @@ static void init_one_value(const struct my_option *option, void *variable,
*((int*) variable)= (int) getopt_ll_limit_value((int) value, option, NULL);
break;
case GET_ENUM:
- *((uint*) variable)= (uint) value;
+ *((ulong*) variable)= (ulong) value;
break;
case GET_UINT:
*((uint*) variable)= (uint) getopt_ull_limit_value((uint) value, option, NULL);
@@ -1022,10 +1117,11 @@ static void init_one_value(const struct my_option *option, void *variable,
*((ulonglong*) variable)= (ulonglong) getopt_ull_limit_value((ulonglong) value, option, NULL);
break;
case GET_SET:
+ case GET_FLAGSET:
*((ulonglong*) variable)= (ulonglong) value;
break;
case GET_DOUBLE:
- *((double*) variable)= (double) value;
+ *((double*) variable)= ulonglong2double(value);
break;
case GET_STR:
/*
@@ -1046,8 +1142,9 @@ static void init_one_value(const struct my_option *option, void *variable,
*/
if ((char*) (intptr) value)
{
- my_free((*(char**) variable), MYF(MY_ALLOW_ZERO_PTR));
- *((char**) variable)= my_strdup((char*) (intptr) value, MYF(MY_WME));
+ char **pstr= (char **) variable;
+ my_free(*pstr);
+ *pstr= my_strdup((char*) (intptr) value, MYF(MY_WME));
}
break;
default: /* dummy default to avoid compiler warnings */
@@ -1072,7 +1169,7 @@ static void fini_one_value(const struct my_option *option, void *variable,
DBUG_ENTER("fini_one_value");
switch ((option->var_type & GET_TYPE_MASK)) {
case GET_STR_ALLOC:
- my_free((*(char**) variable), MYF(MY_ALLOW_ZERO_PTR));
+ my_free(*((char**) variable));
*((char**) variable)= NULL;
break;
default: /* dummy default to avoid compiler warnings */
@@ -1097,7 +1194,7 @@ void my_cleanup_options(const struct my_option *options)
NOTES
We will initialize the value that is pointed to by options->value.
- If the value is of type GET_ASK_ADDR, we will also ask for the address
+ If the value is of type GET_ASK_ADDR, we will ask for the address
for a value and initialize.
*/
@@ -1107,7 +1204,7 @@ static void init_variables(const struct my_option *options,
DBUG_ENTER("init_variables");
for (; options->name; options++)
{
- void *variable;
+ void *value;
DBUG_PRINT("options", ("name: '%s'", options->name));
/*
We must set u_max_value first as for some variables
@@ -1116,15 +1213,22 @@ static void init_variables(const struct my_option *options,
*/
if (options->u_max_value)
init_one_value(options, options->u_max_value, options->max_value);
- if (options->value)
- init_one_value(options, options->value, options->def_value);
- if (options->var_type & GET_ASK_ADDR &&
- (variable= (*getopt_get_addr)("", 0, options, 0)))
- init_one_value(options, variable, options->def_value);
+ value= (options->var_type & GET_ASK_ADDR ?
+ (*getopt_get_addr)("", 0, options, 0) : options->value);
+ if (value)
+ init_one_value(options, value, options->def_value);
}
DBUG_VOID_RETURN;
}
+/** Prints variable or option name, replacing _ with - */
+static uint print_name(const struct my_option *optp)
+{
+ const char *s= optp->name;
+ for (;*s;s++)
+ putchar(*s == '_' ? '-' : *s);
+ return s - optp->name;
+}
/*
function: my_print_options
@@ -1132,17 +1236,15 @@ static void init_variables(const struct my_option *options,
Print help for all options and variables.
*/
-#include <help_start.h>
-
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++)
+ for (optp= options; optp->name; optp++)
{
- if (optp->id < 256)
+ if (optp->id && optp->id < 256)
{
printf(" -%c%s", optp->id, strlen(optp->name) ? ", " : " ");
col= 6;
@@ -1154,21 +1256,24 @@ void my_print_help(const struct my_option *options)
}
if (strlen(optp->name))
{
- printf("--%s", optp->name);
- col+= 2 + (uint) strlen(optp->name);
- if ((optp->var_type & GET_TYPE_MASK) == GET_STR ||
- (optp->var_type & GET_TYPE_MASK) == GET_STR_ALLOC)
+ printf("--");
+ col+= 2 + print_name(optp);
+ if (optp->arg_type == NO_ARG ||
+ (optp->var_type & GET_TYPE_MASK) == GET_BOOL)
+ {
+ putchar(' ');
+ col++;
+ }
+ else if ((optp->var_type & GET_TYPE_MASK) == GET_STR ||
+ (optp->var_type & GET_TYPE_MASK) == GET_STR_ALLOC ||
+ (optp->var_type & GET_TYPE_MASK) == GET_ENUM ||
+ (optp->var_type & GET_TYPE_MASK) == GET_SET ||
+ (optp->var_type & GET_TYPE_MASK) == GET_FLAGSET )
{
printf("%s=name%s ", optp->arg_type == OPT_ARG ? "[" : "",
optp->arg_type == OPT_ARG ? "]" : "");
col+= (optp->arg_type == OPT_ARG) ? 8 : 6;
}
- else if ((optp->var_type & GET_TYPE_MASK) == GET_NO_ARG ||
- (optp->var_type & GET_TYPE_MASK) == GET_BOOL)
- {
- putchar(' ');
- col++;
- }
else
{
printf("%s=#%s ", optp->arg_type == OPT_ARG ? "[" : "",
@@ -1200,6 +1305,15 @@ void my_print_help(const struct my_option *options)
printf("%s", comment);
}
putchar('\n');
+ if ((optp->var_type & GET_TYPE_MASK) == GET_BOOL)
+ {
+ if (optp->def_value != 0)
+ {
+ printf("%*s(Defaults to on; use --skip-", name_space, "");
+ print_name(optp);
+ printf(" to disable.)\n");
+ }
+ }
}
}
@@ -1213,38 +1327,55 @@ void my_print_help(const struct my_option *options)
void my_print_variables(const struct my_option *options)
{
uint name_space= 34, length, nr;
- ulonglong bit, llvalue;
+ ulonglong llvalue;
char buff[255];
const struct my_option *optp;
+ for (optp= options; optp->name; optp++)
+ {
+ length= strlen(optp->name)+1;
+ if (length > name_space)
+ name_space= length;
+ }
+
printf("\nVariables (--variable-name=value)\n");
- printf("and boolean options {FALSE|TRUE} Value (after reading options)\n");
- printf("--------------------------------- -----------------------------\n");
- for (optp= options; optp->id; optp++)
+ printf("%-*s%s", name_space, "and boolean options {FALSE|TRUE}",
+ "Value (after reading options)\n");
+ for (length=1; length < 75; length++)
+ putchar(length == name_space ? ' ' : '-');
+ putchar('\n');
+
+ for (optp= options; optp->name; optp++)
{
void *value= (optp->var_type & GET_ASK_ADDR ?
(*getopt_get_addr)("", 0, optp, 0) : optp->value);
if (value)
{
- printf("%s ", optp->name);
- length= (uint) strlen(optp->name)+1;
+ length= print_name(optp);
for (; length < name_space; length++)
putchar(' ');
switch ((optp->var_type & GET_TYPE_MASK)) {
case GET_SET:
if (!(llvalue= *(ulonglong*) value))
- printf("%s\n", "(No default value)");
+ printf("%s\n", "");
else
- for (nr= 0, bit= 1; llvalue && nr < optp->typelib->count; nr++, bit<<=1)
+ for (nr= 0; llvalue && nr < optp->typelib->count; nr++, llvalue >>=1)
{
- if (!(bit & llvalue))
- continue;
- llvalue&= ~bit;
- printf( llvalue ? "%s," : "%s\n", get_type(optp->typelib, nr));
+ if (llvalue & 1)
+ printf( llvalue > 1 ? "%s," : "%s\n", get_type(optp->typelib, nr));
}
break;
+ case GET_FLAGSET:
+ llvalue= *(ulonglong*) value;
+ for (nr= 0; llvalue && nr < optp->typelib->count; nr++, llvalue >>=1)
+ {
+ printf("%s%s=", (nr ? "," : ""), get_type(optp->typelib, nr));
+ printf(llvalue & 1 ? "on" : "off");
+ }
+ printf("\n");
+ break;
case GET_ENUM:
- printf("%s\n", get_type(optp->typelib, *(uint*) value));
+ printf("%s\n", get_type(optp->typelib, *(ulong*) value));
break;
case GET_STR:
case GET_STR_ALLOC: /* fall through */
@@ -1276,6 +1407,9 @@ void my_print_variables(const struct my_option *options)
case GET_DOUBLE:
printf("%g\n", *(double*) value);
break;
+ case GET_NO_ARG:
+ printf("(No default value)\n");
+ break;
default:
printf("(Disabled)\n");
break;
@@ -1283,5 +1417,3 @@ void my_print_variables(const struct my_option *options)
}
}
}
-
-#include <help_end.h>