mySQL 5.0.11 sources for tomato
[tomato.git] / release / src / router / mysql / mysys / my_getopt.c
bloba1669110219a4d93828dc8d08b85710c8b15b001
1 /*
2 Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; version 2 of the License.
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
13 You should have received a copy of the GNU General Public License
14 along with this program; if not, write to the Free Software
15 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 #include <my_global.h>
19 #include <m_string.h>
20 #include <stdlib.h>
21 #include <my_sys.h>
22 #include <mysys_err.h>
23 #include <my_getopt.h>
24 #include <errno.h>
25 #include <m_string.h>
27 typedef void (*init_func_p)(const struct my_option *option, void *variable,
28 longlong value);
30 static void default_reporter(enum loglevel level, const char *format, ...);
31 my_error_reporter my_getopt_error_reporter= &default_reporter;
33 static int findopt(char *optpat, uint length,
34 const struct my_option **opt_res,
35 const char **ffname);
36 my_bool getopt_compare_strings(const char *s,
37 const char *t,
38 uint length);
39 static longlong getopt_ll(char *arg, const struct my_option *optp, int *err);
40 static ulonglong getopt_ull(char *arg, const struct my_option *optp,
41 int *err);
42 static double getopt_double(char *arg, const struct my_option *optp, int *err);
43 static void init_variables(const struct my_option *options,
44 init_func_p init_one_value);
45 static void init_one_value(const struct my_option *option, void *variable,
46 longlong value);
47 static void fini_one_value(const struct my_option *option, void *variable,
48 longlong value);
49 static int setval(const struct my_option *opts, void *value, char *argument,
50 my_bool set_maximum_value);
51 static char *check_struct_option(char *cur_arg, char *key_name);
54 The following three variables belong to same group and the number and
55 order of their arguments must correspond to each other.
57 static const char *special_opt_prefix[]=
58 {"skip", "disable", "enable", "maximum", "loose", 0};
59 static const uint special_opt_prefix_lengths[]=
60 { 4, 7, 6, 7, 5, 0};
61 enum enum_special_opt
62 { OPT_SKIP, OPT_DISABLE, OPT_ENABLE, OPT_MAXIMUM, OPT_LOOSE};
64 char *disabled_my_option= (char*) "0";
66 /*
67 This is a flag that can be set in client programs. 0 means that
68 my_getopt will not print error messages, but the client should do
69 it by itself
72 my_bool my_getopt_print_errors= 1;
74 /*
75 This is a flag that can be set in client programs. 1 means that
76 my_getopt will skip over options it does not know how to handle.
79 my_bool my_getopt_skip_unknown= 0;
81 static void default_reporter(enum loglevel level,
82 const char *format, ...)
84 va_list args;
85 va_start(args, format);
86 if (level == WARNING_LEVEL)
87 fprintf(stderr, "%s", "Warning: ");
88 else if (level == INFORMATION_LEVEL)
89 fprintf(stderr, "%s", "Info: ");
90 vfprintf(stderr, format, args);
91 va_end(args);
92 fputc('\n', stderr);
93 fflush(stderr);
96 /*
97 function: handle_options
99 Sort options; put options first, until special end of options (--), or
100 until end of argv. Parse options; check that the given option matches with
101 one of the options in struct 'my_option', return error in case of ambiguous
102 or unknown option. Check that option was given an argument if it requires
103 one. Call function 'get_one_option()' once for each option.
106 static my_getopt_value getopt_get_addr;
108 void my_getopt_register_get_addr(my_getopt_value func_addr)
110 getopt_get_addr= func_addr;
113 int handle_options(int *argc, char ***argv,
114 const struct my_option *longopts,
115 my_get_one_option get_one_option)
117 uint UNINIT_VAR(opt_found), argvpos= 0, length;
118 my_bool end_of_options= 0, must_be_var, set_maximum_value,
119 option_is_loose;
120 char **pos, **pos_end, *optend, *opt_str, key_name[FN_REFLEN];
121 const char *UNINIT_VAR(prev_found);
122 const struct my_option *optp;
123 void *value;
124 int error, i;
126 /* handle_options() assumes arg0 (program name) always exists */
127 DBUG_ASSERT(argc && *argc >= 1);
128 DBUG_ASSERT(argv && *argv);
129 (*argc)--; /* Skip the program name */
130 (*argv)++; /* --- || ---- */
131 init_variables(longopts, init_one_value);
133 for (pos= *argv, pos_end=pos+ *argc; pos != pos_end ; pos++)
135 char **first= pos;
136 char *cur_arg= *pos;
137 if (cur_arg[0] == '-' && cur_arg[1] && !end_of_options) /* must be opt */
139 char *argument= 0;
140 must_be_var= 0;
141 set_maximum_value= 0;
142 option_is_loose= 0;
144 cur_arg++; /* skip '-' */
145 if (*cur_arg == '-' || *cur_arg == 'O') /* check for long option, */
146 { /* --set-variable, or -O */
147 if (*cur_arg == 'O')
149 my_getopt_error_reporter(WARNING_LEVEL,
150 "%s: Option '-O' is deprecated. "
151 "Use --variable-name=value instead.",
152 my_progname);
153 must_be_var= 1;
155 if (!(*++cur_arg)) /* If not -Ovar=# */
157 /* the argument must be in next argv */
158 if (!*++pos)
160 if (my_getopt_print_errors)
161 my_getopt_error_reporter(ERROR_LEVEL,
162 "%s: Option '-O' requires an argument",
163 my_progname);
164 return EXIT_ARGUMENT_REQUIRED;
166 cur_arg= *pos;
167 (*argc)--;
170 else if (!getopt_compare_strings(cur_arg, "-set-variable", 13))
172 my_getopt_error_reporter(WARNING_LEVEL,
173 "%s: Option '--set-variable' is deprecated. "
174 "Use --variable-name=value instead.",
175 my_progname);
177 must_be_var= 1;
178 if (cur_arg[13] == '=')
180 cur_arg+= 14;
181 if (!*cur_arg)
183 if (my_getopt_print_errors)
184 my_getopt_error_reporter(ERROR_LEVEL,
185 "%s: Option '--set-variable' requires an argument",
186 my_progname);
187 return EXIT_ARGUMENT_REQUIRED;
190 else if (cur_arg[14]) /* garbage, or another option. break out */
191 must_be_var= 0;
192 else
194 /* the argument must be in next argv */
195 if (!*++pos)
197 if (my_getopt_print_errors)
198 my_getopt_error_reporter(ERROR_LEVEL,
199 "%s: Option '--set-variable' requires an argument",
200 my_progname);
201 return EXIT_ARGUMENT_REQUIRED;
203 cur_arg= *pos;
204 (*argc)--;
207 else if (!must_be_var)
209 if (!*++cur_arg) /* skip the double dash */
211 /* '--' means end of options, look no further */
212 end_of_options= 1;
213 (*argc)--;
214 continue;
217 opt_str= check_struct_option(cur_arg, key_name);
218 optend= strcend(opt_str, '=');
219 length= (uint) (optend - opt_str);
220 if (*optend == '=')
221 optend++;
222 else
223 optend= 0;
226 Find first the right option. Return error in case of an ambiguous,
227 or unknown option
229 optp= longopts;
230 if (!(opt_found= findopt(opt_str, length, &optp, &prev_found)))
233 Didn't find any matching option. Let's see if someone called
234 option with a special option prefix
236 if (!must_be_var)
238 if (optend)
239 must_be_var= 1; /* option is followed by an argument */
240 for (i= 0; special_opt_prefix[i]; i++)
242 if (!getopt_compare_strings(special_opt_prefix[i], opt_str,
243 special_opt_prefix_lengths[i]) &&
244 (opt_str[special_opt_prefix_lengths[i]] == '-' ||
245 opt_str[special_opt_prefix_lengths[i]] == '_'))
248 We were called with a special prefix, we can reuse opt_found
250 opt_str+= special_opt_prefix_lengths[i] + 1;
251 length-= special_opt_prefix_lengths[i] + 1;
252 if (i == OPT_LOOSE)
253 option_is_loose= 1;
254 if ((opt_found= findopt(opt_str, length, &optp, &prev_found)))
256 if (opt_found > 1)
258 if (my_getopt_print_errors)
259 my_getopt_error_reporter(ERROR_LEVEL,
260 "%s: ambiguous option '--%s-%s' (--%s-%s)",
261 my_progname, special_opt_prefix[i],
262 cur_arg, special_opt_prefix[i],
263 prev_found);
264 return EXIT_AMBIGUOUS_OPTION;
266 switch (i) {
267 case OPT_SKIP:
268 case OPT_DISABLE: /* fall through */
270 double negation is actually enable again,
271 for example: --skip-option=0 -> option = TRUE
273 optend= (optend && *optend == '0' && !(*(optend + 1))) ?
274 (char*) "1" : disabled_my_option;
275 break;
276 case OPT_ENABLE:
277 optend= (optend && *optend == '0' && !(*(optend + 1))) ?
278 disabled_my_option : (char*) "1";
279 break;
280 case OPT_MAXIMUM:
281 set_maximum_value= 1;
282 must_be_var= 1;
283 break;
285 break; /* break from the inner loop, main loop continues */
287 i= -1; /* restart the loop */
291 if (!opt_found)
293 if (my_getopt_skip_unknown)
296 preserve all the components of this unknown option, this may
297 occurr when the user provides options like: "-O foo" or
298 "--set-variable foo" (note that theres a space in there)
299 Generally, these kind of options are to be avoided
301 do {
302 (*argv)[argvpos++]= *first++;
303 } while (first <= pos);
304 continue;
306 if (must_be_var)
308 if (my_getopt_print_errors)
309 my_getopt_error_reporter(option_is_loose ?
310 WARNING_LEVEL : ERROR_LEVEL,
311 "%s: unknown variable '%s'",
312 my_progname, cur_arg);
313 if (!option_is_loose)
314 return EXIT_UNKNOWN_VARIABLE;
316 else
318 if (my_getopt_print_errors)
319 my_getopt_error_reporter(option_is_loose ?
320 WARNING_LEVEL : ERROR_LEVEL,
321 "%s: unknown option '--%s'",
322 my_progname, cur_arg);
323 if (!option_is_loose)
324 return EXIT_UNKNOWN_OPTION;
326 if (option_is_loose)
328 (*argc)--;
329 continue;
333 if (opt_found > 1)
335 if (must_be_var)
337 if (my_getopt_print_errors)
338 my_getopt_error_reporter(ERROR_LEVEL,
339 "%s: variable prefix '%s' is not unique",
340 my_progname, opt_str);
341 return EXIT_VAR_PREFIX_NOT_UNIQUE;
343 else
345 if (my_getopt_print_errors)
346 my_getopt_error_reporter(ERROR_LEVEL,
347 "%s: ambiguous option '--%s' (%s, %s)",
348 my_progname, opt_str, prev_found,
349 optp->name);
350 return EXIT_AMBIGUOUS_OPTION;
353 if ((optp->var_type & GET_TYPE_MASK) == GET_DISABLED)
355 if (my_getopt_print_errors)
356 fprintf(stderr,
357 "%s: %s: Option '%s' used, but is disabled\n", my_progname,
358 option_is_loose ? "WARNING" : "ERROR", opt_str);
359 if (option_is_loose)
361 (*argc)--;
362 continue;
364 return EXIT_OPTION_DISABLED;
366 if (must_be_var && (optp->var_type & GET_TYPE_MASK) == GET_NO_ARG)
368 if (my_getopt_print_errors)
369 my_getopt_error_reporter(ERROR_LEVEL,
370 "%s: option '%s' cannot take an argument",
371 my_progname, optp->name);
372 return EXIT_NO_ARGUMENT_ALLOWED;
374 error= 0;
375 value= optp->var_type & GET_ASK_ADDR ?
376 (*getopt_get_addr)(key_name, (uint) strlen(key_name), optp, &error) :
377 optp->value;
378 if (error)
379 return error;
381 if (optp->arg_type == NO_ARG)
383 if (optend && (optp->var_type & GET_TYPE_MASK) != GET_BOOL)
385 if (my_getopt_print_errors)
386 my_getopt_error_reporter(ERROR_LEVEL,
387 "%s: option '--%s' cannot take an argument",
388 my_progname, optp->name);
389 return EXIT_NO_ARGUMENT_ALLOWED;
391 if ((optp->var_type & GET_TYPE_MASK) == GET_BOOL)
394 Set bool to 1 if no argument or if the user has used
395 --enable-'option-name'.
396 *optend was set to '0' if one used --disable-option
398 (*argc)--;
399 if (!optend || *optend == '1' ||
400 !my_strcasecmp(&my_charset_latin1, optend, "true"))
401 *((my_bool*) value)= (my_bool) 1;
402 else if (*optend == '0' ||
403 !my_strcasecmp(&my_charset_latin1, optend, "false"))
404 *((my_bool*) value)= (my_bool) 0;
405 else
407 my_getopt_error_reporter(WARNING_LEVEL,
408 "%s: ignoring option '--%s' due to "
409 "invalid value '%s'",
410 my_progname, optp->name, optend);
411 continue;
413 if (get_one_option(optp->id, optp,
414 *((my_bool*) value) ?
415 (char*) "1" : disabled_my_option))
416 return EXIT_ARGUMENT_INVALID;
417 continue;
419 argument= optend;
421 else if (optp->arg_type == OPT_ARG &&
422 (((optp->var_type & GET_TYPE_MASK) == GET_BOOL) ||
423 (optp->var_type & GET_TYPE_MASK) == GET_ENUM))
425 if (optend == disabled_my_option)
426 init_one_value(optp, value, 0);
427 else
429 if (!optend) /* No argument -> enable option */
430 init_one_value(optp, value, 1);
431 else
432 argument= optend;
435 else if (optp->arg_type == REQUIRED_ARG && !optend)
437 /* Check if there are more arguments after this one */
438 if (!*++pos)
440 if (my_getopt_print_errors)
441 my_getopt_error_reporter(ERROR_LEVEL,
442 "%s: option '--%s' requires an argument",
443 my_progname, optp->name);
444 return EXIT_ARGUMENT_REQUIRED;
446 argument= *pos;
447 (*argc)--;
449 else
450 argument= optend;
452 else /* must be short option */
454 for (optend= cur_arg; *optend; optend++)
456 opt_found= 0;
457 for (optp= longopts; optp->id; optp++)
459 if (optp->id == (int) (uchar) *optend)
461 /* Option recognized. Find next what to do with it */
462 opt_found= 1;
463 if ((optp->var_type & GET_TYPE_MASK) == GET_DISABLED)
465 if (my_getopt_print_errors)
466 fprintf(stderr,
467 "%s: ERROR: Option '-%c' used, but is disabled\n",
468 my_progname, optp->id);
469 return EXIT_OPTION_DISABLED;
471 if ((optp->var_type & GET_TYPE_MASK) == GET_BOOL &&
472 optp->arg_type == NO_ARG)
474 *((my_bool*) optp->value)= (my_bool) 1;
475 if (get_one_option(optp->id, optp, argument))
476 return EXIT_UNSPECIFIED_ERROR;
477 continue;
479 else if (optp->arg_type == REQUIRED_ARG ||
480 optp->arg_type == OPT_ARG)
482 if (*(optend + 1))
484 /* The rest of the option is option argument */
485 argument= optend + 1;
486 /* This is in effect a jump out of the outer loop */
487 optend= (char*) " ";
489 else
491 if (optp->arg_type == OPT_ARG)
493 if (optp->var_type == GET_BOOL)
494 *((my_bool*) optp->value)= (my_bool) 1;
495 if (get_one_option(optp->id, optp, argument))
496 return EXIT_UNSPECIFIED_ERROR;
497 continue;
499 /* Check if there are more arguments after this one */
500 if (!pos[1])
502 if (my_getopt_print_errors)
503 my_getopt_error_reporter(ERROR_LEVEL,
504 "%s: option '-%c' requires an argument",
505 my_progname, optp->id);
506 return EXIT_ARGUMENT_REQUIRED;
508 argument= *++pos;
509 (*argc)--;
510 /* the other loop will break, because *optend + 1 == 0 */
513 if ((error= setval(optp, optp->value, argument,
514 set_maximum_value)))
516 my_getopt_error_reporter(ERROR_LEVEL,
517 "%s: Error while setting value '%s' to '%s'",
518 my_progname, argument, optp->name);
519 return error;
521 if (get_one_option(optp->id, optp, argument))
522 return EXIT_UNSPECIFIED_ERROR;
523 break;
526 if (!opt_found)
528 if (my_getopt_print_errors)
529 my_getopt_error_reporter(ERROR_LEVEL,
530 "%s: unknown option '-%c'",
531 my_progname, *optend);
532 return EXIT_UNKNOWN_OPTION;
535 (*argc)--; /* option handled (short), decrease argument count */
536 continue;
538 if ((error= setval(optp, value, argument, set_maximum_value)))
540 my_getopt_error_reporter(ERROR_LEVEL,
541 "%s: Error while setting value '%s' to '%s'",
542 my_progname, argument, optp->name);
543 return error;
545 if (get_one_option(optp->id, optp, argument))
546 return EXIT_UNSPECIFIED_ERROR;
548 (*argc)--; /* option handled (short or long), decrease argument count */
550 else /* non-option found */
551 (*argv)[argvpos++]= cur_arg;
554 Destroy the first, already handled option, so that programs that look
555 for arguments in 'argv', without checking 'argc', know when to stop.
556 Items in argv, before the destroyed one, are all non-option -arguments
557 to the program, yet to be (possibly) handled.
559 (*argv)[argvpos]= 0;
560 return 0;
565 function: check_struct_option
567 Arguments: Current argument under processing from argv and a variable
568 where to store the possible key name.
570 Return value: In case option is a struct option, returns a pointer to
571 the current argument at the position where the struct option (key_name)
572 ends, the next character after the dot. In case argument is not a struct
573 option, returns a pointer to the argument.
575 key_name will hold the name of the key, or 0 if not found.
578 static char *check_struct_option(char *cur_arg, char *key_name)
580 char *ptr, *end;
582 ptr= strcend(cur_arg + 1, '.'); /* Skip the first character */
583 end= strcend(cur_arg, '=');
586 If the first dot is after an equal sign, then it is part
587 of a variable value and the option is not a struct option.
588 Also, if the last character in the string before the ending
589 NULL, or the character right before equal sign is the first
590 dot found, the option is not a struct option.
592 if (end - ptr > 1)
594 uint len= (uint) (ptr - cur_arg);
595 set_if_smaller(len, FN_REFLEN-1);
596 strmake(key_name, cur_arg, len);
597 return ++ptr;
599 else
601 key_name[0]= 0;
602 return cur_arg;
607 function: setval
609 Arguments: opts, argument
610 Will set the option value to given value
613 static int setval(const struct my_option *opts, void *value, char *argument,
614 my_bool set_maximum_value)
616 int err= 0;
618 if (value && argument)
620 void *result_pos= ((set_maximum_value) ? opts->u_max_value : value);
622 if (!result_pos)
623 return EXIT_NO_PTR_TO_VARIABLE;
625 switch ((opts->var_type & GET_TYPE_MASK)) {
626 case GET_BOOL: /* If argument differs from 0, enable option, else disable */
627 *((my_bool*) result_pos)= (my_bool) atoi(argument) != 0;
628 break;
629 case GET_INT:
630 *((int*) result_pos)= (int) getopt_ll(argument, opts, &err);
631 break;
632 case GET_UINT:
633 *((uint*) result_pos)= (uint) getopt_ull(argument, opts, &err);
634 break;
635 case GET_LONG:
636 *((long*) result_pos)= (long) getopt_ll(argument, opts, &err);
637 break;
638 case GET_ULONG:
639 *((long*) result_pos)= (long) getopt_ull(argument, opts, &err);
640 break;
641 case GET_LL:
642 *((longlong*) result_pos)= getopt_ll(argument, opts, &err);
643 break;
644 case GET_ULL:
645 *((ulonglong*) result_pos)= getopt_ull(argument, opts, &err);
646 break;
647 case GET_DOUBLE:
648 *((double*) result_pos)= getopt_double(argument, opts, &err);
649 break;
650 case GET_STR:
651 *((char**) result_pos)= argument;
652 break;
653 case GET_STR_ALLOC:
654 if ((*((char**) result_pos)))
655 my_free((*(char**) result_pos), MYF(MY_WME | MY_FAE));
656 if (!(*((char**) result_pos)= my_strdup(argument, MYF(MY_WME))))
657 return EXIT_OUT_OF_MEMORY;
658 break;
659 case GET_ENUM:
661 int type= find_type(argument, opts->typelib, 2);
662 if (type < 1)
665 Accept an integer representation of the enumerated item.
667 char *endptr;
668 ulong arg= strtoul(argument, &endptr, 10);
669 if (*endptr || arg >= opts->typelib->count)
670 return EXIT_ARGUMENT_INVALID;
671 *((ulong*) result_pos)= arg;
673 else
674 *((ulong*) result_pos)= type - 1;
676 break;
677 case GET_SET:
678 *((ulonglong*)result_pos)= find_typeset(argument, opts->typelib, &err);
679 if (err)
680 return EXIT_ARGUMENT_INVALID;
681 break;
682 default: /* dummy default to avoid compiler warnings */
683 break;
685 if (err)
686 return EXIT_UNKNOWN_SUFFIX;
688 return 0;
693 Find option
695 SYNOPSIS
696 findopt()
697 optpat Prefix of option to find (with - or _)
698 length Length of optpat
699 opt_res Options
700 ffname Place for pointer to first found name
702 IMPLEMENTATION
703 Go through all options in the my_option struct. Return number
704 of options found that match the pattern and in the argument
705 list the option found, if any. In case of ambiguous option, store
706 the name in ffname argument
708 RETURN
709 0 No matching options
710 # Number of matching options
711 ffname points to first matching option
714 static int findopt(char *optpat, uint length,
715 const struct my_option **opt_res,
716 const char **ffname)
718 uint count;
719 const struct my_option *opt= *opt_res;
721 for (count= 0; opt->name; opt++)
723 if (!getopt_compare_strings(opt->name, optpat, length)) /* match found */
725 (*opt_res)= opt;
726 if (!opt->name[length]) /* Exact match */
727 return 1;
728 if (!count)
730 /* We only need to know one prev */
731 count= 1;
732 *ffname= opt->name;
734 else if (strcmp(*ffname, opt->name))
737 The above test is to not count same option twice
738 (see mysql.cc, option "help")
740 count++;
744 return count;
749 function: compare_strings
751 Works like strncmp, other than 1.) considers '-' and '_' the same.
752 2.) Returns -1 if strings differ, 0 if they are equal
755 my_bool getopt_compare_strings(register const char *s, register const char *t,
756 uint length)
758 char const *end= s + length;
759 for (;s != end ; s++, t++)
761 if ((*s != '-' ? *s : '_') != (*t != '-' ? *t : '_'))
762 return 1;
764 return 0;
768 function: eval_num_suffix
770 Transforms a number with a suffix to real number. Suffix can
771 be k|K for kilo, m|M for mega or g|G for giga.
774 static longlong eval_num_suffix(char *argument, int *error, char *option_name)
776 char *endchar;
777 longlong num;
779 *error= 0;
780 errno= 0;
781 num= strtoll(argument, &endchar, 10);
782 if (errno == ERANGE)
784 my_getopt_error_reporter(ERROR_LEVEL,
785 "Incorrect integer value: '%s'", argument);
786 *error= 1;
787 return 0;
789 if (*endchar == 'k' || *endchar == 'K')
790 num*= 1024L;
791 else if (*endchar == 'm' || *endchar == 'M')
792 num*= 1024L * 1024L;
793 else if (*endchar == 'g' || *endchar == 'G')
794 num*= 1024L * 1024L * 1024L;
795 else if (*endchar)
797 fprintf(stderr,
798 "Unknown suffix '%c' used for variable '%s' (value '%s')\n",
799 *endchar, option_name, argument);
800 *error= 1;
801 return 0;
803 return num;
807 function: getopt_ll
809 Evaluates and returns the value that user gave as an argument
810 to a variable. Recognizes (case insensitive) K as KILO, M as MEGA
811 and G as GIGA bytes. Some values must be in certain blocks, as
812 defined in the given my_option struct, this function will check
813 that those values are honored.
814 In case of an error, set error value in *err.
817 static longlong getopt_ll(char *arg, const struct my_option *optp, int *err)
819 longlong num=eval_num_suffix(arg, err, (char*) optp->name);
820 return getopt_ll_limit_value(num, optp, NULL);
824 function: getopt_ll_limit_value
826 Applies min/max/block_size to a numeric value of an option.
827 Returns "fixed" value.
830 longlong getopt_ll_limit_value(longlong num, const struct my_option *optp,
831 my_bool *fix)
833 longlong old= num;
834 my_bool adjusted= FALSE;
835 char buf1[255], buf2[255];
836 ulonglong block_size= (optp->block_size ? (ulonglong) optp->block_size : 1L);
838 if (num > 0 && ((ulonglong) num > (ulonglong) optp->max_value) &&
839 optp->max_value) /* if max value is not set -> no upper limit */
841 num= (ulonglong) optp->max_value;
842 adjusted= TRUE;
845 switch ((optp->var_type & GET_TYPE_MASK)) {
846 case GET_INT:
847 if (num > (longlong) INT_MAX)
849 num= ((longlong) INT_MAX);
850 adjusted= TRUE;
852 break;
853 case GET_LONG:
854 #if SIZEOF_LONG < SIZEOF_LONG_LONG
855 if (num > (longlong) LONG_MAX)
857 num= ((longlong) LONG_MAX);
858 adjusted= TRUE;
860 #endif
861 break;
862 default:
863 DBUG_ASSERT((optp->var_type & GET_TYPE_MASK) == GET_LL);
864 break;
867 num= ((num - optp->sub_size) / block_size);
868 num= (longlong) (num * block_size);
870 if (num < optp->min_value)
872 num= optp->min_value;
873 if (old < optp->min_value)
874 adjusted= TRUE;
877 if (fix)
878 *fix= adjusted;
879 else if (adjusted)
880 my_getopt_error_reporter(WARNING_LEVEL,
881 "option '%s': signed value %s adjusted to %s",
882 optp->name, llstr(old, buf1), llstr(num, buf2));
883 return num;
887 function: getopt_ull
889 This is the same as getopt_ll, but is meant for unsigned long long
890 values.
893 static ulonglong getopt_ull(char *arg, const struct my_option *optp, int *err)
895 ulonglong num= eval_num_suffix(arg, err, (char*) optp->name);
896 return getopt_ull_limit_value(num, optp, NULL);
900 ulonglong getopt_ull_limit_value(ulonglong num, const struct my_option *optp,
901 my_bool *fix)
903 my_bool adjusted= FALSE;
904 ulonglong old= num;
905 char buf1[255], buf2[255];
907 if ((ulonglong) num > (ulonglong) optp->max_value &&
908 optp->max_value) /* if max value is not set -> no upper limit */
910 num= (ulonglong) optp->max_value;
911 adjusted= TRUE;
914 switch ((optp->var_type & GET_TYPE_MASK)) {
915 case GET_UINT:
916 if (num > (ulonglong) UINT_MAX)
918 num= ((ulonglong) UINT_MAX);
919 adjusted= TRUE;
921 break;
922 case GET_ULONG:
923 #if SIZEOF_LONG < SIZEOF_LONG_LONG
924 if (num > (ulonglong) ULONG_MAX)
926 num= ((ulonglong) ULONG_MAX);
927 adjusted= TRUE;
929 #endif
930 break;
931 default:
932 DBUG_ASSERT((optp->var_type & GET_TYPE_MASK) == GET_ULL);
933 break;
936 if (optp->block_size > 1)
938 num/= (ulonglong) optp->block_size;
939 num*= (ulonglong) optp->block_size;
942 if (num < (ulonglong) optp->min_value)
944 num= (ulonglong) optp->min_value;
945 if (old < (ulonglong) optp->min_value)
946 adjusted= TRUE;
949 if (fix)
950 *fix= adjusted;
951 else if (adjusted)
952 my_getopt_error_reporter(WARNING_LEVEL,
953 "option '%s': unsigned value %s adjusted to %s",
954 optp->name, ullstr(old, buf1), ullstr(num, buf2));
956 return num;
961 Get double value withing ranges
963 Evaluates and returns the value that user gave as an argument to a variable.
965 RETURN
966 decimal value of arg
968 In case of an error, prints an error message and sets *err to
969 EXIT_ARGUMENT_INVALID. Otherwise err is not touched
972 static double getopt_double(char *arg, const struct my_option *optp, int *err)
974 double num;
975 int error;
976 char *end= arg + 1000; /* Big enough as *arg is \0 terminated */
977 num= my_strtod(arg, &end, &error);
978 if (end[0] != 0 || error)
980 fprintf(stderr,
981 "%s: ERROR: Invalid decimal value for option '%s'\n",
982 my_progname, optp->name);
983 *err= EXIT_ARGUMENT_INVALID;
984 return 0.0;
986 if (optp->max_value && num > (double) optp->max_value)
987 num= (double) optp->max_value;
988 return max(num, (double) optp->min_value);
992 Init one value to it's default values
994 SYNOPSIS
995 init_one_value()
996 option Option to initialize
997 value Pointer to variable
1000 static void init_one_value(const struct my_option *option, void *variable,
1001 longlong value)
1003 DBUG_ENTER("init_one_value");
1004 switch ((option->var_type & GET_TYPE_MASK)) {
1005 case GET_BOOL:
1006 *((my_bool*) variable)= (my_bool) value;
1007 break;
1008 case GET_INT:
1009 *((int*) variable)= (int) getopt_ll_limit_value((int) value, option, NULL);
1010 break;
1011 case GET_ENUM:
1012 *((ulong*) variable)= (ulong) value;
1013 break;
1014 case GET_UINT:
1015 *((uint*) variable)= (uint) getopt_ull_limit_value((uint) value, option, NULL);
1016 break;
1017 case GET_LONG:
1018 *((long*) variable)= (long) getopt_ll_limit_value((long) value, option, NULL);
1019 break;
1020 case GET_ULONG:
1021 *((ulong*) variable)= (ulong) getopt_ull_limit_value((ulong) value, option, NULL);
1022 break;
1023 case GET_LL:
1024 *((longlong*) variable)= (longlong) getopt_ll_limit_value((longlong) value, option, NULL);
1025 break;
1026 case GET_ULL:
1027 *((ulonglong*) variable)= (ulonglong) getopt_ull_limit_value((ulonglong) value, option, NULL);
1028 break;
1029 case GET_SET:
1030 *((ulonglong*) variable)= (ulonglong) value;
1031 break;
1032 case GET_DOUBLE:
1033 *((double*) variable)= (double) value;
1034 break;
1035 case GET_STR:
1037 Do not clear variable value if it has no default value.
1038 The default value may already be set.
1039 NOTE: To avoid compiler warnings, we first cast longlong to intptr,
1040 so that the value has the same size as a pointer.
1042 if ((char*) (intptr) value)
1043 *((char**) variable)= (char*) (intptr) value;
1044 break;
1045 case GET_STR_ALLOC:
1047 Do not clear variable value if it has no default value.
1048 The default value may already be set.
1049 NOTE: To avoid compiler warnings, we first cast longlong to intptr,
1050 so that the value has the same size as a pointer.
1052 if ((char*) (intptr) value)
1054 my_free((*(char**) variable), MYF(MY_ALLOW_ZERO_PTR));
1055 *((char**) variable)= my_strdup((char*) (intptr) value, MYF(MY_WME));
1057 break;
1058 default: /* dummy default to avoid compiler warnings */
1059 break;
1061 DBUG_VOID_RETURN;
1066 Init one value to it's default values
1068 SYNOPSIS
1069 init_one_value()
1070 option Option to initialize
1071 value Pointer to variable
1074 static void fini_one_value(const struct my_option *option, void *variable,
1075 longlong value __attribute__ ((unused)))
1077 DBUG_ENTER("fini_one_value");
1078 switch ((option->var_type & GET_TYPE_MASK)) {
1079 case GET_STR_ALLOC:
1080 my_free((*(char**) variable), MYF(MY_ALLOW_ZERO_PTR));
1081 *((char**) variable)= NULL;
1082 break;
1083 default: /* dummy default to avoid compiler warnings */
1084 break;
1086 DBUG_VOID_RETURN;
1090 void my_cleanup_options(const struct my_option *options)
1092 init_variables(options, fini_one_value);
1097 initialize all variables to their default values
1099 SYNOPSIS
1100 init_variables()
1101 options Array of options
1103 NOTES
1104 We will initialize the value that is pointed to by options->value.
1105 If the value is of type GET_ASK_ADDR, we will also ask for the address
1106 for a value and initialize.
1109 static void init_variables(const struct my_option *options,
1110 init_func_p init_one_value)
1112 DBUG_ENTER("init_variables");
1113 for (; options->name; options++)
1115 void *variable;
1116 DBUG_PRINT("options", ("name: '%s'", options->name));
1118 We must set u_max_value first as for some variables
1119 options->u_max_value == options->value and in this case we want to
1120 set the value to default value.
1122 if (options->u_max_value)
1123 init_one_value(options, options->u_max_value, options->max_value);
1124 if (options->value)
1125 init_one_value(options, options->value, options->def_value);
1126 if (options->var_type & GET_ASK_ADDR &&
1127 (variable= (*getopt_get_addr)("", 0, options, 0)))
1128 init_one_value(options, variable, options->def_value);
1130 DBUG_VOID_RETURN;
1135 function: my_print_options
1137 Print help for all options and variables.
1140 #include <help_start.h>
1142 void my_print_help(const struct my_option *options)
1144 uint col, name_space= 22, comment_space= 57;
1145 const char *line_end;
1146 const struct my_option *optp;
1148 for (optp= options; optp->id; optp++)
1150 if (optp->id < 256)
1152 printf(" -%c%s", optp->id, strlen(optp->name) ? ", " : " ");
1153 col= 6;
1155 else
1157 printf(" ");
1158 col= 2;
1160 if (strlen(optp->name))
1162 printf("--%s", optp->name);
1163 col+= 2 + (uint) strlen(optp->name);
1164 if ((optp->var_type & GET_TYPE_MASK) == GET_STR ||
1165 (optp->var_type & GET_TYPE_MASK) == GET_STR_ALLOC)
1167 printf("%s=name%s ", optp->arg_type == OPT_ARG ? "[" : "",
1168 optp->arg_type == OPT_ARG ? "]" : "");
1169 col+= (optp->arg_type == OPT_ARG) ? 8 : 6;
1171 else if ((optp->var_type & GET_TYPE_MASK) == GET_NO_ARG ||
1172 (optp->var_type & GET_TYPE_MASK) == GET_BOOL)
1174 putchar(' ');
1175 col++;
1177 else
1179 printf("%s=#%s ", optp->arg_type == OPT_ARG ? "[" : "",
1180 optp->arg_type == OPT_ARG ? "]" : "");
1181 col+= (optp->arg_type == OPT_ARG) ? 5 : 3;
1183 if (col > name_space && optp->comment && *optp->comment)
1185 putchar('\n');
1186 col= 0;
1189 for (; col < name_space; col++)
1190 putchar(' ');
1191 if (optp->comment && *optp->comment)
1193 const char *comment= optp->comment, *end= strend(comment);
1195 while ((uint) (end - comment) > comment_space)
1197 for (line_end= comment + comment_space; *line_end != ' '; line_end--);
1198 for (; comment != line_end; comment++)
1199 putchar(*comment);
1200 comment++; /* skip the space, as a newline will take it's place now */
1201 putchar('\n');
1202 for (col= 0; col < name_space; col++)
1203 putchar(' ');
1205 printf("%s", comment);
1207 putchar('\n');
1213 function: my_print_options
1215 Print variables.
1218 void my_print_variables(const struct my_option *options)
1220 uint name_space= 34, length, nr;
1221 ulonglong bit, llvalue;
1222 char buff[255];
1223 const struct my_option *optp;
1225 printf("\nVariables (--variable-name=value)\n");
1226 printf("and boolean options {FALSE|TRUE} Value (after reading options)\n");
1227 printf("--------------------------------- -----------------------------\n");
1228 for (optp= options; optp->id; optp++)
1230 void *value= (optp->var_type & GET_ASK_ADDR ?
1231 (*getopt_get_addr)("", 0, optp, 0) : optp->value);
1232 if (value)
1234 printf("%s ", optp->name);
1235 length= (uint) strlen(optp->name)+1;
1236 for (; length < name_space; length++)
1237 putchar(' ');
1238 switch ((optp->var_type & GET_TYPE_MASK)) {
1239 case GET_SET:
1240 if (!(llvalue= *(ulonglong*) value))
1241 printf("%s\n", "(No default value)");
1242 else
1243 for (nr= 0, bit= 1; llvalue && nr < optp->typelib->count; nr++, bit<<=1)
1245 if (!(bit & llvalue))
1246 continue;
1247 llvalue&= ~bit;
1248 printf( llvalue ? "%s," : "%s\n", get_type(optp->typelib, nr));
1250 break;
1251 case GET_ENUM:
1252 printf("%s\n", get_type(optp->typelib, *(ulong*) value));
1253 break;
1254 case GET_STR:
1255 case GET_STR_ALLOC: /* fall through */
1256 printf("%s\n", *((char**) value) ? *((char**) value) :
1257 "(No default value)");
1258 break;
1259 case GET_BOOL:
1260 printf("%s\n", *((my_bool*) value) ? "TRUE" : "FALSE");
1261 break;
1262 case GET_INT:
1263 printf("%d\n", *((int*) value));
1264 break;
1265 case GET_UINT:
1266 printf("%d\n", *((uint*) value));
1267 break;
1268 case GET_LONG:
1269 printf("%ld\n", *((long*) value));
1270 break;
1271 case GET_ULONG:
1272 printf("%lu\n", *((ulong*) value));
1273 break;
1274 case GET_LL:
1275 printf("%s\n", llstr(*((longlong*) value), buff));
1276 break;
1277 case GET_ULL:
1278 longlong2str(*((ulonglong*) value), buff, 10);
1279 printf("%s\n", buff);
1280 break;
1281 case GET_DOUBLE:
1282 printf("%g\n", *(double*) value);
1283 break;
1284 default:
1285 printf("(Disabled)\n");
1286 break;
1292 #include <help_end.h>