diff options
Diffstat (limited to 'mysys/my_getopt.c')
-rw-r--r-- | mysys/my_getopt.c | 310 |
1 files changed, 207 insertions, 103 deletions
diff --git a/mysys/my_getopt.c b/mysys/my_getopt.c index 694c4685667..d7a9babe5e7 100644 --- a/mysys/my_getopt.c +++ b/mysys/my_getopt.c @@ -18,7 +18,6 @@ #include <m_string.h> #include <stdlib.h> #include <my_getopt.h> -#include <assert.h> #include <my_sys.h> #include <mysys_err.h> @@ -32,8 +31,9 @@ static longlong getopt_ll(char *arg, const struct my_option *optp, int *err); static ulonglong getopt_ull(char *arg, const struct my_option *optp, int *err); static void init_variables(const struct my_option *options); -static int setval(const struct my_option *opts,char *argument, +static int setval(const struct my_option *opts, gptr *value, char *argument, my_bool set_maximum_value); +static char *check_struct_option(char *cur_arg, char *key_name); /* The following three variables belong to same group and the number and @@ -67,6 +67,14 @@ my_bool my_getopt_print_errors= 1; one. Call function 'get_one_option()' once for each option. */ +static gptr* (*getopt_get_addr)(const char *, uint, const struct my_option *); + +void my_getopt_register_get_addr(gptr* (*func_addr)(const char *, uint, + const struct my_option *)) +{ + getopt_get_addr= func_addr; +} + int handle_options(int *argc, char ***argv, const struct my_option *longopts, my_bool (*get_one_option)(int, @@ -74,10 +82,12 @@ int handle_options(int *argc, char ***argv, char *)) { uint opt_found, argvpos= 0, length, i; - my_bool end_of_options= 0, must_be_var, set_maximum_value, special_used, + my_bool end_of_options= 0, must_be_var, set_maximum_value, option_is_loose; - char *progname= *(*argv), **pos, **pos_end, *optend, *prev_found; + char **pos, **pos_end, *optend, *prev_found, + *opt_str, key_name[FN_REFLEN]; const struct my_option *optp; + gptr *value; int error; LINT_INIT(opt_found); @@ -93,7 +103,6 @@ int handle_options(int *argc, char ***argv, char *argument= 0; must_be_var= 0; set_maximum_value= 0; - special_used= 0; option_is_loose= 0; cur_arg++; /* skip '-' */ @@ -110,7 +119,7 @@ int handle_options(int *argc, char ***argv, { if (my_getopt_print_errors) fprintf(stderr, "%s: Option '-O' requires an argument\n", - progname); + my_progname); return EXIT_ARGUMENT_REQUIRED; } cur_arg= *pos; @@ -128,7 +137,7 @@ int handle_options(int *argc, char ***argv, if (my_getopt_print_errors) fprintf(stderr, "%s: Option '--set-variable' requires an argument\n", - progname); + my_progname); return EXIT_ARGUMENT_REQUIRED; } } @@ -142,7 +151,7 @@ int handle_options(int *argc, char ***argv, if (my_getopt_print_errors) fprintf(stderr, "%s: Option '--set-variable' requires an argument\n", - progname); + my_progname); return EXIT_ARGUMENT_REQUIRED; } cur_arg= *pos; @@ -159,19 +168,20 @@ int handle_options(int *argc, char ***argv, continue; } } - optend= strcend(cur_arg, '='); - length= optend - cur_arg; + opt_str= check_struct_option(cur_arg, key_name); + optend= strcend(opt_str, '='); + length= optend - opt_str; if (*optend == '=') optend++; else - optend=0; + optend= 0; /* Find first the right option. Return error in case of an ambiguous, or unknown option */ optp= longopts; - if (!(opt_found= findopt(cur_arg, length, &optp, &prev_found))) + if (!(opt_found= findopt(opt_str, length, &optp, &prev_found))) { /* Didn't find any matching option. Let's see if someone called @@ -183,18 +193,17 @@ int handle_options(int *argc, char ***argv, 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], cur_arg, + if (!getopt_compare_strings(special_opt_prefix[i], opt_str, special_opt_prefix_lengths[i]) && - cur_arg[special_opt_prefix_lengths[i]] == '-') + opt_str[special_opt_prefix_lengths[i]] == '-') { /* We were called with a special prefix, we can reuse opt_found */ - special_used= 1; - cur_arg+= (special_opt_prefix_lengths[i] + 1); + opt_str+= (special_opt_prefix_lengths[i] + 1); if (i == OPT_LOOSE) option_is_loose= 1; - if ((opt_found= findopt(cur_arg, length - + if ((opt_found= findopt(opt_str, length - (special_opt_prefix_lengths[i] + 1), &optp, &prev_found))) { @@ -203,7 +212,7 @@ int handle_options(int *argc, char ***argv, if (my_getopt_print_errors) fprintf(stderr, "%s: ambiguous option '--%s-%s' (--%s-%s)\n", - progname, special_opt_prefix[i], cur_arg, + my_progname, special_opt_prefix[i], opt_str, special_opt_prefix[i], prev_found); return EXIT_AMBIGUOUS_OPTION; } @@ -237,8 +246,8 @@ int handle_options(int *argc, char ***argv, { if (my_getopt_print_errors) fprintf(stderr, - "%s: %s: unknown variable '%s'\n", progname, - option_is_loose ? "WARNING" : "ERROR", cur_arg); + "%s: %s: unknown variable '%s'\n", my_progname, + option_is_loose ? "WARNING" : "ERROR", opt_str); if (!option_is_loose) return EXIT_UNKNOWN_VARIABLE; } @@ -246,8 +255,8 @@ int handle_options(int *argc, char ***argv, { if (my_getopt_print_errors) fprintf(stderr, - "%s: %s: unknown option '--%s'\n", progname, - option_is_loose ? "WARNING" : "ERROR", cur_arg); + "%s: %s: unknown option '--%s'\n", my_progname, + option_is_loose ? "WARNING" : "ERROR", opt_str); if (!option_is_loose) return EXIT_UNKNOWN_OPTION; } @@ -264,34 +273,50 @@ int handle_options(int *argc, char ***argv, { if (my_getopt_print_errors) fprintf(stderr, "%s: variable prefix '%s' is not unique\n", - progname, cur_arg); + my_progname, opt_str); return EXIT_VAR_PREFIX_NOT_UNIQUE; } else { if (my_getopt_print_errors) fprintf(stderr, "%s: ambiguous option '--%s' (%s, %s)\n", - progname, cur_arg, prev_found, optp->name); + my_progname, opt_str, prev_found, optp->name); return EXIT_AMBIGUOUS_OPTION; } } - if (must_be_var && optp->var_type == GET_NO_ARG) + if ((optp->var_type & GET_TYPE_MASK) == GET_DISABLED) + { + if (my_getopt_print_errors) + fprintf(stderr, + "%s: %s: Option '%s' used, but is disabled\n", my_progname, + option_is_loose ? "WARNING" : "ERROR", opt_str); + if (option_is_loose) + { + (*argc)--; + continue; + } + return EXIT_OPTION_DISABLED; + } + if (must_be_var && (optp->var_type & GET_TYPE_MASK) == GET_NO_ARG) { if (my_getopt_print_errors) fprintf(stderr, "%s: option '%s' cannot take an argument\n", - progname, optp->name); + my_progname, optp->name); return EXIT_NO_ARGUMENT_ALLOWED; } + value= optp->var_type & GET_ASK_ADDR ? + (*getopt_get_addr)(key_name, strlen(key_name), optp) : optp->value; + if (optp->arg_type == NO_ARG) { - if (optend && optp->var_type != GET_BOOL) + if (optend && (optp->var_type & GET_TYPE_MASK) != GET_BOOL) { if (my_getopt_print_errors) fprintf(stderr, "%s: option '--%s' cannot take an argument\n", - progname, optp->name); + my_progname, optp->name); return EXIT_NO_ARGUMENT_ALLOWED; } - if (optp->var_type == GET_BOOL) + if ((optp->var_type & GET_TYPE_MASK) == GET_BOOL) { /* Set bool to 1 if no argument or if the user has used @@ -299,7 +324,7 @@ int handle_options(int *argc, char ***argv, *optend was set to '0' if one used --disable-option */ my_bool tmp= (my_bool) (!optend || *optend == '1'); - *((my_bool*) optp->value)= tmp; + *((my_bool*) value)= tmp; (*argc)--; get_one_option(optp->id, optp, tmp ? (char*) "1" : disabled_my_option); @@ -307,14 +332,15 @@ int handle_options(int *argc, char ***argv, } argument= optend; } - else if (optp->arg_type == OPT_ARG && optp->var_type == GET_BOOL) + else if (optp->arg_type == OPT_ARG && + (optp->var_type & GET_TYPE_MASK) == GET_BOOL) { if (optend == disabled_my_option) - *((my_bool*) optp->value)= (my_bool) 0; + *((my_bool*) value)= (my_bool) 0; else { if (!optend) /* No argument -> enable option */ - *((my_bool*) optp->value)= (my_bool) 1; + *((my_bool*) value)= (my_bool) 1; else argument= optend; } @@ -326,7 +352,7 @@ int handle_options(int *argc, char ***argv, { if (my_getopt_print_errors) fprintf(stderr, "%s: option '--%s' requires an argument\n", - progname, optp->name); + my_progname, optp->name); return EXIT_ARGUMENT_REQUIRED; } argument= *pos; @@ -346,7 +372,16 @@ int handle_options(int *argc, char ***argv, { /* Option recognized. Find next what to do with it */ opt_found= 1; - if (optp->var_type == GET_BOOL && optp->arg_type == NO_ARG) + if ((optp->var_type & GET_TYPE_MASK) == GET_DISABLED) + { + if (my_getopt_print_errors) + fprintf(stderr, + "%s: ERROR: Option '-%c' used, but is disabled\n", + 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; get_one_option(optp->id, optp, argument); @@ -377,7 +412,7 @@ int handle_options(int *argc, char ***argv, if (my_getopt_print_errors) fprintf(stderr, "%s: option '-%c' requires an argument\n", - progname, optp->id); + my_progname, optp->id); return EXIT_ARGUMENT_REQUIRED; } argument= *++pos; @@ -385,11 +420,12 @@ int handle_options(int *argc, char ***argv, /* the other loop will break, because *optend + 1 == 0 */ } } - if ((error= setval(optp, argument, set_maximum_value))) + if ((error= setval(optp, optp->value, argument, + set_maximum_value))) { fprintf(stderr, "%s: Error while setting value '%s' to '%s'\n", - progname, argument, optp->name); + my_progname, argument, optp->name); return error; } get_one_option(optp->id, optp, argument); @@ -400,18 +436,18 @@ int handle_options(int *argc, char ***argv, { if (my_getopt_print_errors) fprintf(stderr, - "%s: unknown option '-%c'\n", progname, *optend); + "%s: unknown option '-%c'\n", my_progname, *optend); return EXIT_UNKNOWN_OPTION; } } (*argc)--; /* option handled (short), decrease argument count */ continue; } - if ((error= setval(optp, argument, set_maximum_value))) + if ((error= setval(optp, value, argument, set_maximum_value))) { fprintf(stderr, "%s: Error while setting value '%s' to '%s'\n", - progname, argument, optp->name); + my_progname, argument, optp->name); return error; } get_one_option(optp->id, optp, argument); @@ -431,6 +467,49 @@ int handle_options(int *argc, char ***argv, return 0; } + +/* + function: check_struct_option + + Arguments: Current argument under processing from argv and a variable + where to store the possible key name. + + Return value: 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. +*/ + +static char *check_struct_option(char *cur_arg, char *key_name) +{ + char *ptr, *end; + + ptr= strcend(cur_arg + 1, '.'); /* Skip the first character */ + end= 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 (end - ptr > 1) + { + uint len= ptr - cur_arg; + set_if_smaller(len, FN_REFLEN-1); + strmake(key_name, cur_arg, len); + return ++ptr; + } + else + { + key_name[0]= 0; + return cur_arg; + } +} + /* function: setval @@ -438,20 +517,20 @@ int handle_options(int *argc, char ***argv, Will set the option value to given value */ -static int setval(const struct my_option *opts, char *argument, +static int setval(const struct my_option *opts, gptr *value, char *argument, my_bool set_maximum_value) { int err= 0; - if (opts->value && argument) + if (value && argument) { gptr *result_pos= ((set_maximum_value) ? - opts->u_max_value : opts->value); + opts->u_max_value : value); if (!result_pos) return EXIT_NO_PTR_TO_VARIABLE; - switch (opts->var_type) { + switch ((opts->var_type & GET_TYPE_MASK)) { case GET_BOOL: /* If argument differs from 0, enable option, else disable */ *((my_bool*) result_pos)= (my_bool) atoi(argument) != 0; break; @@ -503,7 +582,7 @@ static int findopt(char *optpat, uint length, const struct my_option **opt_res, char **ffname) { - int count; + uint count; struct my_option *opt= (struct my_option *) *opt_res; for (count= 0; opt->name; opt++) @@ -515,7 +594,8 @@ static int findopt(char *optpat, uint length, *ffname= (char *) opt->name; /* We only need to know one prev */ if (!opt->name[length]) /* Exact match */ return 1; - count++; + if (!count || strcmp(*ffname, opt->name)) /* Don't count synonyms */ + count++; } } return count; @@ -628,58 +708,77 @@ ulonglong getopt_ull_limit_value(ulonglong num, const struct my_option *optp) return num; } -/* - function: init_variables +/* + 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, gptr *variable, + longlong value) +{ + switch ((option->var_type & GET_TYPE_MASK)) { + case GET_BOOL: + *((my_bool*) variable)= (my_bool) value; + break; + case GET_INT: + *((int*) variable)= (int) value; + break; + case GET_UINT: + *((uint*) variable)= (uint) value; + break; + case GET_LONG: + *((long*) variable)= (long) value; + break; + case GET_ULONG: + *((ulong*) variable)= (ulong) value; + break; + case GET_LL: + *((longlong*) variable)= (longlong) value; + break; + case GET_ULL: + *((ulonglong*) variable)= (ulonglong) value; + break; + default: /* dummy default to avoid compiler warnings */ + break; + } +} + + +/* 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 also ask for the address + for a value and initialize. */ static void init_variables(const struct my_option *options) { for (; options->name; options++) { + gptr *variable; + /* + 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); if (options->value) - { - switch (options->var_type) { - case GET_BOOL: - if (options->u_max_value) - *((my_bool*) options->u_max_value)= (my_bool) options->max_value; - *((my_bool*) options->value)= (my_bool) options->def_value; - break; - case GET_INT: - if (options->u_max_value) - *((int*) options->u_max_value)= (int) options->max_value; - *((int*) options->value)= (int) options->def_value; - break; - case GET_UINT: - if (options->u_max_value) - *((uint*) options->u_max_value)= (uint) options->max_value; - *((uint*) options->value)= (uint) options->def_value; - break; - case GET_LONG: - if (options->u_max_value) - *((long*) options->u_max_value)= (long) options->max_value; - *((long*) options->value)= (long) options->def_value; - break; - case GET_ULONG: - if (options->u_max_value) - *((ulong*) options->u_max_value)= (ulong) options->max_value; - *((ulong*) options->value)= (ulong) options->def_value; - break; - case GET_LL: - if (options->u_max_value) - *((longlong*) options->u_max_value)= (longlong) options->max_value; - *((longlong*) options->value)= (longlong) options->def_value; - break; - case GET_ULL: - if (options->u_max_value) - *((ulonglong*) options->u_max_value)= (ulonglong) options->max_value; - *((ulonglong*) options->value)= (ulonglong) options->def_value; - break; - default: /* dummy default to avoid compiler warnings */ - break; - } - } + init_one_value(options, options->value, options->def_value); + if (options->var_type & GET_ASK_ADDR && + (variable= (*getopt_get_addr)("", 0, options))) + init_one_value(options, variable, options->def_value); } } @@ -714,13 +813,15 @@ void my_print_help(const struct my_option *options) { printf("--%s", optp->name); col+= 2 + strlen(optp->name); - if (optp->var_type == GET_STR || optp->var_type == GET_STR_ALLOC) + if ((optp->var_type & GET_TYPE_MASK) == GET_STR || + (optp->var_type & GET_TYPE_MASK) == GET_STR_ALLOC) { printf("%s=name%s ", optp->arg_type == OPT_ARG ? "[" : "", optp->arg_type == OPT_ARG ? "]" : ""); col+= (optp->arg_type == OPT_ARG) ? 8 : 6; } - else if (optp->var_type == GET_NO_ARG || optp->var_type == GET_BOOL) + else if ((optp->var_type & GET_TYPE_MASK) == GET_NO_ARG || + (optp->var_type & GET_TYPE_MASK) == GET_BOOL) { putchar(' '); col++; @@ -777,41 +878,44 @@ void my_print_variables(const struct my_option *options) printf("--------------------------------- -----------------------------\n"); for (optp= options; optp->id; optp++) { - if (optp->value) + gptr *value= (optp->var_type & GET_ASK_ADDR ? + (*getopt_get_addr)("", 0, optp) : optp->value); + if (value) { printf("%s", optp->name); length= strlen(optp->name); for (; length < name_space; length++) putchar(' '); - switch (optp->var_type) { + switch ((optp->var_type & GET_TYPE_MASK)) { case GET_STR: case GET_STR_ALLOC: /* fall through */ - printf("%s\n", *((char**) optp->value) ? *((char**) optp->value) : + printf("%s\n", *((char**) value) ? *((char**) value) : "(No default value)"); break; case GET_BOOL: - printf("%s\n", *((my_bool*) optp->value) ? "TRUE" : "FALSE"); + printf("%s\n", *((my_bool*) value) ? "TRUE" : "FALSE"); break; case GET_INT: - printf("%d\n", *((int*) optp->value)); + printf("%d\n", *((int*) value)); break; case GET_UINT: - printf("%d\n", *((uint*) optp->value)); + printf("%d\n", *((uint*) value)); break; case GET_LONG: - printf("%lu\n", *((long*) optp->value)); + printf("%lu\n", *((long*) value)); break; case GET_ULONG: - printf("%lu\n", *((ulong*) optp->value)); + printf("%lu\n", *((ulong*) value)); break; case GET_LL: - printf("%s\n", llstr(*((longlong*) optp->value), buff)); + printf("%s\n", llstr(*((longlong*) value), buff)); break; case GET_ULL: - longlong2str(*((ulonglong*) optp->value), buff, 10); + longlong2str(*((ulonglong*) value), buff, 10); printf("%s\n", buff); break; - default: /* dummy default to avoid compiler warnings */ + default: + printf("(Disabled)\n"); break; } } |