summaryrefslogtreecommitdiff
path: root/mysql/mysys_ssl/my_getopt.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'mysql/mysys_ssl/my_getopt.cpp')
-rw-r--r--mysql/mysys_ssl/my_getopt.cpp1615
1 files changed, 0 insertions, 1615 deletions
diff --git a/mysql/mysys_ssl/my_getopt.cpp b/mysql/mysys_ssl/my_getopt.cpp
deleted file mode 100644
index 40ae171..0000000
--- a/mysql/mysys_ssl/my_getopt.cpp
+++ /dev/null
@@ -1,1615 +0,0 @@
-/* Copyright (c) 2002, 2016, Oracle and/or its affiliates. All rights reserved.
-
- 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
- the Free Software Foundation; version 2 of the License.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software Foundation,
- 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
-
-#include <my_global.h>
-#include <m_string.h>
-#include <stdlib.h>
-#include <mysys_err.h>
-#include <my_getopt.h>
-#include <errno.h>
-#include <m_string.h>
-#include "my_default.h"
-#include <m_ctype.h>
-#include "../mysys/mysys_priv.h"
-
-typedef void (*init_func_p)(const struct my_option *option, void *variable,
- longlong value);
-
-my_error_reporter my_getopt_error_reporter= &my_message_local;
-
-static bool findopt(char *, uint, const struct my_option **);
-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 *, 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 *, 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);
-static my_bool get_bool_argument(const struct my_option *opts,
- const char *argument,
- bool *error);
-
-/*
- The following three variables belong to same group and the number and
- order of their arguments must correspond to each other.
-*/
-static const char *special_opt_prefix[]=
-{"skip", "disable", "enable", "maximum", "loose", 0};
-static const uint special_opt_prefix_lengths[]=
-{ 4, 7, 6, 7, 5, 0};
-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
- my_getopt will not print error messages, but the client should do
- it by itself
-*/
-
-my_bool my_getopt_print_errors= 1;
-
-/*
- This is a flag that can be set in client programs. 1 means that
- my_getopt will skip over options it does not know how to handle.
-*/
-
-my_bool my_getopt_skip_unknown= 0;
-
-static my_getopt_value getopt_get_addr;
-
-void my_getopt_register_get_addr(my_getopt_value func_addr)
-{
- getopt_get_addr= func_addr;
-}
-
-
-/**
- Wrapper around my_handle_options() for interface compatibility.
-
- @param argc [in, out] Command line options (count)
- @param argv [in, out] Command line options (values)
- @param longopts [in] Descriptor of all valid options
- @param get_one_option [in] 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)
-{
- return my_handle_options(argc, argv, longopts, get_one_option, NULL, FALSE);
-}
-
-union ull_dbl
-{
- ulonglong ull;
- double dbl;
-};
-
-/**
- Returns an ulonglong value containing a raw
- representation of the given double value.
-*/
-ulonglong getopt_double2ulonglong(double v)
-{
- union ull_dbl u;
- u.dbl= v;
- compile_time_assert(sizeof(ulonglong) >= sizeof(double));
- return u.ull;
-}
-
-/**
- Returns the double value which corresponds to
- the given raw representation.
-*/
-double getopt_ulonglong2double(ulonglong v)
-{
- union ull_dbl u;
- u.ull= v;
- return u.dbl;
-}
-
-/**
- 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.
- @param [in] command_list NULL-terminated list of strings (commands) which
- (if set) is looked up for all non-option strings
- found while parsing the command line parameters.
- The parsing terminates if a match is found. At
- exit, argv [out] would contain all the remaining
- unparsed options along with the matched command.
-
- @param [in] ignore_unknown_option When set to TRUE, options are continued to
- be read even when unknown options are
- encountered.
-
- @return error in case of ambiguous or unknown options,
- 0 on success.
-*/
-int my_handle_options(int *argc, char ***argv,
- const struct my_option *longopts,
- my_get_one_option get_one_option,
- const char **command_list, my_bool ignore_unknown_option)
-{
- uint 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];
- const struct my_option *optp;
- void *value;
- int error, i;
- my_bool is_cmdline_arg= 1;
- bool opt_found;
-
- /* handle_options() assumes arg0 (program name) always exists */
- DBUG_ASSERT(argc && *argc >= 1);
- DBUG_ASSERT(argv && *argv);
- (*argc)--; /* Skip the program name */
- (*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 (my_getopt_is_args_separator(*pos))
- {
- 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= false;
- if (!is_cmdline_arg && (my_getopt_is_args_separator(cur_arg)))
- {
- 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;
- must_be_var= 0;
- set_maximum_value= 0;
- option_is_loose= 0;
-
- cur_arg++; /* skip '-' */
- 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);
- if (*optend == '=')
- optend++;
- else
- optend= 0;
-
- /*
- Find first the right option. Return error in case of an ambiguous,
- or unknown option
- */
- optp= longopts;
- if (!(opt_found= findopt(opt_str, length, &optp)))
- {
- /*
- Didn't find any matching option. Let's see if someone called
- option with a special option prefix
- */
- if (!must_be_var)
- {
- if (optend)
- must_be_var= 1; /* option is followed by an argument */
- for (i= 0; special_opt_prefix[i]; i++)
- {
- if (!getopt_compare_strings(special_opt_prefix[i], opt_str,
- special_opt_prefix_lengths[i]) &&
- (opt_str[special_opt_prefix_lengths[i]] == '-' ||
- opt_str[special_opt_prefix_lengths[i]] == '_'))
- {
- /*
- We were called with a special prefix, we can reuse opt_found
- */
- opt_str+= special_opt_prefix_lengths[i] + 1;
- length-= special_opt_prefix_lengths[i] + 1;
- if (i == OPT_LOOSE)
- option_is_loose= 1;
- if ((opt_found= findopt(opt_str, length, &optp)))
- {
- switch (i) {
- case OPT_SKIP:
- case OPT_DISABLE: /* fall through */
- /*
- double negation is actually enable again,
- for example: --skip-option=0 -> option = TRUE
- */
- optend= (optend && *optend == '0' && !(*(optend + 1))) ?
- enabled_my_option : disabled_my_option;
- break;
- case OPT_ENABLE:
- optend= (optend && *optend == '0' && !(*(optend + 1))) ?
- disabled_my_option : enabled_my_option;
- break;
- case OPT_MAXIMUM:
- set_maximum_value= 1;
- must_be_var= 1;
- break;
- }
- break; /* break from the inner loop, main loop continues */
- }
- i= -1; /* restart the loop */
- }
- }
- }
- if (!opt_found)
- {
- if (my_getopt_skip_unknown)
- {
- /* Preserve all the components of this unknown option. */
- do {
- (*argv)[argvpos++]= *first++;
- } while (first <= pos);
- continue;
- }
- if (must_be_var)
- {
- if (my_getopt_print_errors)
- my_getopt_error_reporter(option_is_loose ?
- WARNING_LEVEL : ERROR_LEVEL,
- "unknown variable '%s'", cur_arg);
- if (!option_is_loose)
- return EXIT_UNKNOWN_VARIABLE;
- }
- else
- {
- if (my_getopt_print_errors)
- my_getopt_error_reporter(option_is_loose ?
- WARNING_LEVEL : ERROR_LEVEL,
- "unknown option '--%s'", cur_arg);
- if (!(option_is_loose || ignore_unknown_option))
- return EXIT_UNKNOWN_OPTION;
- }
- if (option_is_loose || ignore_unknown_option)
- {
- (*argc)--;
- continue;
- }
- }
- }
- if ((optp->var_type & GET_TYPE_MASK) == GET_DISABLED)
- {
- if (my_getopt_print_errors)
- my_message_local(option_is_loose ? WARNING_LEVEL : ERROR_LEVEL,
- "%s: Option '%s' used, but is disabled",
- my_progname, opt_str);
- if (option_is_loose)
- {
- (*argc)--;
- continue;
- }
- return EXIT_OPTION_DISABLED;
- }
- error= 0;
- value= optp->var_type & GET_ASK_ADDR ?
- (*getopt_get_addr)(key_name, strlen(key_name), optp, &error) :
- optp->value;
- if (error)
- return error;
-
- 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)
- my_getopt_error_reporter(ERROR_LEVEL,
- "%s: option '--%s' cannot take an argument",
- my_progname, optp->name);
- return EXIT_NO_ARGUMENT_ALLOWED;
- }
- if ((optp->var_type & GET_TYPE_MASK) == GET_BOOL)
- {
- /*
- 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)
- *((my_bool*) value)= (my_bool) 1;
- else
- {
- my_bool ret= 0;
- bool error= 0;
- ret= get_bool_argument(optp, optend, &error);
- if(error)
- {
- my_getopt_error_reporter(WARNING_LEVEL,
- "%s: ignoring option '--%s' "
- "due to invalid value '%s'",
- my_progname, optp->name, optend);
- continue;
- }
- else
- *((my_bool*) value)= ret;
- }
- if (get_one_option && get_one_option(optp->id, optp,
- *((my_bool*) value) ?
- enabled_my_option : disabled_my_option))
- return EXIT_ARGUMENT_INVALID;
- continue;
- }
- argument= optend;
- }
- else if (optp->arg_type == REQUIRED_ARG && !optend)
- {
- /* 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,
- "%s: option '--%s' requires an argument",
- my_progname, optp->name);
- return EXIT_ARGUMENT_REQUIRED;
- }
- argument= *pos;
- (*argc)--;
- }
- else
- argument= optend;
-
- if (optp->var_type == GET_PASSWORD && is_cmdline_arg && argument)
- print_cmdline_password_warning();
- }
- else /* must be short option */
- {
- for (optend= cur_arg; *optend; optend++)
- {
- opt_found= false;
- for (optp= longopts; optp->name; optp++)
- {
- if (optp->id && optp->id == (int) (uchar) *optend)
- {
- /* Option recognized. Find next what to do with it */
- opt_found= true;
- if ((optp->var_type & GET_TYPE_MASK) == GET_DISABLED)
- {
- if (my_getopt_print_errors)
- my_message_local(ERROR_LEVEL,
- "%s: Option '-%c' used, but is disabled",
- my_progname, optp->id);
- return EXIT_OPTION_DISABLED;
- }
- if ((optp->var_type & GET_TYPE_MASK) == GET_BOOL &&
- optp->arg_type == NO_ARG)
- {
- *((my_bool*) optp->value)= (my_bool) 1;
- if (get_one_option && get_one_option(optp->id, optp, argument))
- return EXIT_UNSPECIFIED_ERROR;
- continue;
- }
- else if (optp->arg_type == REQUIRED_ARG ||
- optp->arg_type == OPT_ARG)
- {
- if (*(optend + 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*) " ";
- if (optp->var_type == GET_PASSWORD && is_cmdline_arg)
- print_cmdline_password_warning();
- }
- else
- {
- if (optp->arg_type == OPT_ARG)
- {
- if (optp->var_type == GET_BOOL)
- *((my_bool*) optp->value)= (my_bool) 1;
- if (get_one_option && get_one_option(optp->id, optp, argument))
- return EXIT_UNSPECIFIED_ERROR;
- continue;
- }
- /* Check if there are more arguments after this one */
- if (!pos[1])
- {
- if (my_getopt_print_errors)
- my_getopt_error_reporter(ERROR_LEVEL,
- "%s: option '-%c' requires an argument",
- my_progname, optp->id);
- return EXIT_ARGUMENT_REQUIRED;
- }
- argument= *++pos;
- (*argc)--;
- /* the other loop will break, because *optend + 1 == 0 */
- }
- }
- if ((error= setval(optp, optp->value, argument,
- set_maximum_value)))
- return error;
- if (get_one_option && get_one_option(optp->id, optp, argument))
- return EXIT_UNSPECIFIED_ERROR;
- break;
- }
- }
- if (!opt_found)
- {
- 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;
- }
- }
- }
- if (opt_found)
- (*argc)--; /* option handled (short), decrease argument count */
- continue;
- }
- if ((error= setval(optp, value, argument, set_maximum_value)))
- return error;
- if (get_one_option && get_one_option(optp->id, optp, argument))
- return EXIT_UNSPECIFIED_ERROR;
-
- (*argc)--; /* option handled (long), decrease argument count */
- }
- else /* non-option found */
- {
- if (command_list)
- {
- while (* command_list)
- {
- if (!strcmp(*command_list, cur_arg))
- {
- /* Match found. */
- (*argv)[argvpos ++]= cur_arg;
-
- /* Copy rest of the un-parsed elements & return. */
- while ((++ pos) != pos_end)
- (*argv)[argvpos ++]= *pos;
- goto done;
- }
- command_list ++;
- }
- }
- (*argv)[argvpos ++]= cur_arg;
- }
- }
-
-done:
- /*
- Destroy the first, already handled option, so that programs that look
- for arguments in 'argv', without checking 'argc', know when to stop.
- Items in argv, before the destroyed one, are all non-option -arguments
- to the program, yet to be (possibly) handled.
- */
- (*argv)[argvpos]= 0;
- return 0;
-}
-
-
-/**
- * This function should be called to print a warning message
- * if password string is specified on the command line.
- */
-
-void print_cmdline_password_warning()
-{
- static my_bool password_warning_announced= FALSE;
-
- if (!password_warning_announced)
- {
- my_message_local(WARNING_LEVEL, "Using a password on the command line "
- "interface can be insecure.");
- password_warning_announced= TRUE;
- }
-}
-
-
-/**
- @brief Check for struct options
-
- @param[in] cur_arg Current argument under processing from argv
- @param[in] key_name variable where to store the possible key name
-
- @details
- In case option is a struct option, returns a pointer to the current
- argument at the position where the struct option (key_name) ends, the
- next character after the dot. In case argument is not a struct option,
- returns a pointer to the argument.
- key_name will hold the name of the key, or 0 if not found.
-
- @return char*
- If struct option Pointer to next character after dot.
- If no struct option Pointer to the argument
-*/
-
-static char *check_struct_option(char *cur_arg, char *key_name)
-{
- char *dot_pos, *equal_pos, *space_pos;
-
- dot_pos= strcend(cur_arg + 1, '.'); /* Skip the first character */
- equal_pos= strcend(cur_arg, '=');
- space_pos= strcend(cur_arg, ' ');
-
- /*
- If the first dot is after an equal sign, then it is part
- of a variable value and the option is not a struct option.
- Also, if the last character in the string before the ending
- NULL, or the character right before equal sign is the first
- dot found, the option is not a struct option.
- */
- if ((equal_pos > dot_pos) && (space_pos > dot_pos))
- {
- size_t len= (uint) (dot_pos - cur_arg);
- set_if_smaller(len, FN_REFLEN-1);
- strmake(key_name, cur_arg, len);
- return ++dot_pos;
- }
- else
- {
- key_name[0]= 0;
- return cur_arg;
- }
-}
-
-
-/**
- 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 struct my_option *opts,
- const char *argument,
- bool *error)
-{
- if (!my_strcasecmp(&my_charset_latin1, argument, "true") ||
- !my_strcasecmp(&my_charset_latin1, argument, "on") ||
- !my_strcasecmp(&my_charset_latin1, argument, "1"))
- return 1;
- else if (!my_strcasecmp(&my_charset_latin1, argument, "false") ||
- !my_strcasecmp(&my_charset_latin1, argument, "off") ||
- !my_strcasecmp(&my_charset_latin1, argument, "0"))
- return 0;
- else
- *error= 1;
- return 0;
-}
-
-/*
- function: setval
-
- Arguments: opts, argument
- Will set the option value to given value
-*/
-
-static int setval(const struct my_option *opts, void *value, char *argument,
- my_bool set_maximum_value)
-{
- int err= 0, res= 0;
- bool error= 0;
- ulong var_type= opts->var_type & GET_TYPE_MASK;
-
- if (!argument)
- argument= enabled_my_option;
-
- /*
- Thus check applies only to options that have a defined value
- storage pointer.
- We do it for numeric types only, as empty value is a valid
- option for strings (the only way to reset back to default value).
- Note: it does not relate to OPT_ARG/REQUIRED_ARG/NO_ARG, since
- --param="" is not generally the same as --param.
- TODO: Add an option definition flag to signify whether empty value
- (i.e. --param="") is an acceptable value or an error and extend
- the check to all options.
- */
- if (!*argument &&
- (
- var_type == GET_INT ||
- var_type == GET_UINT ||
- var_type == GET_LONG ||
- var_type == GET_ULONG ||
- var_type == GET_LL ||
- var_type == GET_ULL ||
- var_type == GET_DOUBLE ||
- var_type == GET_ENUM
- )
- )
- {
- if (strncmp(opts->name, "port", 10) == 0)
- {
- my_getopt_error_reporter(WARNING_LEVEL,
- "%s: Empty value for '%s' specified. Will throw an error in future versions",
- my_progname, opts->name);
- }
- else
- {
- my_getopt_error_reporter(ERROR_LEVEL,
- "%s: Empty value for '%s' specified",
- my_progname, opts->name);
- return EXIT_ARGUMENT_REQUIRED;
- }
- }
-
- 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 (var_type) {
- case GET_BOOL: /* If argument differs from 0, enable option, else disable */
- *((my_bool*) value)= get_bool_argument(opts, argument, &error);
- if(error)
- my_getopt_error_reporter(WARNING_LEVEL,
- "option '%s': boolean value '%s' wasn't recognized. Set to OFF.",
- opts->name, argument);
- break;
- case GET_INT:
- *((int*) value)= (int) getopt_ll(argument, opts, &err);
- break;
- case GET_UINT:
- *((uint*) value)= (uint) getopt_ull(argument, opts, &err);
- break;
- case GET_LONG:
- *((long*) value)= (long) getopt_ll(argument, opts, &err);
- break;
- case GET_ULONG:
- *((long*) value)= (long) getopt_ull(argument, opts, &err);
- break;
- case GET_LL:
- *((longlong*) value)= getopt_ll(argument, opts, &err);
- break;
- case GET_ULL:
- *((ulonglong*) value)= getopt_ull(argument, opts, &err);
- break;
- case GET_DOUBLE:
- *((double*) value)= getopt_double(argument, opts, &err);
- break;
- case GET_STR:
- case GET_PASSWORD:
- if (argument == enabled_my_option)
- break; /* string options don't use this default of "1" */
- *((char**) value)= argument;
- break;
- case GET_STR_ALLOC:
- if (argument == enabled_my_option)
- break; /* string options don't use this default of "1" */
- my_free(*((char**) value));
- if (!(*((char**) value)= my_strdup(key_memory_defaults,
- argument, MYF(MY_WME))))
- {
- res= EXIT_OUT_OF_MEMORY;
- goto ret;
- };
- break;
- case GET_ENUM:
- {
- int type= find_type(argument, opts->typelib, FIND_TYPE_BASIC);
- 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 if (type < 0)
- {
- res= EXIT_AMBIGUOUS_OPTION;
- goto ret;
- }
- else
- *(ulong*)value= type - 1;
- }
- break;
- case GET_SET:
- *((ulonglong*)value)= find_typeset(argument, opts->typelib, &err);
- if (err)
- {
- /* 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;
- 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, (uint)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)
- {
- 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;
-}
-
-
-/**
- Find option
-
- IMPLEMENTATION
- Go through all options in the my_option struct. Return true
- if an option is found. sets opt_res to the option found, if any.
-
- @param optpat name of option to find (with - or _)
- @param length Length of optpat
- @param[in,out] opt_res Options
-
- @retval false No matching options
- @retval true Found an option
-*/
-
-static bool findopt(char *optpat, uint length,
- const struct my_option **opt_res)
-{
- for (const struct my_option *opt= *opt_res; opt->name; opt++)
- if (!getopt_compare_strings(opt->name, optpat, length) &&
- !opt->name[length])
- {
- (*opt_res)= opt;
- return true;
- }
- return false;
-}
-
-
-/*
- function: compare_strings
-
- Works like strncmp, other than 1.) considers '-' and '_' the same.
- 2.) Returns -1 if strings differ, 0 if they are equal
-*/
-
-my_bool getopt_compare_strings(const char *s, 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: eval_num_suffix
-
- Transforms a number with a suffix to real number. Suffix can
- be k|K for kilo, m|M for mega or g|G for giga.
-*/
-
-static longlong eval_num_suffix(char *argument, int *error, char *option_name)
-{
- char *endchar;
- longlong num;
-
- *error= 0;
- errno= 0;
- num= my_strtoll(argument, &endchar, 10);
- if (errno == ERANGE)
- {
- my_getopt_error_reporter(ERROR_LEVEL,
- "Incorrect integer value: '%s'", argument);
- *error= 1;
- return 0;
- }
- 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)
- {
- my_message_local(ERROR_LEVEL,
- "Unknown suffix '%c' used for variable '%s' (value '%s')",
- *endchar, option_name, argument);
- *error= 1;
- return 0;
- }
- return num;
-}
-
-/**
- function: eval_num_suffix_ull
- This is the same as eval_num_suffix, but is meant for unsigned long long
- values. Transforms an unsigned number with a suffix to real number. Suffix can
- be k|K for kilo, m|M for mega or g|G for giga.
- @param [IN] argument argument value for option_name
- @param [IN, OUT] error error no.
- @param [IN] option_name name of option
-*/
-
-static ulonglong eval_num_suffix_ull(char *argument, int *error, char *option_name)
-{
- char *endchar;
- ulonglong num;
-
- *error= 0;
- errno= 0;
- num= my_strtoull(argument, &endchar, 10);
- if (errno == ERANGE)
- {
- my_getopt_error_reporter(ERROR_LEVEL,
- "Incorrect unsigned integer value: '%s'", argument);
- *error= 1;
- return 0;
- }
- 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)
- {
- my_message_local(ERROR_LEVEL,
- "Unknown suffix '%c' used for variable '%s' (value '%s')",
- *endchar, option_name, argument);
- *error= 1;
- return 0;
- }
- return num;
-}
-
-/*
- 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)
-{
- longlong num=eval_num_suffix(arg, err, (char*) optp->name);
- return getopt_ll_limit_value(num, optp, NULL);
-}
-
-
-/**
- Maximum possible value for an integer GET_* variable type
- @param var_type type of integer variable (GET_*)
- @returns maximum possible value for this type
- */
-ulonglong max_of_int_range(int var_type)
-{
- switch (var_type)
- {
- case GET_INT:
- return INT_MAX;
- case GET_LONG:
- return LONG_MAX;
- case GET_LL:
- return LLONG_MAX;
- case GET_UINT:
- return UINT_MAX;
- case GET_ULONG:
- return ULONG_MAX;
- case GET_ULL:
- return ULLONG_MAX;
- default:
- DBUG_ASSERT(0);
- return 0;
- }
-}
-
-
-/*
- function: getopt_ll_limit_value
-
- Applies min/max/block_size to a numeric value of an option.
- Returns "fixed" value.
-*/
-
-longlong getopt_ll_limit_value(longlong num, const struct my_option *optp,
- my_bool *fix)
-{
- longlong old= num;
- my_bool adjusted= FALSE;
- char buf1[255], buf2[255];
- ulonglong block_size= (optp->block_size ? (ulonglong) optp->block_size : 1L);
- const longlong max_of_type=
- (longlong)max_of_int_range(optp->var_type & GET_TYPE_MASK);
-
- if (num > 0 && ((ulonglong) num > (ulonglong) optp->max_value) &&
- optp->max_value) /* if max value is not set -> no upper limit */
- {
- num= (ulonglong) optp->max_value;
- adjusted= TRUE;
- }
-
- if (num > max_of_type)
- {
- num= max_of_type;
- adjusted= TRUE;
- }
-
- num= (num / block_size);
- num= (longlong) (num * block_size);
-
- if (num < optp->min_value)
- {
- num= optp->min_value;
- if (old < optp->min_value)
- adjusted= TRUE;
- }
-
- if (fix)
- *fix= old != num;
- else if (adjusted)
- my_getopt_error_reporter(WARNING_LEVEL,
- "option '%s': signed value %s adjusted to %s",
- optp->name, llstr(old, buf1), llstr(num, buf2));
- return num;
-}
-
-static inline my_bool is_negative_num(char* num)
-{
- while (my_isspace(&my_charset_latin1, *num))
- num++;
-
- return (*num == '-');
-}
-
-/*
- function: getopt_ull
-
- This is the same as getopt_ll, but is meant for unsigned long long
- values.
-*/
-
-static ulonglong getopt_ull(char *arg, const struct my_option *optp, int *err)
-{
- char buf[255];
- ulonglong num;
-
- /* If a negative number is specified as a value for the option. */
- if (arg == NULL || is_negative_num(arg) == TRUE)
- {
- num= (ulonglong) optp->min_value;
- my_getopt_error_reporter(WARNING_LEVEL,
- "option '%s': value %s adjusted to %s",
- optp->name, arg, ullstr(num, buf));
- }
- else
- num= eval_num_suffix_ull(arg, err, (char*) optp->name);
-
- return getopt_ull_limit_value(num, optp, NULL);
-}
-
-
-ulonglong getopt_ull_limit_value(ulonglong num, const struct my_option *optp,
- my_bool *fix)
-{
- my_bool adjusted= FALSE;
- ulonglong old= num;
- char buf1[255], buf2[255];
- const ulonglong max_of_type=
- max_of_int_range(optp->var_type & GET_TYPE_MASK);
-
- if (num > (ulonglong) optp->max_value &&
- optp->max_value) /* if max value is not set -> no upper limit */
- {
- num= (ulonglong) optp->max_value;
- adjusted= TRUE;
- }
-
- if (num > max_of_type)
- {
- num= max_of_type;
- adjusted= TRUE;
- }
-
- if (optp->block_size > 1)
- {
- num/= (ulonglong) optp->block_size;
- num*= (ulonglong) optp->block_size;
- }
-
- if (num < (ulonglong) optp->min_value)
- {
- num= (ulonglong) optp->min_value;
- if (old < (ulonglong) optp->min_value)
- adjusted= TRUE;
- }
-
- if (fix)
- *fix= old != num;
- else if (adjusted)
- my_getopt_error_reporter(WARNING_LEVEL,
- "option '%s': unsigned value %s adjusted to %s",
- optp->name, ullstr(old, buf1), ullstr(num, buf2));
-
- return num;
-}
-
-double getopt_double_limit_value(double num, const struct my_option *optp,
- my_bool *fix)
-{
- my_bool adjusted= FALSE;
- double old= num;
- double min, max;
-
- max= getopt_ulonglong2double(optp->max_value);
- min= getopt_ulonglong2double(optp->min_value);
- if (max && num > max)
- {
- num= max;
- adjusted= TRUE;
- }
- if (num < min)
- {
- num= min;
- 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
-
- Evaluates and returns the value that user gave as an argument to a variable.
-
- RETURN
- decimal value of arg
-
- In case of an error, prints an error message and sets *err to
- EXIT_ARGUMENT_INVALID. Otherwise err is not touched
-*/
-
-static double getopt_double(char *arg, const struct my_option *optp, int *err)
-{
- double num;
- int error;
- char *end= arg + 1000; /* Big enough as *arg is \0 terminated */
- num= my_strtod(arg, &end, &error);
- if (end[0] != 0 || error)
- {
- my_getopt_error_reporter(ERROR_LEVEL,
- "Invalid decimal value for option '%s'\n", optp->name);
- *err= EXIT_ARGUMENT_INVALID;
- return 0.0;
- }
- return getopt_double_limit_value(num, optp, NULL);
-}
-
-/*
- Init one value to it's default values
-
- SYNOPSIS
- init_one_value()
- option Option to initialize
- value Pointer to variable
-*/
-
-static void init_one_value(const struct my_option *option, void *variable,
- longlong value)
-{
- DBUG_ENTER("init_one_value");
- switch ((option->var_type & GET_TYPE_MASK)) {
- case GET_BOOL:
- *((my_bool*) variable)= (my_bool) value;
- break;
- case GET_INT:
- *((int*) variable)= (int) getopt_ll_limit_value((int) value, option, NULL);
- break;
- case GET_ENUM:
- *((ulong*) variable)= (ulong) value;
- break;
- case GET_UINT:
- *((uint*) variable)= (uint) getopt_ull_limit_value((uint) value, option, NULL);
- break;
- case GET_LONG:
- *((long*) variable)= (long) getopt_ll_limit_value((long) value, option, NULL);
- break;
- case GET_ULONG:
- *((ulong*) variable)= (ulong) getopt_ull_limit_value((ulong) value, option, NULL);
- break;
- case GET_LL:
- *((longlong*) variable)= getopt_ll_limit_value(value, option, NULL);
- break;
- case GET_ULL:
- *((ulonglong*) variable)= 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)= getopt_ulonglong2double(value);
- break;
- case GET_STR:
- case GET_PASSWORD:
- /*
- Do not clear variable value if it has no default value.
- The default value may already be set.
- NOTE: To avoid compiler warnings, we first cast longlong to intptr,
- so that the value has the same size as a pointer.
- */
- if ((char*) (intptr) value)
- *((char**) variable)= (char*) (intptr) value;
- break;
- case GET_STR_ALLOC:
- /*
- Do not clear variable value if it has no default value.
- The default value may already be set.
- NOTE: To avoid compiler warnings, we first cast longlong to intptr,
- so that the value has the same size as a pointer.
- */
- if ((char*) (intptr) value)
- {
- char **pstr= (char **) variable;
- my_free(*pstr);
- *pstr= my_strdup(key_memory_defaults,
- (char*) (intptr) value, MYF(MY_WME));
- }
- break;
- default: /* dummy default to avoid compiler warnings */
- break;
- }
- DBUG_VOID_RETURN;
-}
-
-
-/*
- Init one value to it's default values
-
- SYNOPSIS
- init_one_value()
- option Option to initialize
- value Pointer to variable
-*/
-
-static void fini_one_value(const struct my_option *option, void *variable,
- longlong value MY_ATTRIBUTE ((unused)))
-{
- DBUG_ENTER("fini_one_value");
- switch ((option->var_type & GET_TYPE_MASK)) {
- case GET_STR_ALLOC:
- my_free(*((char**) variable));
- *((char**) variable)= NULL;
- break;
- default: /* dummy default to avoid compiler warnings */
- break;
- }
- DBUG_VOID_RETURN;
-}
-
-
-void my_cleanup_options(const struct my_option *options)
-{
- init_variables(options, fini_one_value);
-}
-
-
-/*
- initialize all variables to their default values
-
- SYNOPSIS
- init_variables()
- options Array of 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 ask for the address
- for a value and initialize.
-*/
-
-static void init_variables(const struct my_option *options,
- init_func_p init_one_value)
-{
- DBUG_ENTER("init_variables");
- for (; options->name; options++)
- {
- void *value;
- DBUG_PRINT("options", ("name: '%s'", options->name));
- /*
- We must set u_max_value first as for some variables
- options->u_max_value == options->value and in this case we want to
- set the value to default value.
- */
- if (options->u_max_value)
- init_one_value(options, options->u_max_value, options->max_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 - to given file stream
- parameter (by default to stdout).
- @param [IN] optp my_option parameter
- @param [IN] file stream where the output of optp parameter name
- goes (by default to stdout).
-*/
-static uint print_name(const struct my_option *optp, FILE* file = stdout)
-{
- const char *s= optp->name;
- for (;*s;s++)
- putc(*s == '_' ? '-' : *s, file);
- return s - optp->name;
-}
-
-/*
- 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->name; optp++)
- {
- if (optp->id && optp->id < 256)
- {
- printf(" -%c%s", optp->id, strlen(optp->name) ? ", " : " ");
- col= 6;
- }
- else
- {
- printf(" ");
- col= 2;
- }
- if (strlen(optp->name))
- {
- 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_PASSWORD ||
- (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
- {
- printf("%s=#%s ", optp->arg_type == OPT_ARG ? "[" : "",
- optp->arg_type == OPT_ARG ? "]" : "");
- col+= (optp->arg_type == OPT_ARG) ? 5 : 3;
- }
- if (col > name_space && optp->comment && *optp->comment)
- {
- 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');
- 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");
- }
- }
- }
-}
-
-/**
- function: my_print_variables
- Print variables.
- @param [IN] options my_option list
-*/
-void my_print_variables(const struct my_option *options)
-{
- my_print_variables_ex(options, stdout);
-}
-
-/**
- function: my_print_variables_ex
- Print variables to given file parameter stream (by default to stdout).
- @param [IN] options my_options list
- @param [IN] file stream where the output goes.
-*/
-
-void my_print_variables_ex(const struct my_option *options, FILE* file)
-{
- uint name_space= 34, nr;
- size_t length;
- 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;
- }
-
- fprintf(file, "\nVariables (--variable-name=value)\n");
- fprintf(file, "%-*s%s", name_space, "and boolean options {FALSE|TRUE}",
- "Value (after reading options)\n");
- for (length=1; length < 75; length++)
- putc(length == name_space ? ' ' : '-', file);
- putc('\n', file);
-
- for (optp= options; optp->name; optp++)
- {
- void *value= (optp->var_type & GET_ASK_ADDR ?
- (*getopt_get_addr)("", 0, optp, 0) : optp->value);
- if (value)
- {
- length= print_name(optp, file);
- for (; length < name_space; length++)
- putc(' ', file);
- switch ((optp->var_type & GET_TYPE_MASK)) {
- case GET_SET:
- if (!(llvalue= *(ulonglong*) value))
- fprintf(file, "%s\n", "");
- else
- for (nr= 0; llvalue && nr < optp->typelib->count; nr++, llvalue >>=1)
- {
- if (llvalue & 1)
- fprintf(file, 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)
- {
- fprintf(file, "%s%s=", (nr ? "," : ""), get_type(optp->typelib, nr));
- fprintf(file, llvalue & 1 ? "on" : "off");
- }
- fprintf(file, "\n");
- break;
- case GET_ENUM:
- fprintf(file, "%s\n", get_type(optp->typelib, *(ulong*) value));
- break;
- case GET_STR:
- case GET_PASSWORD:
- case GET_STR_ALLOC: /* fall through */
- fprintf(file, "%s\n", *((char**) value) ? *((char**) value) :
- "(No default value)");
- break;
- case GET_BOOL:
- fprintf(file, "%s\n", *((my_bool*) value) ? "TRUE" : "FALSE");
- break;
- case GET_INT:
- fprintf(file, "%d\n", *((int*) value));
- break;
- case GET_UINT:
- fprintf(file, "%d\n", *((uint*) value));
- break;
- case GET_LONG:
- fprintf(file, "%ld\n", *((long*) value));
- break;
- case GET_ULONG:
- fprintf(file, "%lu\n", *((ulong*) value));
- break;
- case GET_LL:
- fprintf(file, "%s\n", llstr(*((longlong*) value), buff));
- break;
- case GET_ULL:
- longlong2str(*((ulonglong*) value), buff, 10);
- fprintf(file, "%s\n", buff);
- break;
- case GET_DOUBLE:
- fprintf(file, "%g\n", *(double*) value);
- break;
- case GET_NO_ARG:
- fprintf(file, "(No default value)\n");
- break;
- default:
- fprintf(file, "(Disabled)\n");
- break;
- }
- }
- }
-}