diff options
-rw-r--r-- | include/my_getopt.h | 4 | ||||
-rw-r--r-- | mysys/my_getopt.c | 50 | ||||
-rw-r--r-- | sql/mysqld.cc | 21 | ||||
-rw-r--r-- | sql/set_var.cc | 25 | ||||
-rw-r--r-- | sql/set_var.h | 19 | ||||
-rw-r--r-- | sql/sys_vars.ic | 29 | ||||
-rw-r--r-- | storage/perfschema/unittest/pfs_server_stubs.cc | 6 | ||||
-rw-r--r-- | unittest/mysys/CMakeLists.txt | 1 | ||||
-rw-r--r-- | unittest/mysys/my_getopt-t.c | 353 |
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(); +} |