00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #include <config.h>
00017 #include <drizzled/internal/my_sys.h>
00018 #include <drizzled/gettext.h>
00019
00020 #include <drizzled/internal/m_string.h>
00021 #include <drizzled/internal/my_sys.h>
00022 #include <drizzled/error.h>
00023 #include <drizzled/option.h>
00024 #include <drizzled/typelib.h>
00025
00026 #include <stdio.h>
00027 #include <stdlib.h>
00028 #include <errno.h>
00029 #include <iostream>
00030 #include <algorithm>
00031
00032 using namespace std;
00033 namespace drizzled
00034 {
00035
00036 typedef void (*init_func_p)(const struct option *option, char **variable,
00037 int64_t value);
00038
00039 void default_reporter(enum loglevel level, const char *format, ...);
00040 my_error_reporter my_getopt_error_reporter= &default_reporter;
00041
00042 static int findopt(char *optpat, uint32_t length,
00043 const struct option **opt_res,
00044 char **ffname);
00045 static int64_t getopt_ll(char *arg, const struct option *optp, int *err);
00046 static uint64_t getopt_ull(char *arg, const struct option *optp,
00047 int *err);
00048 static size_t getopt_size(char *arg, const struct option *optp, int *err);
00049 static double getopt_double(char *arg, const struct option *optp, int *err);
00050 static void init_variables(const struct option *options,
00051 init_func_p init_one_value);
00052 static void init_one_value(const struct option *option, char **variable,
00053 int64_t value);
00054 static void fini_one_value(const struct option *option, char **variable,
00055 int64_t value);
00056 static int setval(const struct option *opts, char* *value, char *argument,
00057 bool set_maximum_value);
00058 static char *check_struct_option(char *cur_arg, char *key_name);
00059
00060
00061
00062
00063
00064 static const char *special_opt_prefix[]=
00065 {"skip", "disable", "enable", "maximum", "loose", 0};
00066 static const uint32_t special_opt_prefix_lengths[]=
00067 { 4, 7, 6, 7, 5, 0};
00068 enum enum_special_opt
00069 { OPT_SKIP, OPT_DISABLE, OPT_ENABLE, OPT_MAXIMUM, OPT_LOOSE};
00070
00071 char *disabled_my_option= (char*) "0";
00072
00073
00074
00075
00076
00077
00078 bool my_getopt_skip_unknown= 0;
00079
00080 void default_reporter(enum loglevel level, const char *format, ...)
00081 {
00082 va_list args;
00083 va_start(args, format);
00084 if (level == WARNING_LEVEL)
00085 fprintf(stderr, "%s", _("Warning: "));
00086 else if (level == INFORMATION_LEVEL)
00087 fprintf(stderr, "%s", _("Info: "));
00088 vfprintf(stderr, format, args);
00089 va_end(args);
00090 fputc('\n', stderr);
00091 fflush(stderr);
00092 }
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104 static getopt_get_addr_func getopt_get_addr;
00105
00106 int handle_options(int *argc, char ***argv,
00107 const struct option *longopts,
00108 my_get_one_option get_one_option)
00109 {
00110 uint32_t opt_found, argvpos= 0, length;
00111 bool end_of_options= 0, must_be_var, set_maximum_value=false,
00112 option_is_loose;
00113 char **pos, **pos_end, *optend, *prev_found=NULL,
00114 *opt_str, key_name[FN_REFLEN];
00115 const struct option *optp;
00116 char* *value;
00117 int error, i;
00118
00119
00120 assert(argc && *argc >= 1);
00121 assert(argv && *argv);
00122 (*argc)--;
00123 (*argv)++;
00124 init_variables(longopts, init_one_value);
00125
00126 for (pos= *argv, pos_end=pos+ *argc; pos != pos_end ; pos++)
00127 {
00128 char **first= pos;
00129 char *cur_arg= *pos;
00130 if (cur_arg[0] == '-' && cur_arg[1] && !end_of_options)
00131 {
00132 char *argument= 0;
00133 must_be_var= 0;
00134 set_maximum_value= 0;
00135 option_is_loose= 0;
00136
00137 cur_arg++;
00138 if (*cur_arg == '-' || *cur_arg == 'O')
00139 {
00140 if (*cur_arg == 'O')
00141 {
00142 must_be_var= 1;
00143
00144 if (!(*++cur_arg))
00145 {
00146
00147 if (!*++pos)
00148 {
00149 my_getopt_error_reporter(ERROR_LEVEL,
00150 "%s: Option '-O' requires an argument",
00151 internal::my_progname);
00152 return EXIT_ARGUMENT_REQUIRED;
00153 }
00154 cur_arg= *pos;
00155 (*argc)--;
00156 }
00157 }
00158 else if (!getopt_compare_strings(cur_arg, "-set-variable", 13))
00159 {
00160 must_be_var= 1;
00161 if (cur_arg[13] == '=')
00162 {
00163 cur_arg+= 14;
00164 if (!*cur_arg)
00165 {
00166 my_getopt_error_reporter(ERROR_LEVEL,
00167 "%s: Option '--set-variable' requires an argument",
00168 internal::my_progname);
00169 return EXIT_ARGUMENT_REQUIRED;
00170 }
00171 }
00172 else if (cur_arg[14])
00173 must_be_var= 0;
00174 else
00175 {
00176
00177 if (!*++pos)
00178 {
00179 my_getopt_error_reporter(ERROR_LEVEL,
00180 "%s: Option '--set-variable' requires an argument",
00181 internal::my_progname);
00182 return EXIT_ARGUMENT_REQUIRED;
00183 }
00184 cur_arg= *pos;
00185 (*argc)--;
00186 }
00187 }
00188 else if (!must_be_var)
00189 {
00190 if (!*++cur_arg)
00191 {
00192
00193 end_of_options= 1;
00194 (*argc)--;
00195 continue;
00196 }
00197 }
00198 opt_str= check_struct_option(cur_arg, key_name);
00199 optend= strchr(opt_str, '=');
00200 if (optend != NULL)
00201 {
00202 length= (uint32_t) (optend - opt_str);
00203 optend++;
00204 }
00205 else
00206 {
00207 length= static_cast<uint32_t>(strlen(opt_str));
00208 optend= 0;
00209 }
00210
00211
00212
00213
00214
00215 optp= longopts;
00216 if (!(opt_found= findopt(opt_str, length, &optp, &prev_found)))
00217 {
00218
00219
00220
00221
00222 if (!must_be_var)
00223 {
00224 if (optend)
00225 must_be_var= 1;
00226 for (i= 0; special_opt_prefix[i]; i++)
00227 {
00228 if (!getopt_compare_strings(special_opt_prefix[i], opt_str,
00229 special_opt_prefix_lengths[i]) &&
00230 (opt_str[special_opt_prefix_lengths[i]] == '-' ||
00231 opt_str[special_opt_prefix_lengths[i]] == '_'))
00232 {
00233
00234
00235
00236 opt_str+= special_opt_prefix_lengths[i] + 1;
00237 length-= special_opt_prefix_lengths[i] + 1;
00238 if (i == OPT_LOOSE)
00239 option_is_loose= 1;
00240 if ((opt_found= findopt(opt_str, length, &optp, &prev_found)))
00241 {
00242 if (opt_found > 1)
00243 {
00244 my_getopt_error_reporter(ERROR_LEVEL,
00245 "%s: ambiguous option '--%s-%s' (--%s-%s)",
00246 internal::my_progname,
00247 special_opt_prefix[i],
00248 cur_arg, special_opt_prefix[i],
00249 prev_found);
00250 return EXIT_AMBIGUOUS_OPTION;
00251 }
00252 switch (i) {
00253 case OPT_SKIP:
00254 case OPT_DISABLE:
00255
00256
00257
00258
00259 optend= (optend && *optend == '0' && !(*(optend + 1))) ?
00260 (char*) "1" : disabled_my_option;
00261 break;
00262 case OPT_ENABLE:
00263 optend= (optend && *optend == '0' && !(*(optend + 1))) ?
00264 disabled_my_option : (char*) "1";
00265 break;
00266 case OPT_MAXIMUM:
00267 set_maximum_value= true;
00268 must_be_var= true;
00269 break;
00270 }
00271 break;
00272 }
00273 i= -1;
00274 }
00275 }
00276 }
00277 if (!opt_found)
00278 {
00279 if (my_getopt_skip_unknown)
00280 {
00281
00282
00283
00284
00285
00286
00287 do {
00288 (*argv)[argvpos++]= *first++;
00289 } while (first <= pos);
00290 continue;
00291 }
00292 if (must_be_var)
00293 {
00294 my_getopt_error_reporter(option_is_loose ?
00295 WARNING_LEVEL : ERROR_LEVEL,
00296 "%s: unknown variable '%s'",
00297 internal::my_progname, cur_arg);
00298 if (!option_is_loose)
00299 return EXIT_UNKNOWN_VARIABLE;
00300 }
00301 else
00302 {
00303 my_getopt_error_reporter(option_is_loose ?
00304 WARNING_LEVEL : ERROR_LEVEL,
00305 "%s: unknown option '--%s'",
00306 internal::my_progname, cur_arg);
00307 if (!option_is_loose)
00308 return EXIT_UNKNOWN_OPTION;
00309 }
00310 if (option_is_loose)
00311 {
00312 (*argc)--;
00313 continue;
00314 }
00315 }
00316 }
00317 if (opt_found > 1)
00318 {
00319 if (must_be_var)
00320 {
00321 my_getopt_error_reporter(ERROR_LEVEL,
00322 "%s: variable prefix '%s' is not unique",
00323 internal::my_progname, opt_str);
00324 return EXIT_VAR_PREFIX_NOT_UNIQUE;
00325 }
00326 else
00327 {
00328 my_getopt_error_reporter(ERROR_LEVEL,
00329 "%s: ambiguous option '--%s' (%s, %s)",
00330 internal::my_progname, opt_str, prev_found,
00331 optp->name);
00332 return EXIT_AMBIGUOUS_OPTION;
00333 }
00334 }
00335 if ((optp->var_type & GET_TYPE_MASK) == GET_DISABLED)
00336 {
00337 fprintf(stderr,
00338 _("%s: %s: Option '%s' used, but is disabled\n"),
00339 internal::my_progname,
00340 option_is_loose ? _("WARNING") : _("ERROR"), opt_str);
00341 if (option_is_loose)
00342 {
00343 (*argc)--;
00344 continue;
00345 }
00346 return EXIT_OPTION_DISABLED;
00347 }
00348 if (must_be_var && (optp->var_type & GET_TYPE_MASK) == GET_NO_ARG)
00349 {
00350 my_getopt_error_reporter(ERROR_LEVEL,
00351 "%s: option '%s' cannot take an argument",
00352 internal::my_progname, optp->name);
00353 return EXIT_NO_ARGUMENT_ALLOWED;
00354 }
00355 value= optp->var_type & GET_ASK_ADDR ?
00356 (*getopt_get_addr)(key_name, (uint32_t) strlen(key_name), optp) : optp->value;
00357
00358 if (optp->arg_type == NO_ARG)
00359 {
00360 if (optend && (optp->var_type & GET_TYPE_MASK) != GET_BOOL)
00361 {
00362 my_getopt_error_reporter(ERROR_LEVEL,
00363 "%s: option '--%s' cannot take an argument",
00364 internal::my_progname, optp->name);
00365 return EXIT_NO_ARGUMENT_ALLOWED;
00366 }
00367 if ((optp->var_type & GET_TYPE_MASK) == GET_BOOL)
00368 {
00369
00370
00371
00372
00373
00374 (*argc)--;
00375 if (!optend || *optend == '1' ||
00376 !my_strcasecmp(&my_charset_utf8_general_ci, optend, "true"))
00377 *((bool*) value)= (bool) 1;
00378 else if (*optend == '0' ||
00379 !my_strcasecmp(&my_charset_utf8_general_ci, optend, "false"))
00380 *((bool*) value)= (bool) 0;
00381 else
00382 {
00383 my_getopt_error_reporter(WARNING_LEVEL,
00384 "%s: ignoring option '--%s' due to "
00385 "invalid value '%s'",
00386 internal::my_progname,
00387 optp->name, optend);
00388 continue;
00389 }
00390 error= get_one_option(optp->id, optp, *((bool*) value) ?
00391 (char*) "1" : disabled_my_option);
00392 if (error != 0)
00393 return error;
00394 else
00395 continue;
00396 }
00397 argument= optend;
00398 }
00399 else if (optp->arg_type == OPT_ARG &&
00400 (optp->var_type & GET_TYPE_MASK) == GET_BOOL)
00401 {
00402 if (optend == disabled_my_option)
00403 *((bool*) value)= (bool) 0;
00404 else
00405 {
00406 if (!optend)
00407 *((bool*) value)= (bool) 1;
00408 else
00409 argument= optend;
00410 }
00411 }
00412 else if (optp->arg_type == REQUIRED_ARG && !optend)
00413 {
00414
00415 if (!*++pos)
00416 {
00417 my_getopt_error_reporter(ERROR_LEVEL,
00418 "%s: option '--%s' requires an argument",
00419 internal::my_progname, optp->name);
00420 return EXIT_ARGUMENT_REQUIRED;
00421 }
00422 argument= *pos;
00423 (*argc)--;
00424 }
00425 else
00426 argument= optend;
00427 }
00428 else
00429 {
00430 for (optend= cur_arg; *optend; optend++)
00431 {
00432 opt_found= 0;
00433 for (optp= longopts; optp->id; optp++)
00434 {
00435 if (optp->id == (int) (unsigned char) *optend)
00436 {
00437
00438 opt_found= 1;
00439 if ((optp->var_type & GET_TYPE_MASK) == GET_DISABLED)
00440 {
00441 fprintf(stderr,
00442 _("%s: ERROR: Option '-%c' used, but is disabled\n"),
00443 internal::my_progname, optp->id);
00444 return EXIT_OPTION_DISABLED;
00445 }
00446 if ((optp->var_type & GET_TYPE_MASK) == GET_BOOL &&
00447 optp->arg_type == NO_ARG)
00448 {
00449 *((bool*) optp->value)= (bool) 1;
00450 error= get_one_option(optp->id, optp, argument);
00451 if (error != 0)
00452 return error;
00453 else
00454 continue;
00455
00456 }
00457 else if (optp->arg_type == REQUIRED_ARG ||
00458 optp->arg_type == OPT_ARG)
00459 {
00460 if (*(optend + 1))
00461 {
00462
00463 argument= optend + 1;
00464
00465 optend= (char*) " ";
00466 }
00467 else
00468 {
00469 if (optp->arg_type == OPT_ARG)
00470 {
00471 if (optp->var_type == GET_BOOL)
00472 *((bool*) optp->value)= (bool) 1;
00473 error= get_one_option(optp->id, optp, argument);
00474 if (error != 0)
00475 return error;
00476 else
00477 continue;
00478 }
00479
00480 if (!pos[1])
00481 {
00482 my_getopt_error_reporter(ERROR_LEVEL,
00483 "%s: option '-%c' requires "
00484 "an argument",
00485 internal::my_progname, optp->id);
00486 return EXIT_ARGUMENT_REQUIRED;
00487 }
00488 argument= *++pos;
00489 (*argc)--;
00490
00491 }
00492 }
00493 if ((error= setval(optp, optp->value, argument,
00494 set_maximum_value)))
00495 {
00496 my_getopt_error_reporter(ERROR_LEVEL,
00497 "%s: Error while setting value '%s' "
00498 "to '%s'",
00499 internal::my_progname,
00500 argument, optp->name);
00501 return error;
00502 }
00503 error= get_one_option(optp->id, optp, argument);
00504 if (error != 0)
00505 return error;
00506 else
00507 break;
00508 }
00509 }
00510 if (!opt_found)
00511 {
00512 my_getopt_error_reporter(ERROR_LEVEL,
00513 "%s: unknown option '-%c'",
00514 internal::my_progname, *optend);
00515 return EXIT_UNKNOWN_OPTION;
00516 }
00517 }
00518 (*argc)--;
00519 continue;
00520 }
00521 if ((error= setval(optp, value, argument, set_maximum_value)))
00522 {
00523 my_getopt_error_reporter(ERROR_LEVEL,
00524 "%s: Error while setting value '%s' to '%s'",
00525 internal::my_progname, argument, optp->name);
00526 return error;
00527 }
00528 error= get_one_option(optp->id, optp, argument);
00529 if (error != 0)
00530 return error;
00531
00532 (*argc)--;
00533 }
00534 else
00535 (*argv)[argvpos++]= cur_arg;
00536 }
00537
00538
00539
00540
00541
00542
00543 (*argv)[argvpos]= 0;
00544 return 0;
00545 }
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562 static char *check_struct_option(char *cur_arg, char *key_name)
00563 {
00564 char *ptr, *end;
00565
00566 ptr= NULL;
00567 end= strrchr(cur_arg, '=');
00568
00569
00570
00571
00572
00573
00574
00575
00576 if ((ptr != NULL) && (end != NULL) && (end - ptr > 1))
00577 {
00578 uint32_t len= (uint32_t) (ptr - cur_arg);
00579 set_if_smaller(len, (uint32_t)FN_REFLEN-1);
00580 strncpy(key_name, cur_arg, len);
00581 return ++ptr;
00582 }
00583 key_name[0]= 0;
00584 return cur_arg;
00585 }
00586
00587
00588
00589
00590
00591
00592
00593
00594 static int setval(const struct option *opts, char **value, char *argument,
00595 bool set_maximum_value)
00596 {
00597 int err= 0;
00598
00599 if (value && argument)
00600 {
00601 char* *result_pos= ((set_maximum_value) ?
00602 opts->u_max_value : value);
00603
00604 if (!result_pos)
00605 return EXIT_NO_PTR_TO_VARIABLE;
00606
00607 switch ((opts->var_type & GET_TYPE_MASK)) {
00608 case GET_BOOL:
00609 *((bool*) result_pos)= (bool) atoi(argument) != 0;
00610 break;
00611 case GET_INT:
00612 *((int32_t*) result_pos)= (int) getopt_ll(argument, opts, &err);
00613 break;
00614 case GET_UINT:
00615 case GET_UINT32:
00616 *((uint32_t*) result_pos)= (uint32_t) getopt_ull(argument, opts, &err);
00617 break;
00618 case GET_ULONG_IS_FAIL:
00619 *((ulong*) result_pos)= (ulong) getopt_ull(argument, opts, &err);
00620 break;
00621 case GET_LONG:
00622 *((long*) result_pos)= (long) getopt_ll(argument, opts, &err);
00623 break;
00624 case GET_LL:
00625 *((int64_t*) result_pos)= getopt_ll(argument, opts, &err);
00626 break;
00627 case GET_ULL:
00628 case GET_UINT64:
00629 *((uint64_t*) result_pos)= getopt_ull(argument, opts, &err);
00630 break;
00631 case GET_SIZE:
00632 *((size_t*) result_pos)= getopt_size(argument, opts, &err);
00633 break;
00634 case GET_DOUBLE:
00635 *((double*) result_pos)= getopt_double(argument, opts, &err);
00636 break;
00637 case GET_STR:
00638 *((char**) result_pos)= argument;
00639 break;
00640 case GET_STR_ALLOC:
00641 if ((*((char**) result_pos)))
00642 free((*(char**) result_pos));
00643 if (!(*((char**) result_pos)= strdup(argument)))
00644 return EXIT_OUT_OF_MEMORY;
00645 break;
00646 case GET_ENUM:
00647 if (((*(int*)result_pos)= opts->typelib->find_type(argument, 2) - 1) < 0)
00648 return EXIT_ARGUMENT_INVALID;
00649 break;
00650 case GET_SET:
00651 *((uint64_t*)result_pos)= opts->typelib->find_typeset(argument, &err);
00652 if (err)
00653 return EXIT_ARGUMENT_INVALID;
00654 break;
00655 default:
00656 break;
00657 }
00658 if (err)
00659 return EXIT_UNKNOWN_SUFFIX;
00660 }
00661 return 0;
00662 }
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687 static int findopt(char *optpat, uint32_t length,
00688 const struct option **opt_res,
00689 char **ffname)
00690 {
00691 uint32_t count;
00692 struct option *opt= (struct option *) *opt_res;
00693
00694 for (count= 0; opt->name; opt++)
00695 {
00696 if (!getopt_compare_strings(opt->name, optpat, length))
00697 {
00698 (*opt_res)= opt;
00699 if (!opt->name[length])
00700 return 1;
00701 if (!count)
00702 {
00703 count= 1;
00704 *ffname= (char *) opt->name;
00705 }
00706 else if (strcmp(*ffname, opt->name))
00707 {
00708
00709
00710
00711
00712 count++;
00713 }
00714 }
00715 }
00716 return count;
00717 }
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727 bool getopt_compare_strings(const char *s, const char *t,
00728 uint32_t length)
00729 {
00730 char const *end= s + length;
00731 for (;s != end ; s++, t++)
00732 {
00733 if ((*s != '-' ? *s : '_') != (*t != '-' ? *t : '_'))
00734 return 1;
00735 }
00736 return 0;
00737 }
00738
00739
00740
00741
00742
00743
00744
00745
00746 static int64_t eval_num_suffix(char *argument, int *error, char *option_name)
00747 {
00748 char *endchar;
00749 int64_t num;
00750
00751 *error= 0;
00752 errno= 0;
00753 num= strtoll(argument, &endchar, 10);
00754 if (errno == ERANGE)
00755 {
00756 my_getopt_error_reporter(ERROR_LEVEL,
00757 "Incorrect integer value: '%s'", argument);
00758 *error= 1;
00759 return 0;
00760 }
00761 if (*endchar == 'k' || *endchar == 'K')
00762 num*= 1024L;
00763 else if (*endchar == 'm' || *endchar == 'M')
00764 num*= 1024L * 1024L;
00765 else if (*endchar == 'g' || *endchar == 'G')
00766 num*= 1024L * 1024L * 1024L;
00767 else if (*endchar)
00768 {
00769 fprintf(stderr,
00770 _("Unknown suffix '%c' used for variable '%s' (value '%s')\n"),
00771 *endchar, option_name, argument);
00772 *error= 1;
00773 return 0;
00774 }
00775 return num;
00776 }
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789 static int64_t getopt_ll(char *arg, const struct option *optp, int *err)
00790 {
00791 int64_t num=eval_num_suffix(arg, err, (char*) optp->name);
00792 return getopt_ll_limit_value(num, optp, NULL);
00793 }
00794
00795
00796
00797
00798
00799
00800
00801
00802 int64_t getopt_ll_limit_value(int64_t num, const struct option *optp,
00803 bool *fix)
00804 {
00805 int64_t old= num;
00806 bool adjusted= false;
00807 char buf1[255], buf2[255];
00808 uint64_t block_size= (optp->block_size ? (uint64_t) optp->block_size : 1L);
00809
00810 if (num > 0 && ((uint64_t) num > (uint64_t) optp->max_value) &&
00811 optp->max_value)
00812 {
00813 num= (uint64_t) optp->max_value;
00814 adjusted= true;
00815 }
00816
00817 switch ((optp->var_type & GET_TYPE_MASK)) {
00818 case GET_INT:
00819 if (num > (int64_t) INT_MAX)
00820 {
00821 num= ((int64_t) INT_MAX);
00822 adjusted= true;
00823 }
00824 break;
00825 case GET_LONG:
00826 if (num > (int64_t) INT32_MAX)
00827 {
00828 num= ((int64_t) INT32_MAX);
00829 adjusted= true;
00830 }
00831 break;
00832 default:
00833 assert((optp->var_type & GET_TYPE_MASK) == GET_LL);
00834 break;
00835 }
00836
00837 num= ((num - optp->sub_size) / block_size);
00838 num= (int64_t) (num * block_size);
00839
00840 if (num < optp->min_value)
00841 {
00842 num= optp->min_value;
00843 adjusted= true;
00844 }
00845
00846 if (fix)
00847 *fix= adjusted;
00848 else if (adjusted)
00849 my_getopt_error_reporter(WARNING_LEVEL,
00850 "option '%s': signed value %s adjusted to %s",
00851 optp->name, internal::llstr(old, buf1), internal::llstr(num, buf2));
00852 return num;
00853 }
00854
00855
00856
00857
00858
00859
00860
00861
00862 static uint64_t getopt_ull(char *arg, const struct option *optp, int *err)
00863 {
00864 uint64_t num= eval_num_suffix(arg, err, (char*) optp->name);
00865 return getopt_ull_limit_value(num, optp, NULL);
00866 }
00867
00868
00869 static size_t getopt_size(char *arg, const struct option *optp, int *err)
00870 {
00871 return (size_t)getopt_ull(arg, optp, err);
00872 }
00873
00874
00875
00876 uint64_t getopt_ull_limit_value(uint64_t num, const struct option *optp,
00877 bool *fix)
00878 {
00879 bool adjusted= false;
00880 uint64_t old= num;
00881 char buf1[255], buf2[255];
00882
00883 if ((uint64_t) num > (uint64_t) optp->max_value &&
00884 optp->max_value)
00885 {
00886 num= (uint64_t) optp->max_value;
00887 adjusted= true;
00888 }
00889
00890 switch ((optp->var_type & GET_TYPE_MASK)) {
00891 case GET_UINT:
00892 if (num > (uint64_t) UINT_MAX)
00893 {
00894 num= ((uint64_t) UINT_MAX);
00895 adjusted= true;
00896 }
00897 break;
00898 case GET_UINT32:
00899 case GET_ULONG_IS_FAIL:
00900 if (num > (uint64_t) UINT32_MAX)
00901 {
00902 num= ((uint64_t) UINT32_MAX);
00903 adjusted= true;
00904 }
00905 break;
00906 case GET_SIZE:
00907 if (num > (uint64_t) SIZE_MAX)
00908 {
00909 num= ((uint64_t) SIZE_MAX);
00910 adjusted= true;
00911 }
00912 break;
00913 default:
00914 assert(((optp->var_type & GET_TYPE_MASK) == GET_ULL)
00915 || ((optp->var_type & GET_TYPE_MASK) == GET_UINT64));
00916 break;
00917 }
00918
00919 if (optp->block_size > 1)
00920 {
00921 num/= (uint64_t) optp->block_size;
00922 num*= (uint64_t) optp->block_size;
00923 }
00924
00925 if (num < (uint64_t) optp->min_value)
00926 {
00927 num= (uint64_t) optp->min_value;
00928 adjusted= true;
00929 }
00930
00931 if (fix)
00932 *fix= adjusted;
00933 else if (adjusted)
00934 my_getopt_error_reporter(WARNING_LEVEL,
00935 "option '%s': unsigned value %s adjusted to %s",
00936 optp->name, internal::ullstr(old, buf1), internal::ullstr(num, buf2));
00937
00938 return num;
00939 }
00940
00941
00942
00943
00944
00945
00946
00947
00948
00949
00950
00951
00952
00953
00954 static double getopt_double(char *arg, const struct option *optp, int *err)
00955 {
00956 double num;
00957 int error;
00958 char *end= arg + 1000;
00959 num= internal::my_strtod(arg, &end, &error);
00960 if (end[0] != 0 || error)
00961 {
00962 fprintf(stderr,
00963 _("%s: ERROR: Invalid decimal value for option '%s'\n"),
00964 internal::my_progname, optp->name);
00965 *err= EXIT_ARGUMENT_INVALID;
00966 return 0.0;
00967 }
00968 if (optp->max_value && num > (double) optp->max_value)
00969 num= (double) optp->max_value;
00970 return max(num, (double) optp->min_value);
00971 }
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982 static void init_one_value(const struct option *option, char** variable,
00983 int64_t value)
00984 {
00985 switch ((option->var_type & GET_TYPE_MASK)) {
00986 case GET_BOOL:
00987 *((bool*) variable)= (bool) value;
00988 break;
00989 case GET_INT:
00990 *((int*) variable)= (int) value;
00991 break;
00992 case GET_UINT:
00993 case GET_ENUM:
00994 *((uint*) variable)= (uint32_t) value;
00995 break;
00996 case GET_LONG:
00997 *((long*) variable)= (long) value;
00998 break;
00999 case GET_UINT32:
01000 *((uint32_t*) variable)= (uint32_t) value;
01001 break;
01002 case GET_ULONG_IS_FAIL:
01003 *((ulong*) variable)= (ulong) value;
01004 break;
01005 case GET_LL:
01006 *((int64_t*) variable)= (int64_t) value;
01007 break;
01008 case GET_SIZE:
01009 *((size_t*) variable)= (size_t) value;
01010 break;
01011 case GET_ULL:
01012 case GET_SET:
01013 case GET_UINT64:
01014 *((uint64_t*) variable)= (uint64_t) value;
01015 break;
01016 case GET_DOUBLE:
01017 *((double*) variable)= (double) value;
01018 break;
01019 case GET_STR:
01020
01021
01022
01023
01024
01025
01026 if ((char*) (intptr_t) value)
01027 *((char**) variable)= (char*) (intptr_t) value;
01028 break;
01029 case GET_STR_ALLOC:
01030
01031
01032
01033
01034
01035
01036 if ((char*) (intptr_t) value)
01037 {
01038 free((*(char**) variable));
01039 char *tmpptr= strdup((char *) (intptr_t) value);
01040 if (tmpptr != NULL)
01041 *((char**) variable)= tmpptr;
01042 }
01043 break;
01044 default:
01045 break;
01046 }
01047 return;
01048 }
01049
01050
01051
01052
01053
01054
01055
01056
01057
01058
01059
01060 static void fini_one_value(const struct option *option, char **variable,
01061 int64_t)
01062 {
01063 switch ((option->var_type & GET_TYPE_MASK)) {
01064 case GET_STR_ALLOC:
01065 free((*(char**) variable));
01066 *((char**) variable)= NULL;
01067 break;
01068 default:
01069 break;
01070 }
01071 return;
01072 }
01073
01074
01075 void my_cleanup_options(const struct option *options)
01076 {
01077 init_variables(options, fini_one_value);
01078 }
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094 static void init_variables(const struct option *options,
01095 init_func_p init_one_value)
01096 {
01097 for (; options->name; options++)
01098 {
01099 char* *variable;
01100
01101
01102
01103
01104
01105 if (options->u_max_value)
01106 init_one_value(options, options->u_max_value, options->max_value);
01107 if (options->value)
01108 init_one_value(options, options->value, options->def_value);
01109 if (options->var_type & GET_ASK_ADDR &&
01110 (variable= (*getopt_get_addr)("", 0, options)))
01111 init_one_value(options, variable, options->def_value);
01112 }
01113 return;
01114 }
01115
01116
01117
01118
01119
01120
01121
01122
01123 void my_print_help(const struct option *options)
01124 {
01125 uint32_t col, name_space= 22, comment_space= 57;
01126 const char *line_end;
01127 const struct option *optp;
01128
01129 for (optp= options; optp->id; optp++)
01130 {
01131 if (optp->id < 256)
01132 {
01133 printf(" -%c%s", optp->id, strlen(optp->name) ? ", " : " ");
01134 col= 6;
01135 }
01136 else
01137 {
01138 printf(" ");
01139 col= 2;
01140 }
01141 if (strlen(optp->name))
01142 {
01143 printf("--%s", optp->name);
01144 col+= 2 + (uint32_t) strlen(optp->name);
01145 if ((optp->var_type & GET_TYPE_MASK) == GET_STR ||
01146 (optp->var_type & GET_TYPE_MASK) == GET_STR_ALLOC)
01147 {
01148 printf("%s=name%s ", optp->arg_type == OPT_ARG ? "[" : "",
01149 optp->arg_type == OPT_ARG ? "]" : "");
01150 col+= (optp->arg_type == OPT_ARG) ? 8 : 6;
01151 }
01152 else if ((optp->var_type & GET_TYPE_MASK) == GET_NO_ARG ||
01153 (optp->var_type & GET_TYPE_MASK) == GET_BOOL)
01154 {
01155 putchar(' ');
01156 col++;
01157 }
01158 else
01159 {
01160 printf("%s=#%s ", optp->arg_type == OPT_ARG ? "[" : "",
01161 optp->arg_type == OPT_ARG ? "]" : "");
01162 col+= (optp->arg_type == OPT_ARG) ? 5 : 3;
01163 }
01164 if (col > name_space && optp->comment && *optp->comment)
01165 {
01166 putchar('\n');
01167 col= 0;
01168 }
01169 }
01170 for (; col < name_space; col++)
01171 putchar(' ');
01172 if (optp->comment && *optp->comment)
01173 {
01174 const char *comment= _(optp->comment), *end= strchr(comment, '\0');
01175
01176 while ((uint32_t) (end - comment) > comment_space)
01177 {
01178 for (line_end= comment + comment_space; *line_end != ' '; line_end--)
01179 {}
01180 for (; comment != line_end; comment++)
01181 putchar(*comment);
01182 comment++;
01183 putchar('\n');
01184 for (col= 0; col < name_space; col++)
01185 putchar(' ');
01186 }
01187 printf("%s", comment);
01188 }
01189 putchar('\n');
01190 if ((optp->var_type & GET_TYPE_MASK) == GET_NO_ARG ||
01191 (optp->var_type & GET_TYPE_MASK) == GET_BOOL)
01192 {
01193 if (optp->def_value != 0)
01194 {
01195 printf(_("%*s(Defaults to on; use --skip-%s to disable.)\n"), name_space, "", optp->name);
01196 }
01197 }
01198 }
01199 }
01200
01201
01202
01203
01204
01205
01206
01207
01208 void my_print_variables(const struct option *options)
01209 {
01210 uint32_t name_space= 34, length, nr;
01211 uint64_t bit, llvalue;
01212 char buff[255];
01213 const struct option *optp;
01214
01215 printf(_("\nVariables (--variable-name=value)\n"
01216 "and boolean options {false|true} Value (after reading options)\n"
01217 "--------------------------------- -----------------------------\n"));
01218 for (optp= options; optp->id; optp++)
01219 {
01220 char* *value= (optp->var_type & GET_ASK_ADDR ?
01221 (*getopt_get_addr)("", 0, optp) : optp->value);
01222 if (value)
01223 {
01224 printf("%s ", optp->name);
01225 length= (uint32_t) strlen(optp->name)+1;
01226 for (; length < name_space; length++)
01227 putchar(' ');
01228 switch ((optp->var_type & GET_TYPE_MASK)) {
01229 case GET_SET:
01230 if (!(llvalue= *(uint64_t*) value))
01231 printf("%s\n", _("(No default value)"));
01232 else
01233 for (nr= 0, bit= 1; llvalue && nr < optp->typelib->count; nr++, bit<<=1)
01234 {
01235 if (!(bit & llvalue))
01236 continue;
01237 llvalue&= ~bit;
01238 printf( llvalue ? "%s," : "%s\n", optp->typelib->get_type(nr));
01239 }
01240 break;
01241 case GET_ENUM:
01242 printf("%s\n", optp->typelib->get_type(*(uint*) value));
01243 break;
01244 case GET_STR:
01245 case GET_STR_ALLOC:
01246 printf("%s\n", *((char**) value) ? *((char**) value) :
01247 _("(No default value)"));
01248 break;
01249 case GET_BOOL:
01250 printf("%s\n", *((bool*) value) ? _("true") : _("false"));
01251 break;
01252 case GET_INT:
01253 printf("%d\n", *((int*) value));
01254 break;
01255 case GET_UINT:
01256 printf("%d\n", *((uint*) value));
01257 break;
01258 case GET_LONG:
01259 printf("%ld\n", *((long*) value));
01260 break;
01261 case GET_UINT32:
01262 printf("%u\n", *((uint32_t*) value));
01263 break;
01264 case GET_ULONG_IS_FAIL:
01265 printf("%lu\n", *((ulong*) value));
01266 break;
01267 case GET_SIZE:
01268 internal::int64_t2str((uint64_t)(*(size_t*)value), buff, 10);
01269 printf("%s\n", buff);
01270 break;
01271 case GET_LL:
01272 printf("%s\n", internal::llstr(*((int64_t*) value), buff));
01273 break;
01274 case GET_ULL:
01275 case GET_UINT64:
01276 internal::int64_t2str(*((uint64_t*) value), buff, 10);
01277 printf("%s\n", buff);
01278 break;
01279 case GET_DOUBLE:
01280 printf("%g\n", *(double*) value);
01281 break;
01282 default:
01283 printf(_("(Disabled)\n"));
01284 break;
01285 }
01286 }
01287 }
01288 }
01289
01290 }