summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/my_getopt.h4
-rw-r--r--mysys/my_getopt.c50
-rw-r--r--sql/mysqld.cc21
-rw-r--r--sql/set_var.cc25
-rw-r--r--sql/set_var.h19
-rw-r--r--sql/sys_vars.ic29
-rw-r--r--storage/perfschema/unittest/pfs_server_stubs.cc6
-rw-r--r--unittest/mysys/CMakeLists.txt1
-rw-r--r--unittest/mysys/my_getopt-t.c353
9 files changed, 485 insertions, 23 deletions
diff --git a/include/my_getopt.h b/include/my_getopt.h
index 499cefd93d6..8c3d2db5cda 100644
--- a/include/my_getopt.h
+++ b/include/my_getopt.h
@@ -40,7 +40,8 @@ C_MODE_START
#define GET_FLAGSET 15
#define GET_ASK_ADDR 128
-#define GET_TYPE_MASK 127
+#define GET_AUTO 64
+#define GET_TYPE_MASK 63
/**
Enumeration of the my_option::arg_type attributes.
@@ -100,6 +101,7 @@ typedef void *(*my_getopt_value)(const char *, uint, const struct my_option *,
extern char *disabled_my_option;
+extern char *autoset_my_option;
extern my_bool my_getopt_print_errors;
extern my_bool my_getopt_skip_unknown;
extern my_bool my_getopt_prefix_matching;
diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c
index a619b391233..1f88d51849b 100644
--- a/mysys/my_getopt.c
+++ b/mysys/my_getopt.c
@@ -47,14 +47,15 @@ static char *check_struct_option(char *cur_arg, char *key_name);
order of their arguments must correspond to each other.
*/
static const char *special_opt_prefix[]=
-{"skip", "disable", "enable", "maximum", "loose", 0};
+{"skip", "disable", "enable", "maximum", "loose", "autoset", 0};
static const uint special_opt_prefix_lengths[]=
-{ 4, 7, 6, 7, 5, 0};
+{ 4, 7, 6, 7, 5, 7, 0};
enum enum_special_opt
-{ OPT_SKIP, OPT_DISABLE, OPT_ENABLE, OPT_MAXIMUM, OPT_LOOSE};
+{ OPT_SKIP, OPT_DISABLE, OPT_ENABLE, OPT_MAXIMUM, OPT_LOOSE, OPT_AUTOSET};
char *disabled_my_option= (char*) "0";
char *enabled_my_option= (char*) "1";
+char *autoset_my_option= (char*) "";
/*
This is a flag that can be set in client programs. 0 means that
@@ -198,7 +199,7 @@ int handle_options(int *argc, char ***argv,
{
uint UNINIT_VAR(opt_found), argvpos= 0, length;
my_bool end_of_options= 0, must_be_var, set_maximum_value,
- option_is_loose;
+ option_is_loose, option_is_autoset;
char **pos, **pos_end, *optend, *opt_str, key_name[FN_REFLEN];
const char *UNINIT_VAR(prev_found);
const struct my_option *optp;
@@ -249,6 +250,7 @@ int handle_options(int *argc, char ***argv,
must_be_var= 0;
set_maximum_value= 0;
option_is_loose= 0;
+ option_is_autoset= 0;
cur_arg++; /* skip '-' */
if (*cur_arg == '-') /* check for long option, */
@@ -297,6 +299,8 @@ int handle_options(int *argc, char ***argv,
length-= special_opt_prefix_lengths[i] + 1;
if (i == OPT_LOOSE)
option_is_loose= 1;
+ else if (i == OPT_AUTOSET)
+ option_is_autoset= 1;
if ((opt_found= findopt(opt_str, length, &optp, &prev_found)))
{
if (opt_found > 1)
@@ -458,6 +462,36 @@ int handle_options(int *argc, char ***argv,
}
argument= optend;
}
+ else if (option_is_autoset)
+ {
+ if (optend)
+ {
+ my_getopt_error_reporter(ERROR_LEVEL,
+ "%s: automatic setup request of "
+ "option '--%s' cannot take an argument",
+ my_progname, optp->name);
+
+ DBUG_RETURN(EXIT_NO_ARGUMENT_ALLOWED);
+ }
+ /*
+ We support automatic setup only via get_one_option and only for
+ marked options.
+ */
+ if (!get_one_option ||
+ !(optp->var_type & GET_AUTO))
+ {
+ my_getopt_error_reporter(option_is_loose ?
+ WARNING_LEVEL : ERROR_LEVEL,
+ "%s: automatic setup request is "
+ "unsupported by option '--%s'",
+ my_progname, optp->name);
+ if (!option_is_loose)
+ return EXIT_ARGUMENT_INVALID;
+ continue;
+ }
+ else
+ argument= autoset_my_option;
+ }
else if (optp->arg_type == REQUIRED_ARG && !optend)
{
/* Check if there are more arguments after this one,
@@ -585,7 +619,8 @@ int handle_options(int *argc, char ***argv,
(*argc)--; /* option handled (short), decrease argument count */
continue;
}
- if (((error= setval(optp, value, argument, set_maximum_value))) &&
+ if ((!option_is_autoset) &&
+ ((error= setval(optp, value, argument, set_maximum_value))) &&
!option_is_loose)
DBUG_RETURN(error);
if (get_one_option && get_one_option(optp->id, optp, argument))
@@ -1427,6 +1462,11 @@ void my_print_help(const struct my_option *options)
}
col= print_comment(optp->comment, col, name_space, comment_space);
+ if (optp->var_type & GET_AUTO)
+ {
+ col= print_comment(" (Automatically configured unless set explicitly)",
+ col, name_space, comment_space);
+ }
switch (optp->var_type & GET_TYPE_MASK) {
case GET_ENUM:
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 8d0ac59f89e..2265c6607b1 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -2299,7 +2299,7 @@ static void set_ports()
if ((env = getenv("MYSQL_TCP_PORT")))
{
mysqld_port= (uint) atoi(env);
- mark_sys_var_value_origin(&mysqld_port, sys_var::ENV);
+ set_sys_var_value_origin(&mysqld_port, sys_var::ENV);
}
}
if (!mysqld_unix_port)
@@ -2312,7 +2312,7 @@ static void set_ports()
if ((env = getenv("MYSQL_UNIX_PORT")))
{
mysqld_unix_port= env;
- mark_sys_var_value_origin(&mysqld_unix_port, sys_var::ENV);
+ set_sys_var_value_origin(&mysqld_unix_port, sys_var::ENV);
}
}
}
@@ -4187,7 +4187,7 @@ static int init_common_variables()
strmake(pidfile_name, opt_log_basename, sizeof(pidfile_name)-5);
strmov(fn_ext(pidfile_name),".pid"); // Add proper extension
SYSVAR_AUTOSIZE(pidfile_name_ptr, pidfile_name);
- mark_sys_var_value_origin(&opt_tc_log_size, sys_var::AUTO);
+ set_sys_var_value_origin(&opt_tc_log_size, sys_var::AUTO);
/*
The default-storage-engine entry in my_long_options should have a
@@ -8767,7 +8767,7 @@ static int mysql_init_variables(void)
if (!(tmpenv = getenv("MY_BASEDIR_VERSION")))
tmpenv = DEFAULT_MYSQL_HOME;
strmake_buf(mysql_home, tmpenv);
- mark_sys_var_value_origin(&mysql_home_ptr, sys_var::ENV);
+ set_sys_var_value_origin(&mysql_home_ptr, sys_var::ENV);
#endif
if (wsrep_init_vars())
@@ -8782,6 +8782,11 @@ mysqld_get_one_option(int optid, const struct my_option *opt, char *argument)
if (opt->app_type)
{
sys_var *var= (sys_var*) opt->app_type;
+ if (argument == autoset_my_option)
+ {
+ var->value_origin= sys_var::AUTO;
+ return 0;
+ }
var->value_origin= sys_var::CONFIG;
}
@@ -8894,8 +8899,8 @@ mysqld_get_one_option(int optid, const struct my_option *opt, char *argument)
make_default_log_name(&opt_bin_logname, "-bin", true);
/* Binary log index file */
make_default_log_name(&opt_binlog_index_name, "-bin.index", true);
- mark_sys_var_value_origin(&opt_logname, sys_var::AUTO);
- mark_sys_var_value_origin(&opt_slow_logname, sys_var::AUTO);
+ set_sys_var_value_origin(&opt_logname, sys_var::AUTO);
+ set_sys_var_value_origin(&opt_slow_logname, sys_var::AUTO);
if (!opt_logname || !opt_slow_logname || !opt_bin_logname ||
!opt_binlog_index_name)
return 1;
@@ -8905,7 +8910,7 @@ mysqld_get_one_option(int optid, const struct my_option *opt, char *argument)
make_default_log_name(&opt_relay_logname, "-relay-bin", true);
/* Relay log index file */
make_default_log_name(&opt_relaylog_index_name, "-relay-bin.index", true);
- mark_sys_var_value_origin(&opt_relay_logname, sys_var::AUTO);
+ set_sys_var_value_origin(&opt_relay_logname, sys_var::AUTO);
if (!opt_relay_logname || !opt_relaylog_index_name)
return 1;
#endif
@@ -9101,6 +9106,7 @@ mysqld_get_one_option(int optid, const struct my_option *opt, char *argument)
max_long_data_size_used= true;
break;
case OPT_PFS_INSTRUMENT:
+ {
#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
#ifndef EMBEDDED_LIBRARY
/* Parse instrument name and value from argument string */
@@ -9170,6 +9176,7 @@ mysqld_get_one_option(int optid, const struct my_option *opt, char *argument)
#endif
break;
}
+ }
return 0;
}
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 24e4e63e9cf..3756da562b9 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -178,6 +178,7 @@ sys_var::sys_var(sys_var_chain *chain, const char *name_arg,
else
chain->first= this;
chain->last= this;
+ fix_auto_flag();
}
bool sys_var::update(THD *thd, set_var *var)
@@ -1086,7 +1087,8 @@ int fill_sysvars(THD *thd, TABLE_LIST *tables, COND *cond)
{ STRING_WITH_LEN("DOUBLE") }, // GET_DOUBLE 14
{ STRING_WITH_LEN("FLAGSET") }, // GET_FLAGSET 15
};
- const LEX_CSTRING *type= types + (var->option.var_type & GET_TYPE_MASK);
+ const ulong vartype= (var->option.var_type & GET_TYPE_MASK);
+ const LEX_CSTRING *type= types + vartype;
fields[6]->store(type->str, type->length, scs);
// VARIABLE_COMMENT
@@ -1097,7 +1099,7 @@ int fill_sysvars(THD *thd, TABLE_LIST *tables, COND *cond)
// NUMERIC_MAX_VALUE
// NUMERIC_BLOCK_SIZE
bool is_unsigned= true;
- switch (var->option.var_type)
+ switch (vartype)
{
case GET_INT:
case GET_LONG:
@@ -1179,7 +1181,7 @@ end:
and update it directly.
*/
-void mark_sys_var_value_origin(void *ptr, enum sys_var::where here)
+void set_sys_var_value_origin(void *ptr, enum sys_var::where here)
{
bool found __attribute__((unused))= false;
DBUG_ASSERT(!mysqld_server_started); // only to be used during startup
@@ -1198,3 +1200,20 @@ void mark_sys_var_value_origin(void *ptr, enum sys_var::where here)
DBUG_ASSERT(found); // variable must have been found
}
+enum sys_var::where get_sys_var_value_origin(void *ptr)
+{
+ DBUG_ASSERT(!mysqld_server_started); // only to be used during startup
+
+ for (uint i= 0; i < system_variable_hash.records; i++)
+ {
+ sys_var *var= (sys_var*) my_hash_element(&system_variable_hash, i);
+ if (var->option.value == ptr)
+ {
+ return var->value_origin; //first match
+ }
+ }
+
+ DBUG_ASSERT(0); // variable must have been found
+ return sys_var::CONFIG;
+}
+
diff --git a/sql/set_var.h b/sql/set_var.h
index d10edb07133..b3538559fbb 100644
--- a/sql/set_var.h
+++ b/sql/set_var.h
@@ -62,7 +62,7 @@ public:
LEX_CSTRING name;
enum flag_enum { GLOBAL, SESSION, ONLY_SESSION, SCOPE_MASK=1023,
READONLY=1024, ALLOCATED=2048, PARSE_EARLY=4096,
- NO_SET_STATEMENT=8192};
+ NO_SET_STATEMENT=8192, AUTO_SET=16384};
enum { NO_GETOPT=-1, GETOPT_ONLY_HELP=-2 };
enum where { CONFIG, AUTO, SQL, COMPILE_TIME, ENV };
@@ -89,6 +89,12 @@ protected:
const char *const deprecation_substitute;
bool is_os_charset; ///< true if the value is in character_set_filesystem
+ inline void fix_auto_flag()
+ {
+ if (flags & AUTO_SET)
+ option.var_type|= GET_AUTO;
+ }
+
public:
sys_var(sys_var_chain *chain, const char *name_arg, const char *comment,
int flag_args, ptrdiff_t off, int getopt_id,
@@ -389,10 +395,17 @@ int sql_set_variables(THD *thd, List<set_var_base> *var_list, bool free);
#define SYSVAR_AUTOSIZE(VAR,VAL) \
do { \
VAR= (VAL); \
- mark_sys_var_value_origin(&VAR, sys_var::AUTO); \
+ set_sys_var_value_origin(&VAR, sys_var::AUTO); \
} while(0)
-void mark_sys_var_value_origin(void *ptr, enum sys_var::where here);
+void set_sys_var_value_origin(void *ptr, enum sys_var::where here);
+
+enum sys_var::where get_sys_var_value_origin(void *ptr);
+inline bool IS_SYSVAR_AUTOSIZE(void *ptr)
+{
+ enum sys_var::where res= get_sys_var_value_origin(ptr);
+ return (res == sys_var::AUTO || res == sys_var::COMPILE_TIME);
+}
bool fix_delay_key_write(sys_var *self, THD *thd, enum_var_type type);
diff --git a/sql/sys_vars.ic b/sql/sys_vars.ic
index 7c0359a7427..ea0e11ed19e 100644
--- a/sql/sys_vars.ic
+++ b/sql/sys_vars.ic
@@ -54,6 +54,7 @@
#define ON_CHECK(X) X
#define ON_UPDATE(X) X
#define READ_ONLY sys_var::READONLY+
+#define AUTO_SET sys_var::AUTO_SET+
// this means that Sys_var_charptr initial value was malloc()ed
#define PREALLOCATED sys_var::ALLOCATED+
#define PARSED_EARLY sys_var::PARSE_EARLY+
@@ -138,6 +139,7 @@ public:
on_check_func, on_update_func, substitute)
{
option.var_type= ARGT;
+ fix_auto_flag();
option.min_value= min_val;
option.max_value= max_val;
option.block_size= block_size;
@@ -157,9 +159,10 @@ public:
{
my_bool fixed= FALSE, unused;
longlong v= var->value->val_int();
+ ulong vartype= (ARGT & GET_TYPE_MASK);
- if ((ARGT == GET_HA_ROWS) || (ARGT == GET_UINT) ||
- (ARGT == GET_ULONG) || (ARGT == GET_ULL))
+ if ((vartype == GET_HA_ROWS) || (vartype == GET_UINT) ||
+ (vartype == GET_ULONG) || (vartype == GET_ULL))
{
ulonglong uv;
@@ -343,6 +346,7 @@ public:
substitute)
{
option.var_type= GET_ENUM;
+ fix_auto_flag();
global_var(ulong)= def_val;
SYSVAR_ASSERT(def_val < typelib.count);
SYSVAR_ASSERT(size == sizeof(ulong));
@@ -394,6 +398,7 @@ public:
substitute)
{
option.var_type= GET_BOOL;
+ fix_auto_flag();
global_var(my_bool)= def_val;
SYSVAR_ASSERT(def_val < 2);
SYSVAR_ASSERT(getopt.arg_type == OPT_ARG || getopt.id < 0);
@@ -460,6 +465,7 @@ public:
(think of an exit because of an error right after my_getopt)
*/
option.var_type= (flags & ALLOCATED) ? GET_STR_ALLOC : GET_STR;
+ fix_auto_flag();
global_var(const char*)= def_val;
SYSVAR_ASSERT(scope() == GLOBAL);
SYSVAR_ASSERT(size == sizeof(char *));
@@ -547,6 +553,7 @@ public:
{
is_os_charset= is_os_charset_arg == IN_FS_CHARSET;
option.var_type= GET_STR;
+ fix_auto_flag();
}
bool do_check(THD *thd, set_var *var)
{
@@ -603,6 +610,7 @@ public:
NULL, NULL, NULL), opt_id(getopt_id)
{
option.var_type= GET_STR | GET_ASK_ADDR;
+ fix_auto_flag();
}
bool do_check(THD *thd, set_var *var)
@@ -692,6 +700,7 @@ public:
0),max_length(max_length_arg)
{
option.var_type= GET_STR;
+ fix_auto_flag();
SYSVAR_ASSERT(scope() == ONLY_SESSION)
*const_cast<SHOW_TYPE*>(&show_val_type)= SHOW_LEX_STRING;
}
@@ -778,7 +787,7 @@ public:
getopt.arg_type, SHOW_CHAR, (intptr)def_val,
lock, binlog_status_arg, on_check_func, on_update_func,
substitute)
- { option.var_type= GET_STR; }
+ { option.var_type= GET_STR; fix_auto_flag(); }
bool do_check(THD *thd, set_var *var)
{
char buff[STRING_BUFFER_USUAL_SIZE];
@@ -1026,6 +1035,7 @@ public:
substitute)
{
option.var_type= GET_DOUBLE;
+ fix_auto_flag();
option.min_value= (longlong) getopt_double2ulonglong(min_val);
option.max_value= (longlong) getopt_double2ulonglong(max_val);
global_var(double)= (double)option.def_value;
@@ -1127,6 +1137,7 @@ public:
substitute)
{
option.var_type= GET_FLAGSET;
+ fix_auto_flag();
global_var(ulonglong)= def_val;
SYSVAR_ASSERT(typelib.count > 1);
SYSVAR_ASSERT(typelib.count <= 65);
@@ -1236,6 +1247,7 @@ public:
substitute)
{
option.var_type= GET_SET;
+ fix_auto_flag();
global_var(ulonglong)= def_val;
SYSVAR_ASSERT(typelib.count > 0);
SYSVAR_ASSERT(typelib.count <= 64);
@@ -1341,6 +1353,7 @@ public:
plugin_type(plugin_type_arg)
{
option.var_type= GET_STR;
+ fix_auto_flag();
SYSVAR_ASSERT(size == sizeof(plugin_ref));
SYSVAR_ASSERT(getopt.id < 0); // force NO_CMD_LINE
}
@@ -1457,6 +1470,7 @@ public:
{
SYSVAR_ASSERT(scope() == ONLY_SESSION);
option.var_type= GET_STR;
+ fix_auto_flag();
}
bool do_check(THD *thd, set_var *var)
{
@@ -1549,6 +1563,7 @@ public:
substitute)
{
option.var_type= GET_BOOL;
+ fix_auto_flag();
reverse_semantics= my_count_bits(bitmask_arg) > 1;
bitmask= reverse_semantics ? ~bitmask_arg : bitmask_arg;
set(global_var_ptr(), def_val);
@@ -1757,6 +1772,7 @@ public:
SYSVAR_ASSERT(on_update == 0);
SYSVAR_ASSERT(size == sizeof(enum SHOW_COMP_OPTION));
option.var_type= GET_STR;
+ fix_auto_flag();
}
bool do_check(THD *thd, set_var *var) {
DBUG_ASSERT(FALSE);
@@ -1819,6 +1835,7 @@ public:
name_offset(name_off)
{
option.var_type= GET_ENUM; // because we accept INT and STRING here
+ fix_auto_flag();
/*
struct variables are special on the command line - often (e.g. for
charsets) the name cannot be immediately resolved, but only after all
@@ -1888,6 +1905,7 @@ public:
SYSVAR_ASSERT(getopt.id < 0);
SYSVAR_ASSERT(size == sizeof(Time_zone *));
option.var_type= GET_STR;
+ fix_auto_flag();
}
bool do_check(THD *thd, set_var *var)
{
@@ -2107,6 +2125,7 @@ public:
SYSVAR_ASSERT(getopt.id < 0);
SYSVAR_ASSERT(is_readonly());
option.var_type= GET_STR;
+ fix_auto_flag();
}
bool do_check(THD *thd, set_var *var)
{
@@ -2156,6 +2175,7 @@ public:
SYSVAR_ASSERT(getopt.id < 0);
SYSVAR_ASSERT(is_readonly());
option.var_type= GET_STR;
+ fix_auto_flag();
}
bool do_check(THD *thd, set_var *var)
{
@@ -2203,6 +2223,7 @@ public:
NULL, NULL, NULL)
{
option.var_type= GET_STR;
+ fix_auto_flag();
}
bool do_check(THD *thd, set_var *var);
bool session_update(THD *thd, set_var *var)
@@ -2245,6 +2266,7 @@ public:
NULL, NULL, NULL)
{
option.var_type= GET_STR;
+ fix_auto_flag();
}
bool do_check(THD *thd, set_var *var);
bool session_update(THD *thd, set_var *var)
@@ -2288,6 +2310,7 @@ public:
SYSVAR_ASSERT(getopt.id < 0);
SYSVAR_ASSERT(is_readonly());
option.var_type= GET_STR;
+ fix_auto_flag();
}
bool do_check(THD *thd, set_var *var)
{
diff --git a/storage/perfschema/unittest/pfs_server_stubs.cc b/storage/perfschema/unittest/pfs_server_stubs.cc
index a023414357a..7c0e275edc7 100644
--- a/storage/perfschema/unittest/pfs_server_stubs.cc
+++ b/storage/perfschema/unittest/pfs_server_stubs.cc
@@ -34,7 +34,11 @@ void compute_digest_md5(const sql_digest_storage *, unsigned char *)
}
class sys_var { public: enum where { AUTO }; };
-void mark_sys_var_value_origin(void *ptr, enum sys_var::where here)
+void set_sys_var_value_origin(void *ptr, enum sys_var::where here)
{
}
+enum sys_var::where get_sys_var_value_origin(void *ptr)
+{
+ return sys_var::AUTO;
+}
diff --git a/unittest/mysys/CMakeLists.txt b/unittest/mysys/CMakeLists.txt
index 8a93c7a8b31..9455ad83849 100644
--- a/unittest/mysys/CMakeLists.txt
+++ b/unittest/mysys/CMakeLists.txt
@@ -14,6 +14,7 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
MY_ADD_TESTS(bitmap base64 my_vsnprintf my_atomic my_rdtsc lf my_malloc aes
+ my_getopt
LINK_LIBRARIES mysys)
ADD_DEFINITIONS(${SSL_DEFINES})
diff --git a/unittest/mysys/my_getopt-t.c b/unittest/mysys/my_getopt-t.c
new file mode 100644
index 00000000000..0eff84e8750
--- /dev/null
+++ b/unittest/mysys/my_getopt-t.c
@@ -0,0 +1,353 @@
+/* Copyright (c) 2015, Monty Program Ab
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+ THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND ANY
+ EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> OR
+ CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ SUCH DAMAGE.
+*/
+
+#include <my_global.h>
+#include <my_getopt.h>
+#include <mysys_err.h>
+#include <tap.h>
+
+ulong mopts_num;
+char *mopts_str;
+my_bool mopts_bool;
+static struct my_option mopts_options[]=
+{
+ {"str", 0,
+ "Something numeric.",
+ &mopts_str, &mopts_str, 0, GET_STR,
+ REQUIRED_ARG, (ulong)"ddd", 0, 0, 0, 0, 0},
+ {"bool", 0,
+ "Something true or false",
+ &mopts_bool, &mopts_bool, 0, GET_BOOL,
+ OPT_ARG, FALSE, 0, 0, 0, 0, 0},
+ {"num", 0,
+ "Something numeric.",
+ &mopts_num, &mopts_num, 0, GET_ULONG,
+ REQUIRED_ARG, 1000000L, 1, ULONG_MAX, 0, 2, 0},
+ { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
+};
+
+int mopts1_argc= 4;
+const char *mopts1_argv[]= {"mopts1", "--num=123", "--str=str", "--bool"};
+void test_mopts1()
+{
+ int rc;
+ char **av= (char **)mopts1_argv;
+
+ rc= handle_options(&mopts1_argc, &av, mopts_options, NULL);
+ ok( (rc == 0), "%s", "test_mopts1 call");
+ ok( (mopts_num == 122), "%s", "test_mopts1 num");
+ ok( (strncmp(mopts_str, "str", 4) == 0), "%s", "test_mopts1 str");
+ ok( (mopts_bool == 1), "%s", "test_mopts1 bool");
+}
+
+int mopts2_argc= 4;
+const char *mopts2_argv[]= {"mopts2", "--num=123", "--num=124", "--bool=0"};
+void test_mopts2()
+{
+ int rc;
+ char **av= (char **)mopts2_argv;
+
+ rc= handle_options(&mopts2_argc, &av, mopts_options, NULL);
+ ok( (rc == 0), "%s", "test_mopts2 call");
+ ok( (mopts_num == 124), "%s", "test_mopts2 num");
+ ok( (strncmp(mopts_str, "ddd", 4) == 0), "%s", "test_mopts2 str");
+ ok( (mopts_bool == 0), "%s", "test_mopts2 bool");
+}
+
+int mopts3_argc= 4;
+const char *mopts3_argv[]= {"mopts3", "--loose-foo", "--loose-loose-foo", "--enable-bool"};
+void test_mopts3()
+{
+ int rc;
+ char **av= (char **)mopts3_argv;
+
+ rc= handle_options(&mopts3_argc, &av, mopts_options, NULL);
+ ok( (rc == 0), "%s", "test_mopts3 call");
+ ok( (mopts_num == 1000000L), "%s", "test_mopts3 num");
+ ok( (strncmp(mopts_str, "ddd", 4) == 0), "%s", "test_mopts3 str");
+ ok( (mopts_bool == 1), "%s", "test_mopts3 bool");
+}
+
+int mopts4_argc= 3;
+const char *mopts4_argv[]= {"mopts4", "--loose-str=aa", "--skip-bool"};
+void test_mopts4()
+{
+ int rc;
+ char **av= (char **)mopts4_argv;
+
+ rc= handle_options(&mopts4_argc, &av, mopts_options, NULL);
+ ok( (rc == 0), "%s", "test_mopts4 call");
+ ok( (mopts_num == 1000000L), "%s", "test_mopts4 num");
+ ok( (strncmp(mopts_str, "aa", 3) == 0), "%s", "test_mopts4 str");
+ ok( (mopts_bool == 0), "%s", "test_mopts4 bool");
+}
+
+int mopts5_argc= 2;
+const char *mopts5_argv[]= {"mopts5", "--loose-skip-bool"};
+void test_mopts5()
+{
+ int rc;
+ char **av= (char **)mopts5_argv;
+
+ rc= handle_options(&mopts5_argc, &av, mopts_options, NULL);
+ ok( (rc == 0), "%s", "test_mopts5 call");
+ ok( (mopts_num == 1000000L), "%s", "test_mopts5 num");
+ ok( (strncmp(mopts_str, "ddd", 4) == 0), "%s", "test_mopts5 str");
+ ok( (mopts_bool == 0), "%s", "test_mopts5 bool");
+}
+
+int mopts6_argc= 2;
+const char *mopts6_argv[]= {"mopts6", "--loose-skip-skip-bool"};
+void test_mopts6()
+{
+ int rc;
+ char **av= (char **)mopts6_argv;
+
+ rc= handle_options(&mopts6_argc, &av, mopts_options, NULL);
+ ok( (rc == 0), "%s", "test_mopts6 call");
+ ok( (mopts_num == 1000000L), "%s", "test_mopts6 num");
+ ok( (strncmp(mopts_str, "ddd", 4) == 0), "%s", "test_mopts6 str");
+ ok( (mopts_bool == 0), "%s", "test_mopts6 bool");
+}
+
+int mopts7_argc= 2;
+const char *mopts7_argv[]= {"mopts7", "--loose-disable-skip-bool"};
+void test_mopts7()
+{
+ int rc;
+ char **av= (char **)mopts7_argv;
+
+ rc= handle_options(&mopts7_argc, &av, mopts_options, NULL);
+ ok( (rc == 0), "%s", "test_mopts7 call");
+ ok( (mopts_num == 1000000L), "%s", "test_mopts7 num");
+ ok( (strncmp(mopts_str, "ddd", 4) == 0), "%s", "test_mopts7 str");
+ ok( (mopts_bool == 0), "%s", "test_mopts7 bool");
+}
+
+int mopts8_argc= 2;
+const char *mopts8_argv[]= {"mopts8", "--loose-disable-enable-bool"};
+void test_mopts8()
+{
+ int rc;
+ char **av= (char **)mopts8_argv;
+
+ rc= handle_options(&mopts8_argc, &av, mopts_options, NULL);
+ ok( (rc == 0), "%s", "test_mopts8 call");
+ ok( (mopts_num == 1000000L), "%s", "test_mopts7 num");
+ ok( (strncmp(mopts_str, "ddd", 4) == 0), "%s", "test_mopts7 str");
+ ok( (mopts_bool == 1), "%s", "test_mopts7 bool");
+}
+
+int mopts9_argc= 2;
+const char *mopts9_argv[]= {"mopts9", "--foo"};
+void test_mopts9()
+{
+ int rc;
+ char **av= (char **)mopts9_argv;
+
+ rc= handle_options(&mopts9_argc, &av, mopts_options, NULL);
+ ok( (rc != 0), "%s", "test_mopts9 call");
+}
+
+int mopts10_argc= 2;
+const char *mopts10_argv[]= {"mopts10", "--skip-foo"};
+void test_mopts10()
+{
+ int rc;
+ char **av= (char **)mopts10_argv;
+
+ rc= handle_options(&mopts10_argc, &av, mopts_options, NULL);
+ ok( (rc != 0), "%s", "test_mopts10 call");
+}
+
+ulong auto_num;
+static struct my_option auto_options[]=
+{
+ {"anum", 0,
+ "Something numeric.",
+ &auto_num, &auto_num, 0, GET_ULONG | GET_AUTO,
+ REQUIRED_ARG, 1000000L, 1, ULONG_MAX, 0, 1, 0},
+ {"num", 0,
+ "Something numeric.",
+ &mopts_num, &mopts_num, 0, GET_ULONG,
+ REQUIRED_ARG, 1000000L, 1, ULONG_MAX, 0, 1, 0},
+ { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
+};
+
+
+
+my_bool auto_get_one_option(int optid __attribute__((unused)),
+ const struct my_option *opt,
+ char *argument)
+{
+ if (argument == autoset_my_option)
+ {
+ *((ulong*)opt->value)= 111;
+ }
+ return FALSE;
+}
+
+int auto1_argc= 3;
+const char *auto1_argv[]= {"auto1", "--anum=123", "--autoset-anum"};
+void test_auto1()
+{
+ int rc;
+ char **av= (char **)auto1_argv;
+
+ rc= handle_options(&auto1_argc, &av, auto_options, NULL);
+ ok( (rc == EXIT_ARGUMENT_INVALID), "%s", "test_auto1 call");
+}
+
+int auto2_argc= 3;
+const char *auto2_argv[]= {"auto2", "--num=123", "--autoset-num"};
+void test_auto2()
+{
+ int rc;
+ char **av= (char **)auto2_argv;
+
+ rc= handle_options(&auto2_argc, &av, auto_options, &auto_get_one_option);
+ ok( (rc == EXIT_ARGUMENT_INVALID), "%s", "test_auto2 call");
+}
+
+int auto3_argc= 3;
+const char *auto3_argv[]= {"auto3", "--anum=123", "--autoset-anum"};
+void test_auto3()
+{
+ int rc;
+ char **av= (char **)auto3_argv;
+
+ rc= handle_options(&auto3_argc, &av, auto_options, &auto_get_one_option);
+ ok( (rc == 0), "%s", "test_auto3 call");
+ ok( (mopts_num == 1000000L), "%s", "test_auto3 num");
+ ok( (auto_num == 111), "%s", "test_auto3 anum");
+}
+
+int auto4_argc= 3;
+const char *auto4_argv[]= {"auto4", "--loose-autoset-num", "--loose-autoset-anum"};
+void test_auto4()
+{
+ int rc;
+ char **av= (char **)auto4_argv;
+
+ rc= handle_options(&auto4_argc, &av, auto_options, &auto_get_one_option);
+ ok( (rc == 0), "%s", "test_auto4 call");
+ ok( (mopts_num == 1000000L), "%s", "test_auto4 num");
+ ok( (auto_num == 111), "%s", "test_auto4 anum");
+}
+
+int auto5_argc= 3;
+const char *auto5_argv[]= {"auto5", "--autoset-loose-num", "--autoset-loose-anum"};
+void test_auto5()
+{
+ int rc;
+ char **av= (char **)auto5_argv;
+
+ rc= handle_options(&auto5_argc, &av, auto_options, &auto_get_one_option);
+ ok( (rc == 0), "%s", "test_auto5 call");
+ ok( (mopts_num == 1000000L), "%s", "test_auto5 num");
+ ok( (auto_num == 111), "%s", "test_auto5 anum");
+}
+
+int auto6_argc= 3;
+const char *auto6_argv[]= {"auto6", "--autoset-anum", "--anum=123"};
+void test_auto6()
+{
+ int rc;
+ char **av= (char **)auto6_argv;
+
+ rc= handle_options(&auto6_argc, &av, auto_options, &auto_get_one_option);
+ ok( (rc == 0), "%s", "test_auto6 call");
+ ok( (mopts_num == 1000000L), "%s", "test_auto6 num");
+ ok( (auto_num == 123), "%s", "test_auto6 anum");
+}
+
+
+ulong max_num= ULONG_MAX;
+static struct my_option max_options[]=
+{
+ {"num", 0,
+ "Something numeric.",
+ &mopts_num, &max_num, 0, GET_ULONG,
+ REQUIRED_ARG, 1000000L, 1, 1000001L, 0, 1, 0},
+ { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
+};
+
+int max1_argc= 3;
+const char *max1_argv[]= {"max1", "--num=100", "--num=200"};
+void test_max1()
+{
+ int rc;
+ char **av= (char **)max1_argv;
+
+ rc= handle_options(&max1_argc, &av, max_options, NULL);
+ ok( (rc == 0), "%s", "test_max1 call");
+ ok( (mopts_num == 200), "%s", "test_max1 num");
+ ok( (max_num == 1000001L), "%s", "test_max1 max_num");
+}
+int max2_argc= 3;
+const char *max2_argv[]= {"max2", "--maximum-num=100", "--num=200"};
+void test_max2()
+{
+ int rc;
+ char **av= (char **)max2_argv;
+
+ rc= handle_options(&max2_argc, &av, max_options, NULL);
+ ok( (rc == 0), "%s", "test_max2 call");
+ ok( (mopts_num == 200), "%s", "test_max2 num");
+ ok( (max_num == 100), "%s", "test_max2 max_num");
+}
+
+int main(int argc __attribute__((unused)), char **argv)
+{
+ MY_INIT(argv[0]);
+ plan(4*8 + 1*4 + 3*4 + 3*2);
+
+ test_mopts1();
+ test_mopts2();
+ test_mopts3();
+ test_mopts4();
+ test_mopts5();
+ test_mopts6();
+ test_mopts7();
+ test_mopts8();
+
+ test_mopts9();
+ test_mopts10();
+ test_auto1();
+ test_auto2();
+
+ test_auto3();
+ test_auto4();
+ test_auto5();
+ test_auto6();
+
+ test_max1();
+ test_max2();
+
+ my_end(0);
+ return exit_status();
+}