~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to mysys/my_getopt.cc

  • Committer: Padraig O'Sullivan
  • Date: 2009-09-13 01:03:01 UTC
  • mto: (1126.9.2 captain-20090915-01)
  • mto: This revision was merged to the branch mainline in revision 1133.
  • Revision ID: osullivan.padraig@gmail.com-20090913010301-tcvvezipx1124acy
Added calls to the dtrace delete begin/end probes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2002-2006 MySQL AB
 
2
 
 
3
   This program is free software; you can redistribute it and/or modify
 
4
   it under the terms of the GNU General Public License as published by
 
5
   the Free Software Foundation; version 2 of the License.
 
6
 
 
7
   This program is distributed in the hope that it will be useful,
 
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
10
   GNU General Public License for more details.
 
11
 
 
12
   You should have received a copy of the GNU General Public License
 
13
   along with this program; if not, write to the Free Software
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
15
 
 
16
#include "mysys/mysys_priv.h"
 
17
#include <drizzled/gettext.h>
 
18
 
 
19
#include <mystrings/m_string.h>
 
20
#include <mysys/my_sys.h>
 
21
#include <mysys/mysys_err.h>
 
22
#include <mysys/my_getopt.h>
 
23
 
 
24
#include <stdio.h>
 
25
#include <stdlib.h>
 
26
#include <errno.h>
 
27
#include <iostream>
 
28
#include <algorithm>
 
29
 
 
30
using namespace std;
 
31
 
 
32
typedef void (*init_func_p)(const struct my_option *option, char **variable,
 
33
                            int64_t value);
 
34
 
 
35
void default_reporter(enum loglevel level, const char *format, ...);
 
36
my_error_reporter my_getopt_error_reporter= &default_reporter;
 
37
 
 
38
static int findopt(char *optpat, uint32_t length,
 
39
                   const struct my_option **opt_res,
 
40
                   char **ffname);
 
41
static int64_t getopt_ll(char *arg, const struct my_option *optp, int *err);
 
42
static uint64_t getopt_ull(char *arg, const struct my_option *optp,
 
43
                            int *err);
 
44
static size_t getopt_size(char *arg, const struct my_option *optp, int *err);
 
45
static double getopt_double(char *arg, const struct my_option *optp, int *err);
 
46
static void init_variables(const struct my_option *options,
 
47
                           init_func_p init_one_value);
 
48
static void init_one_value(const struct my_option *option, char **variable,
 
49
                           int64_t value);
 
50
static void fini_one_value(const struct my_option *option, char **variable,
 
51
                           int64_t value);
 
52
static int setval(const struct my_option *opts, char* *value, char *argument,
 
53
                  bool set_maximum_value);
 
54
static char *check_struct_option(char *cur_arg, char *key_name);
 
55
 
 
56
/*
 
57
  The following three variables belong to same group and the number and
 
58
  order of their arguments must correspond to each other.
 
59
*/
 
60
static const char *special_opt_prefix[]=
 
61
{"skip", "disable", "enable", "maximum", "loose", 0};
 
62
static const uint32_t special_opt_prefix_lengths[]=
 
63
{ 4,      7,         6,        7,         5,      0};
 
64
enum enum_special_opt
 
65
{ OPT_SKIP, OPT_DISABLE, OPT_ENABLE, OPT_MAXIMUM, OPT_LOOSE};
 
66
 
 
67
char *disabled_my_option= (char*) "0";
 
68
 
 
69
/*
 
70
   This is a flag that can be set in client programs. 0 means that
 
71
   my_getopt will not print error messages, but the client should do
 
72
   it by itself
 
73
*/
 
74
 
 
75
bool my_getopt_print_errors= 1;
 
76
 
 
77
/*
 
78
   This is a flag that can be set in client programs. 1 means that
 
79
   my_getopt will skip over options it does not know how to handle.
 
80
*/
 
81
 
 
82
bool my_getopt_skip_unknown= 0;
 
83
 
 
84
void default_reporter(enum loglevel level,
 
85
                      const char *format, ...)
 
86
{
 
87
  va_list args;
 
88
  va_start(args, format);
 
89
  if (level == WARNING_LEVEL)
 
90
    fprintf(stderr, "%s", _("Warning: "));
 
91
  else if (level == INFORMATION_LEVEL)
 
92
    fprintf(stderr, "%s", _("Info: "));
 
93
  vfprintf(stderr, format, args);
 
94
  va_end(args);
 
95
  fputc('\n', stderr);
 
96
  fflush(stderr);
 
97
}
 
98
 
 
99
/*
 
100
  function: handle_options
 
101
 
 
102
  Sort options; put options first, until special end of options (--), or
 
103
  until end of argv. Parse options; check that the given option matches with
 
104
  one of the options in struct 'my_option', return error in case of ambiguous
 
105
  or unknown option. Check that option was given an argument if it requires
 
106
  one. Call function 'get_one_option()' once for each option.
 
107
*/
 
108
 
 
109
static getopt_get_addr_func getopt_get_addr;
 
110
 
 
111
void my_getopt_register_get_addr(getopt_get_addr_func func_addr)
 
112
{
 
113
  getopt_get_addr= func_addr;
 
114
}
 
115
 
 
116
int handle_options(int *argc, char ***argv,
 
117
                   const struct my_option *longopts,
 
118
                   my_get_one_option get_one_option)
 
119
{
 
120
  uint32_t opt_found, argvpos= 0, length;
 
121
  bool end_of_options= 0, must_be_var, set_maximum_value=false,
 
122
          option_is_loose;
 
123
  char **pos, **pos_end, *optend, *prev_found=NULL,
 
124
       *opt_str, key_name[FN_REFLEN];
 
125
  const struct my_option *optp;
 
126
  char* *value;
 
127
  int error, i;
 
128
 
 
129
  /* handle_options() assumes arg0 (program name) always exists */
 
130
  assert(argc && *argc >= 1);
 
131
  assert(argv && *argv);
 
132
  (*argc)--; /* Skip the program name */
 
133
  (*argv)++; /*      --- || ----      */
 
134
  init_variables(longopts, init_one_value);
 
135
 
 
136
  for (pos= *argv, pos_end=pos+ *argc; pos != pos_end ; pos++)
 
137
  {
 
138
    char **first= pos;
 
139
    char *cur_arg= *pos;
 
140
    if (cur_arg[0] == '-' && cur_arg[1] && !end_of_options) /* must be opt */
 
141
    {
 
142
      char *argument=    0;
 
143
      must_be_var=       0;
 
144
      set_maximum_value= 0;
 
145
      option_is_loose=   0;
 
146
 
 
147
      cur_arg++;                /* skip '-' */
 
148
      if (*cur_arg == '-' || *cur_arg == 'O') /* check for long option, */
 
149
      {                                       /* --set-variable, or -O  */
 
150
        if (*cur_arg == 'O')
 
151
        {
 
152
          must_be_var= 1;
 
153
 
 
154
          if (!(*++cur_arg))    /* If not -Ovar=# */
 
155
          {
 
156
            /* the argument must be in next argv */
 
157
            if (!*++pos)
 
158
            {
 
159
              if (my_getopt_print_errors)
 
160
                my_getopt_error_reporter(ERROR_LEVEL,
 
161
                                         "%s: Option '-O' requires an argument",
 
162
                                         my_progname);
 
163
              return EXIT_ARGUMENT_REQUIRED;
 
164
            }
 
165
            cur_arg= *pos;
 
166
            (*argc)--;
 
167
          }
 
168
        }
 
169
        else if (!getopt_compare_strings(cur_arg, "-set-variable", 13))
 
170
        {
 
171
          must_be_var= 1;
 
172
          if (cur_arg[13] == '=')
 
173
          {
 
174
            cur_arg+= 14;
 
175
            if (!*cur_arg)
 
176
            {
 
177
              if (my_getopt_print_errors)
 
178
                my_getopt_error_reporter(ERROR_LEVEL,
 
179
                                         "%s: Option '--set-variable' requires an argument",
 
180
                                         my_progname);
 
181
              return EXIT_ARGUMENT_REQUIRED;
 
182
            }
 
183
          }
 
184
          else if (cur_arg[14]) /* garbage, or another option. break out */
 
185
            must_be_var= 0;
 
186
          else
 
187
          {
 
188
            /* the argument must be in next argv */
 
189
            if (!*++pos)
 
190
            {
 
191
              if (my_getopt_print_errors)
 
192
                my_getopt_error_reporter(ERROR_LEVEL,
 
193
                                         "%s: Option '--set-variable' requires an argument",
 
194
                                         my_progname);
 
195
              return EXIT_ARGUMENT_REQUIRED;
 
196
            }
 
197
            cur_arg= *pos;
 
198
            (*argc)--;
 
199
          }
 
200
        }
 
201
        else if (!must_be_var)
 
202
        {
 
203
          if (!*++cur_arg)      /* skip the double dash */
 
204
          {
 
205
            /* '--' means end of options, look no further */
 
206
            end_of_options= 1;
 
207
            (*argc)--;
 
208
            continue;
 
209
          }
 
210
        }
 
211
        opt_str= check_struct_option(cur_arg, key_name);
 
212
        optend= strrchr(opt_str, '=');
 
213
        if (optend != NULL)
 
214
        {
 
215
          length= (uint32_t) (optend - opt_str);
 
216
          optend++;
 
217
        }
 
218
        else
 
219
        {
 
220
          length= strlen(opt_str);
 
221
          optend= 0;
 
222
        }
 
223
 
 
224
        /*
 
225
          Find first the right option. Return error in case of an ambiguous,
 
226
          or unknown option
 
227
        */
 
228
        optp= longopts;
 
229
        if (!(opt_found= findopt(opt_str, length, &optp, &prev_found)))
 
230
        {
 
231
          /*
 
232
            Didn't find any matching option. Let's see if someone called
 
233
            option with a special option prefix
 
234
          */
 
235
          if (!must_be_var)
 
236
          {
 
237
            if (optend)
 
238
              must_be_var= 1; /* option is followed by an argument */
 
239
            for (i= 0; special_opt_prefix[i]; i++)
 
240
            {
 
241
              if (!getopt_compare_strings(special_opt_prefix[i], opt_str,
 
242
                                          special_opt_prefix_lengths[i]) &&
 
243
                  (opt_str[special_opt_prefix_lengths[i]] == '-' ||
 
244
                   opt_str[special_opt_prefix_lengths[i]] == '_'))
 
245
              {
 
246
                /*
 
247
                  We were called with a special prefix, we can reuse opt_found
 
248
                */
 
249
                opt_str+= special_opt_prefix_lengths[i] + 1;
 
250
                length-= special_opt_prefix_lengths[i] + 1;
 
251
                if (i == OPT_LOOSE)
 
252
                  option_is_loose= 1;
 
253
                if ((opt_found= findopt(opt_str, length, &optp, &prev_found)))
 
254
                {
 
255
                  if (opt_found > 1)
 
256
                  {
 
257
                    if (my_getopt_print_errors)
 
258
                      my_getopt_error_reporter(ERROR_LEVEL,
 
259
                                               "%s: ambiguous option '--%s-%s' (--%s-%s)",
 
260
                                               my_progname, special_opt_prefix[i],
 
261
                                               cur_arg, special_opt_prefix[i],
 
262
                                               prev_found);
 
263
                    return EXIT_AMBIGUOUS_OPTION;
 
264
                  }
 
265
                  switch (i) {
 
266
                  case OPT_SKIP:
 
267
                  case OPT_DISABLE: /* fall through */
 
268
                    /*
 
269
                      double negation is actually enable again,
 
270
                      for example: --skip-option=0 -> option = true
 
271
                    */
 
272
                    optend= (optend && *optend == '0' && !(*(optend + 1))) ?
 
273
                      (char*) "1" : disabled_my_option;
 
274
                    break;
 
275
                  case OPT_ENABLE:
 
276
                    optend= (optend && *optend == '0' && !(*(optend + 1))) ?
 
277
                      disabled_my_option : (char*) "1";
 
278
                    break;
 
279
                  case OPT_MAXIMUM:
 
280
                    set_maximum_value= true;
 
281
                    must_be_var= true;
 
282
                    break;
 
283
                  }
 
284
                  break; /* break from the inner loop, main loop continues */
 
285
                }
 
286
                i= -1; /* restart the loop */
 
287
              }
 
288
            }
 
289
          }
 
290
          if (!opt_found)
 
291
          {
 
292
            if (my_getopt_skip_unknown)
 
293
            {
 
294
              /*
 
295
                preserve all the components of this unknown option, this may
 
296
                occurr when the user provides options like: "-O foo" or
 
297
                "--set-variable foo" (note that theres a space in there)
 
298
                Generally, these kind of options are to be avoided
 
299
              */
 
300
              do {
 
301
                (*argv)[argvpos++]= *first++;
 
302
              } while (first <= pos);
 
303
              continue;
 
304
            }
 
305
            if (must_be_var)
 
306
            {
 
307
              if (my_getopt_print_errors)
 
308
                my_getopt_error_reporter(option_is_loose ?
 
309
                                           WARNING_LEVEL : ERROR_LEVEL,
 
310
                                         "%s: unknown variable '%s'",
 
311
                                         my_progname, cur_arg);
 
312
              if (!option_is_loose)
 
313
                return EXIT_UNKNOWN_VARIABLE;
 
314
            }
 
315
            else
 
316
            {
 
317
              if (my_getopt_print_errors)
 
318
                my_getopt_error_reporter(option_is_loose ?
 
319
                                           WARNING_LEVEL : ERROR_LEVEL,
 
320
                                         "%s: unknown option '--%s'",
 
321
                                         my_progname, cur_arg);
 
322
              if (!option_is_loose)
 
323
                return EXIT_UNKNOWN_OPTION;
 
324
            }
 
325
            if (option_is_loose)
 
326
            {
 
327
              (*argc)--;
 
328
              continue;
 
329
            }
 
330
          }
 
331
        }
 
332
        if (opt_found > 1)
 
333
        {
 
334
          if (must_be_var)
 
335
          {
 
336
            if (my_getopt_print_errors)
 
337
              my_getopt_error_reporter(ERROR_LEVEL,
 
338
                                       "%s: variable prefix '%s' is not unique",
 
339
                                       my_progname, opt_str);
 
340
            return EXIT_VAR_PREFIX_NOT_UNIQUE;
 
341
          }
 
342
          else
 
343
          {
 
344
            if (my_getopt_print_errors)
 
345
              my_getopt_error_reporter(ERROR_LEVEL,
 
346
                                       "%s: ambiguous option '--%s' (%s, %s)",
 
347
                                       my_progname, opt_str, prev_found,
 
348
                                       optp->name);
 
349
            return EXIT_AMBIGUOUS_OPTION;
 
350
          }
 
351
        }
 
352
        if ((optp->var_type & GET_TYPE_MASK) == GET_DISABLED)
 
353
        {
 
354
          if (my_getopt_print_errors)
 
355
            fprintf(stderr,
 
356
                    _("%s: %s: Option '%s' used, but is disabled\n"), my_progname,
 
357
                    option_is_loose ? _("WARNING") : _("ERROR"), opt_str);
 
358
          if (option_is_loose)
 
359
          {
 
360
            (*argc)--;
 
361
            continue;
 
362
          }
 
363
          return EXIT_OPTION_DISABLED;
 
364
        }
 
365
        if (must_be_var && (optp->var_type & GET_TYPE_MASK) == GET_NO_ARG)
 
366
        {
 
367
          if (my_getopt_print_errors)
 
368
            my_getopt_error_reporter(ERROR_LEVEL,
 
369
                                     "%s: option '%s' cannot take an argument",
 
370
                                     my_progname, optp->name);
 
371
          return EXIT_NO_ARGUMENT_ALLOWED;
 
372
        }
 
373
        value= optp->var_type & GET_ASK_ADDR ?
 
374
          (*getopt_get_addr)(key_name, (uint32_t) strlen(key_name), optp) : optp->value;
 
375
 
 
376
        if (optp->arg_type == NO_ARG)
 
377
        {
 
378
          if (optend && (optp->var_type & GET_TYPE_MASK) != GET_BOOL)
 
379
          {
 
380
            if (my_getopt_print_errors)
 
381
              my_getopt_error_reporter(ERROR_LEVEL,
 
382
                                       "%s: option '--%s' cannot take an argument",
 
383
                                       my_progname, optp->name);
 
384
            return EXIT_NO_ARGUMENT_ALLOWED;
 
385
          }
 
386
          if ((optp->var_type & GET_TYPE_MASK) == GET_BOOL)
 
387
          {
 
388
            /*
 
389
              Set bool to 1 if no argument or if the user has used
 
390
              --enable-'option-name'.
 
391
              *optend was set to '0' if one used --disable-option
 
392
              */
 
393
            (*argc)--;
 
394
            if (!optend || *optend == '1' ||
 
395
                !my_strcasecmp(&my_charset_utf8_general_ci, optend, "true"))
 
396
              *((bool*) value)= (bool) 1;
 
397
            else if (*optend == '0' ||
 
398
                     !my_strcasecmp(&my_charset_utf8_general_ci, optend, "false"))
 
399
              *((bool*) value)= (bool) 0;
 
400
            else
 
401
            {
 
402
              my_getopt_error_reporter(WARNING_LEVEL,
 
403
                                       "%s: ignoring option '--%s' due to \
 
404
invalid value '%s'",
 
405
                                       my_progname, optp->name, optend);
 
406
              continue;
 
407
            }
 
408
            get_one_option(optp->id, optp,
 
409
                           *((bool*) value) ?
 
410
                           (char*) "1" : disabled_my_option);
 
411
            continue;
 
412
          }
 
413
          argument= optend;
 
414
        }
 
415
        else if (optp->arg_type == OPT_ARG &&
 
416
                 (optp->var_type & GET_TYPE_MASK) == GET_BOOL)
 
417
        {
 
418
          if (optend == disabled_my_option)
 
419
            *((bool*) value)= (bool) 0;
 
420
          else
 
421
          {
 
422
            if (!optend) /* No argument -> enable option */
 
423
              *((bool*) value)= (bool) 1;
 
424
            else
 
425
              argument= optend;
 
426
          }
 
427
        }
 
428
        else if (optp->arg_type == REQUIRED_ARG && !optend)
 
429
        {
 
430
          /* Check if there are more arguments after this one */
 
431
          if (!*++pos)
 
432
          {
 
433
            if (my_getopt_print_errors)
 
434
              my_getopt_error_reporter(ERROR_LEVEL,
 
435
                                       "%s: option '--%s' requires an argument",
 
436
                                       my_progname, optp->name);
 
437
            return EXIT_ARGUMENT_REQUIRED;
 
438
          }
 
439
          argument= *pos;
 
440
          (*argc)--;
 
441
        }
 
442
        else
 
443
          argument= optend;
 
444
      }
 
445
      else  /* must be short option */
 
446
      {
 
447
        for (optend= cur_arg; *optend; optend++)
 
448
        {
 
449
          opt_found= 0;
 
450
          for (optp= longopts; optp->id; optp++)
 
451
          {
 
452
            if (optp->id == (int) (unsigned char) *optend)
 
453
            {
 
454
              /* Option recognized. Find next what to do with it */
 
455
              opt_found= 1;
 
456
              if ((optp->var_type & GET_TYPE_MASK) == GET_DISABLED)
 
457
              {
 
458
                if (my_getopt_print_errors)
 
459
                  fprintf(stderr,
 
460
                          _("%s: ERROR: Option '-%c' used, but is disabled\n"),
 
461
                          my_progname, optp->id);
 
462
                return EXIT_OPTION_DISABLED;
 
463
              }
 
464
              if ((optp->var_type & GET_TYPE_MASK) == GET_BOOL &&
 
465
                  optp->arg_type == NO_ARG)
 
466
              {
 
467
                *((bool*) optp->value)= (bool) 1;
 
468
                get_one_option(optp->id, optp, argument);
 
469
                continue;
 
470
              }
 
471
              else if (optp->arg_type == REQUIRED_ARG ||
 
472
                       optp->arg_type == OPT_ARG)
 
473
              {
 
474
                if (*(optend + 1))
 
475
                {
 
476
                  /* The rest of the option is option argument */
 
477
                  argument= optend + 1;
 
478
                  /* This is in effect a jump out of the outer loop */
 
479
                  optend= (char*) " ";
 
480
                }
 
481
                else
 
482
                {
 
483
                  if (optp->arg_type == OPT_ARG)
 
484
                  {
 
485
                    if (optp->var_type == GET_BOOL)
 
486
                      *((bool*) optp->value)= (bool) 1;
 
487
                    get_one_option(optp->id, optp, argument);
 
488
                    continue;
 
489
                  }
 
490
                  /* Check if there are more arguments after this one */
 
491
                  if (!pos[1])
 
492
                  {
 
493
                    if (my_getopt_print_errors)
 
494
                      my_getopt_error_reporter(ERROR_LEVEL,
 
495
                                               "%s: option '-%c' requires an argument",
 
496
                                               my_progname, optp->id);
 
497
                    return EXIT_ARGUMENT_REQUIRED;
 
498
                  }
 
499
                  argument= *++pos;
 
500
                  (*argc)--;
 
501
                  /* the other loop will break, because *optend + 1 == 0 */
 
502
                }
 
503
              }
 
504
              if ((error= setval(optp, optp->value, argument,
 
505
                                 set_maximum_value)))
 
506
              {
 
507
                my_getopt_error_reporter(ERROR_LEVEL,
 
508
                                         "%s: Error while setting value '%s' to '%s'",
 
509
                                         my_progname, argument, optp->name);
 
510
                return error;
 
511
              }
 
512
              get_one_option(optp->id, optp, argument);
 
513
              break;
 
514
            }
 
515
          }
 
516
          if (!opt_found)
 
517
          {
 
518
            if (my_getopt_print_errors)
 
519
              my_getopt_error_reporter(ERROR_LEVEL,
 
520
                                       "%s: unknown option '-%c'",
 
521
                                       my_progname, *optend);
 
522
            return EXIT_UNKNOWN_OPTION;
 
523
          }
 
524
        }
 
525
        (*argc)--; /* option handled (short), decrease argument count */
 
526
        continue;
 
527
      }
 
528
      if ((error= setval(optp, value, argument, set_maximum_value)))
 
529
      {
 
530
        my_getopt_error_reporter(ERROR_LEVEL,
 
531
                                 "%s: Error while setting value '%s' to '%s'",
 
532
                                 my_progname, argument, optp->name);
 
533
        return error;
 
534
      }
 
535
      get_one_option(optp->id, optp, argument);
 
536
 
 
537
      (*argc)--; /* option handled (short or long), decrease argument count */
 
538
    }
 
539
    else /* non-option found */
 
540
      (*argv)[argvpos++]= cur_arg;
 
541
  }
 
542
  /*
 
543
    Destroy the first, already handled option, so that programs that look
 
544
    for arguments in 'argv', without checking 'argc', know when to stop.
 
545
    Items in argv, before the destroyed one, are all non-option -arguments
 
546
    to the program, yet to be (possibly) handled.
 
547
  */
 
548
  (*argv)[argvpos]= 0;
 
549
  return 0;
 
550
}
 
551
 
 
552
 
 
553
/*
 
554
  function: check_struct_option
 
555
 
 
556
  Arguments: Current argument under processing from argv and a variable
 
557
  where to store the possible key name.
 
558
 
 
559
  Return value: In case option is a struct option, returns a pointer to
 
560
  the current argument at the position where the struct option (key_name)
 
561
  ends, the next character after the dot. In case argument is not a struct
 
562
  option, returns a pointer to the argument.
 
563
 
 
564
  key_name will hold the name of the key, or 0 if not found.
 
565
*/
 
566
 
 
567
static char *check_struct_option(char *cur_arg, char *key_name)
 
568
{
 
569
  char *ptr, *end;
 
570
 
 
571
  ptr= strrchr(cur_arg + 1, '.'); /* Skip the first character */
 
572
  end= strrchr(cur_arg, '=');
 
573
 
 
574
  /*
 
575
     If the first dot is after an equal sign, then it is part
 
576
     of a variable value and the option is not a struct option.
 
577
     Also, if the last character in the string before the ending
 
578
     NULL, or the character right before equal sign is the first
 
579
     dot found, the option is not a struct option.
 
580
  */
 
581
  if ((ptr != NULL) && (end != NULL) && (end - ptr > 1))
 
582
  {
 
583
    uint32_t len= (uint32_t) (ptr - cur_arg);
 
584
    set_if_smaller(len, (uint32_t)FN_REFLEN-1);
 
585
    strncpy(key_name, cur_arg, len);
 
586
    return ++ptr;
 
587
  }
 
588
  key_name[0]= 0;
 
589
  return cur_arg;
 
590
}
 
591
 
 
592
/*
 
593
  function: setval
 
594
 
 
595
  Arguments: opts, argument
 
596
  Will set the option value to given value
 
597
*/
 
598
 
 
599
static int setval(const struct my_option *opts, char **value, char *argument,
 
600
                  bool set_maximum_value)
 
601
{
 
602
  int err= 0;
 
603
 
 
604
  if (value && argument)
 
605
  {
 
606
    char* *result_pos= ((set_maximum_value) ?
 
607
                        opts->u_max_value : value);
 
608
 
 
609
    if (!result_pos)
 
610
      return EXIT_NO_PTR_TO_VARIABLE;
 
611
 
 
612
    switch ((opts->var_type & GET_TYPE_MASK)) {
 
613
    case GET_BOOL: /* If argument differs from 0, enable option, else disable */
 
614
      *((bool*) result_pos)= (bool) atoi(argument) != 0;
 
615
      break;
 
616
    case GET_INT:
 
617
      *((int32_t*) result_pos)= (int) getopt_ll(argument, opts, &err);
 
618
      break;
 
619
    case GET_UINT:
 
620
    case GET_UINT32:
 
621
      *((uint32_t*) result_pos)= (uint32_t) getopt_ull(argument, opts, &err);
 
622
      break;
 
623
    case GET_ULONG_IS_FAIL:
 
624
      *((ulong*) result_pos)= (ulong) getopt_ull(argument, opts, &err);
 
625
      break;
 
626
    case GET_LONG:
 
627
      *((long*) result_pos)= (long) getopt_ll(argument, opts, &err);
 
628
      break;
 
629
    case GET_LL:
 
630
      *((int64_t*) result_pos)= getopt_ll(argument, opts, &err);
 
631
      break;
 
632
    case GET_ULL:
 
633
    case GET_UINT64:
 
634
      *((uint64_t*) result_pos)= getopt_ull(argument, opts, &err);
 
635
      break;
 
636
    case GET_SIZE:
 
637
      *((size_t*) result_pos)= getopt_size(argument, opts, &err);
 
638
      break;
 
639
    case GET_DOUBLE:
 
640
      *((double*) result_pos)= getopt_double(argument, opts, &err);
 
641
      break;
 
642
    case GET_STR:
 
643
      *((char**) result_pos)= argument;
 
644
      break;
 
645
    case GET_STR_ALLOC:
 
646
      if ((*((char**) result_pos)))
 
647
        free((*(char**) result_pos));
 
648
      if (!(*((char**) result_pos)= strdup(argument)))
 
649
        return EXIT_OUT_OF_MEMORY;
 
650
      break;
 
651
    case GET_ENUM:
 
652
      if (((*(int*)result_pos)= find_type(argument, opts->typelib, 2) - 1) < 0)
 
653
        return EXIT_ARGUMENT_INVALID;
 
654
      break;
 
655
    case GET_SET:
 
656
      *((uint64_t*)result_pos)= find_typeset(argument, opts->typelib, &err);
 
657
      if (err)
 
658
        return EXIT_ARGUMENT_INVALID;
 
659
      break;
 
660
    default:    /* dummy default to avoid compiler warnings */
 
661
      break;
 
662
    }
 
663
    if (err)
 
664
      return EXIT_UNKNOWN_SUFFIX;
 
665
  }
 
666
  return 0;
 
667
}
 
668
 
 
669
 
 
670
/*
 
671
  Find option
 
672
 
 
673
  SYNOPSIS
 
674
    findopt()
 
675
    optpat      Prefix of option to find (with - or _)
 
676
    length      Length of optpat
 
677
    opt_res     Options
 
678
    ffname      Place for pointer to first found name
 
679
 
 
680
  IMPLEMENTATION
 
681
    Go through all options in the my_option struct. Return number
 
682
    of options found that match the pattern and in the argument
 
683
    list the option found, if any. In case of ambiguous option, store
 
684
    the name in ffname argument
 
685
 
 
686
    RETURN
 
687
    0    No matching options
 
688
    #   Number of matching options
 
689
        ffname points to first matching option
 
690
*/
 
691
 
 
692
static int findopt(char *optpat, uint32_t length,
 
693
                   const struct my_option **opt_res,
 
694
                   char **ffname)
 
695
{
 
696
  uint32_t count;
 
697
  struct my_option *opt= (struct my_option *) *opt_res;
 
698
 
 
699
  for (count= 0; opt->name; opt++)
 
700
  {
 
701
    if (!getopt_compare_strings(opt->name, optpat, length)) /* match found */
 
702
    {
 
703
      (*opt_res)= opt;
 
704
      if (!opt->name[length])           /* Exact match */
 
705
        return 1;
 
706
      if (!count)
 
707
      {
 
708
        count= 1;
 
709
        *ffname= (char *) opt->name;    /* We only need to know one prev */
 
710
      }
 
711
      else if (strcmp(*ffname, opt->name))
 
712
      {
 
713
        /*
 
714
          The above test is to not count same option twice
 
715
          (see mysql.cc, option "help")
 
716
        */
 
717
        count++;
 
718
      }
 
719
    }
 
720
  }
 
721
  return count;
 
722
}
 
723
 
 
724
 
 
725
/*
 
726
  function: compare_strings
 
727
 
 
728
  Works like strncmp, other than 1.) considers '-' and '_' the same.
 
729
  2.) Returns -1 if strings differ, 0 if they are equal
 
730
*/
 
731
 
 
732
bool getopt_compare_strings(register const char *s, register const char *t,
 
733
                               uint32_t length)
 
734
{
 
735
  char const *end= s + length;
 
736
  for (;s != end ; s++, t++)
 
737
  {
 
738
    if ((*s != '-' ? *s : '_') != (*t != '-' ? *t : '_'))
 
739
      return 1;
 
740
  }
 
741
  return 0;
 
742
}
 
743
 
 
744
/*
 
745
  function: eval_num_suffix
 
746
 
 
747
  Transforms a number with a suffix to real number. Suffix can
 
748
  be k|K for kilo, m|M for mega or g|G for giga.
 
749
*/
 
750
 
 
751
static int64_t eval_num_suffix(char *argument, int *error, char *option_name)
 
752
{
 
753
  char *endchar;
 
754
  int64_t num;
 
755
 
 
756
  *error= 0;
 
757
  errno= 0;
 
758
  num= strtoll(argument, &endchar, 10);
 
759
  if (errno == ERANGE)
 
760
  {
 
761
    my_getopt_error_reporter(ERROR_LEVEL,
 
762
                             "Incorrect integer value: '%s'", argument);
 
763
    *error= 1;
 
764
    return 0;
 
765
  }
 
766
  if (*endchar == 'k' || *endchar == 'K')
 
767
    num*= 1024L;
 
768
  else if (*endchar == 'm' || *endchar == 'M')
 
769
    num*= 1024L * 1024L;
 
770
  else if (*endchar == 'g' || *endchar == 'G')
 
771
    num*= 1024L * 1024L * 1024L;
 
772
  else if (*endchar)
 
773
  {
 
774
    fprintf(stderr,
 
775
            _("Unknown suffix '%c' used for variable '%s' (value '%s')\n"),
 
776
            *endchar, option_name, argument);
 
777
    *error= 1;
 
778
    return 0;
 
779
  }
 
780
  return num;
 
781
}
 
782
 
 
783
/*
 
784
  function: getopt_ll
 
785
 
 
786
  Evaluates and returns the value that user gave as an argument
 
787
  to a variable. Recognizes (case insensitive) K as KILO, M as MEGA
 
788
  and G as GIGA bytes. Some values must be in certain blocks, as
 
789
  defined in the given my_option struct, this function will check
 
790
  that those values are honored.
 
791
  In case of an error, set error value in *err.
 
792
*/
 
793
 
 
794
static int64_t getopt_ll(char *arg, const struct my_option *optp, int *err)
 
795
{
 
796
  int64_t num=eval_num_suffix(arg, err, (char*) optp->name);
 
797
  return getopt_ll_limit_value(num, optp, NULL);
 
798
}
 
799
 
 
800
/*
 
801
  function: getopt_ll_limit_value
 
802
 
 
803
  Applies min/max/block_size to a numeric value of an option.
 
804
  Returns "fixed" value.
 
805
*/
 
806
 
 
807
int64_t getopt_ll_limit_value(int64_t num, const struct my_option *optp,
 
808
                               bool *fix)
 
809
{
 
810
  int64_t old= num;
 
811
  bool adjusted= false;
 
812
  char buf1[255], buf2[255];
 
813
  uint64_t block_size= (optp->block_size ? (uint64_t) optp->block_size : 1L);
 
814
 
 
815
  if (num > 0 && ((uint64_t) num > (uint64_t) optp->max_value) &&
 
816
      optp->max_value) /* if max value is not set -> no upper limit */
 
817
  {
 
818
    num= (uint64_t) optp->max_value;
 
819
    adjusted= true;
 
820
  }
 
821
 
 
822
  switch ((optp->var_type & GET_TYPE_MASK)) {
 
823
  case GET_INT:
 
824
    if (num > (int64_t) INT_MAX)
 
825
    {
 
826
      num= ((int64_t) INT_MAX);
 
827
      adjusted= true;
 
828
    }
 
829
    break;
 
830
  case GET_LONG:
 
831
    if (num > (int64_t) INT32_MAX)
 
832
    {
 
833
      num= ((int64_t) INT32_MAX);
 
834
      adjusted= true;
 
835
    }
 
836
    break;
 
837
  default:
 
838
    assert((optp->var_type & GET_TYPE_MASK) == GET_LL);
 
839
    break;
 
840
  }
 
841
 
 
842
  num= ((num - optp->sub_size) / block_size);
 
843
  num= (int64_t) (num * block_size);
 
844
 
 
845
  if (num < optp->min_value)
 
846
  {
 
847
    num= optp->min_value;
 
848
    adjusted= true;
 
849
  }
 
850
 
 
851
  if (fix)
 
852
    *fix= adjusted;
 
853
  else if (adjusted)
 
854
    my_getopt_error_reporter(WARNING_LEVEL,
 
855
                             "option '%s': signed value %s adjusted to %s",
 
856
                             optp->name, llstr(old, buf1), llstr(num, buf2));
 
857
  return num;
 
858
}
 
859
 
 
860
/*
 
861
  function: getopt_ull
 
862
 
 
863
  This is the same as getopt_ll, but is meant for uint64_t
 
864
  values.
 
865
*/
 
866
 
 
867
static uint64_t getopt_ull(char *arg, const struct my_option *optp, int *err)
 
868
{
 
869
  uint64_t num= eval_num_suffix(arg, err, (char*) optp->name);
 
870
  return getopt_ull_limit_value(num, optp, NULL);
 
871
}
 
872
 
 
873
 
 
874
static size_t getopt_size(char *arg, const struct my_option *optp, int *err)
 
875
{
 
876
  return (size_t)getopt_ull(arg, optp, err);
 
877
}
 
878
 
 
879
 
 
880
 
 
881
uint64_t getopt_ull_limit_value(uint64_t num, const struct my_option *optp,
 
882
                                bool *fix)
 
883
{
 
884
  bool adjusted= false;
 
885
  uint64_t old= num;
 
886
  char buf1[255], buf2[255];
 
887
 
 
888
  if ((uint64_t) num > (uint64_t) optp->max_value &&
 
889
      optp->max_value) /* if max value is not set -> no upper limit */
 
890
  {
 
891
    num= (uint64_t) optp->max_value;
 
892
    adjusted= true;
 
893
  }
 
894
 
 
895
  switch ((optp->var_type & GET_TYPE_MASK)) {
 
896
  case GET_UINT:
 
897
    if (num > (uint64_t) UINT_MAX)
 
898
    {
 
899
      num= ((uint64_t) UINT_MAX);
 
900
      adjusted= true;
 
901
    }
 
902
    break;
 
903
  case GET_UINT32:
 
904
  case GET_ULONG_IS_FAIL:
 
905
    if (num > (uint64_t) UINT32_MAX)
 
906
    {
 
907
      num= ((uint64_t) UINT32_MAX);
 
908
      adjusted= true;
 
909
    }
 
910
    break;
 
911
  case GET_SIZE:
 
912
    if (num > (uint64_t) SIZE_MAX)
 
913
    {
 
914
      num= ((uint64_t) SIZE_MAX);
 
915
      adjusted= true;
 
916
    }
 
917
    break;
 
918
  default:
 
919
    assert(((optp->var_type & GET_TYPE_MASK) == GET_ULL)
 
920
           || ((optp->var_type & GET_TYPE_MASK) == GET_UINT64));
 
921
    break;
 
922
  }
 
923
 
 
924
  if (optp->block_size > 1)
 
925
  {
 
926
    num/= (uint64_t) optp->block_size;
 
927
    num*= (uint64_t) optp->block_size;
 
928
  }
 
929
 
 
930
  if (num < (uint64_t) optp->min_value)
 
931
  {
 
932
    num= (uint64_t) optp->min_value;
 
933
    adjusted= true;
 
934
  }
 
935
 
 
936
  if (fix)
 
937
    *fix= adjusted;
 
938
  else if (adjusted)
 
939
    my_getopt_error_reporter(WARNING_LEVEL,
 
940
                             "option '%s': unsigned value %s adjusted to %s",
 
941
                             optp->name, ullstr(old, buf1), ullstr(num, buf2));
 
942
 
 
943
  return num;
 
944
}
 
945
 
 
946
 
 
947
/*
 
948
  Get double value withing ranges
 
949
 
 
950
  Evaluates and returns the value that user gave as an argument to a variable.
 
951
 
 
952
  RETURN
 
953
    decimal value of arg
 
954
 
 
955
    In case of an error, prints an error message and sets *err to
 
956
    EXIT_ARGUMENT_INVALID.  Otherwise err is not touched
 
957
*/
 
958
 
 
959
static double getopt_double(char *arg, const struct my_option *optp, int *err)
 
960
{
 
961
  double num;
 
962
  int error;
 
963
  char *end= arg + 1000;                     /* Big enough as *arg is \0 terminated */
 
964
  num= my_strtod(arg, &end, &error);
 
965
  if (end[0] != 0 || error)
 
966
  {
 
967
    fprintf(stderr,
 
968
            _("%s: ERROR: Invalid decimal value for option '%s'\n"),
 
969
            my_progname, optp->name);
 
970
    *err= EXIT_ARGUMENT_INVALID;
 
971
    return 0.0;
 
972
  }
 
973
  if (optp->max_value && num > (double) optp->max_value)
 
974
    num= (double) optp->max_value;
 
975
  return max(num, (double) optp->min_value);
 
976
}
 
977
 
 
978
/*
 
979
  Init one value to it's default values
 
980
 
 
981
  SYNOPSIS
 
982
    init_one_value()
 
983
    option              Option to initialize
 
984
    value               Pointer to variable
 
985
*/
 
986
 
 
987
static void init_one_value(const struct my_option *option, char** variable,
 
988
                           int64_t value)
 
989
{
 
990
  switch ((option->var_type & GET_TYPE_MASK)) {
 
991
  case GET_BOOL:
 
992
    *((bool*) variable)= (bool) value;
 
993
    break;
 
994
  case GET_INT:
 
995
    *((int*) variable)= (int) value;
 
996
    break;
 
997
  case GET_UINT:
 
998
  case GET_ENUM:
 
999
    *((uint*) variable)= (uint32_t) value;
 
1000
    break;
 
1001
  case GET_LONG:
 
1002
    *((long*) variable)= (long) value;
 
1003
    break;
 
1004
  case GET_UINT32:
 
1005
    *((uint32_t*) variable)= (uint32_t) value;
 
1006
    break;
 
1007
  case GET_ULONG_IS_FAIL:
 
1008
    *((ulong*) variable)= (ulong) value;
 
1009
    break;
 
1010
  case GET_LL:
 
1011
    *((int64_t*) variable)= (int64_t) value;
 
1012
    break;
 
1013
  case GET_SIZE:
 
1014
    *((size_t*) variable)= (size_t) value;
 
1015
    break;
 
1016
  case GET_ULL:
 
1017
  case GET_SET:
 
1018
  case GET_UINT64:
 
1019
    *((uint64_t*) variable)=  (uint64_t) value;
 
1020
    break;
 
1021
  case GET_DOUBLE:
 
1022
    *((double*) variable)=  (double) value;
 
1023
    break;
 
1024
  case GET_STR:
 
1025
    /*
 
1026
      Do not clear variable value if it has no default value.
 
1027
      The default value may already be set.
 
1028
      NOTE: To avoid compiler warnings, we first cast int64_t to intptr_t,
 
1029
      so that the value has the same size as a pointer.
 
1030
    */
 
1031
    if ((char*) (intptr_t) value)
 
1032
      *((char**) variable)= (char*) (intptr_t) value;
 
1033
    break;
 
1034
  case GET_STR_ALLOC:
 
1035
    /*
 
1036
      Do not clear variable value if it has no default value.
 
1037
      The default value may already be set.
 
1038
      NOTE: To avoid compiler warnings, we first cast int64_t to intptr_t,
 
1039
      so that the value has the same size as a pointer.
 
1040
    */
 
1041
    if ((char*) (intptr_t) value)
 
1042
    {
 
1043
      free((*(char**) variable));
 
1044
      char *tmpptr= strdup((char *) (intptr_t) value);
 
1045
      if (tmpptr != NULL)
 
1046
        *((char**) variable)= tmpptr;
 
1047
    }
 
1048
    break;
 
1049
  default: /* dummy default to avoid compiler warnings */
 
1050
    break;
 
1051
  }
 
1052
  return;
 
1053
}
 
1054
 
 
1055
 
 
1056
/*
 
1057
  Init one value to it's default values
 
1058
 
 
1059
  SYNOPSIS
 
1060
    init_one_value()
 
1061
    option              Option to initialize
 
1062
    value               Pointer to variable
 
1063
*/
 
1064
 
 
1065
static void fini_one_value(const struct my_option *option, char **variable,
 
1066
                           int64_t)
 
1067
{
 
1068
  switch ((option->var_type & GET_TYPE_MASK)) {
 
1069
  case GET_STR_ALLOC:
 
1070
    free((*(char**) variable));
 
1071
    *((char**) variable)= NULL;
 
1072
    break;
 
1073
  default: /* dummy default to avoid compiler warnings */
 
1074
    break;
 
1075
  }
 
1076
  return;
 
1077
}
 
1078
 
 
1079
 
 
1080
void my_cleanup_options(const struct my_option *options)
 
1081
{
 
1082
  init_variables(options, fini_one_value);
 
1083
}
 
1084
 
 
1085
 
 
1086
/*
 
1087
  initialize all variables to their default values
 
1088
 
 
1089
  SYNOPSIS
 
1090
    init_variables()
 
1091
    options             Array of options
 
1092
 
 
1093
  NOTES
 
1094
    We will initialize the value that is pointed to by options->value.
 
1095
    If the value is of type GET_ASK_ADDR, we will also ask for the address
 
1096
    for a value and initialize.
 
1097
*/
 
1098
 
 
1099
static void init_variables(const struct my_option *options,
 
1100
                           init_func_p init_one_value)
 
1101
{
 
1102
  for (; options->name; options++)
 
1103
  {
 
1104
    char* *variable;
 
1105
    /*
 
1106
      We must set u_max_value first as for some variables
 
1107
      options->u_max_value == options->value and in this case we want to
 
1108
      set the value to default value.
 
1109
    */
 
1110
    if (options->u_max_value)
 
1111
      init_one_value(options, options->u_max_value, options->max_value);
 
1112
    if (options->value)
 
1113
      init_one_value(options, options->value, options->def_value);
 
1114
    if (options->var_type & GET_ASK_ADDR &&
 
1115
        (variable= (*getopt_get_addr)("", 0, options)))
 
1116
      init_one_value(options, variable, options->def_value);
 
1117
  }
 
1118
  return;
 
1119
}
 
1120
 
 
1121
 
 
1122
/*
 
1123
  function: my_print_options
 
1124
 
 
1125
  Print help for all options and variables.
 
1126
*/
 
1127
 
 
1128
void my_print_help(const struct my_option *options)
 
1129
{
 
1130
  uint32_t col, name_space= 22, comment_space= 57;
 
1131
  const char *line_end;
 
1132
  const struct my_option *optp;
 
1133
 
 
1134
  for (optp= options; optp->id; optp++)
 
1135
  {
 
1136
    if (optp->id < 256)
 
1137
    {
 
1138
      printf("  -%c%s", optp->id, strlen(optp->name) ? ", " : "  ");
 
1139
      col= 6;
 
1140
    }
 
1141
    else
 
1142
    {
 
1143
      printf("  ");
 
1144
      col= 2;
 
1145
    }
 
1146
    if (strlen(optp->name))
 
1147
    {
 
1148
      printf("--%s", optp->name);
 
1149
      col+= 2 + (uint32_t) strlen(optp->name);
 
1150
      if ((optp->var_type & GET_TYPE_MASK) == GET_STR ||
 
1151
          (optp->var_type & GET_TYPE_MASK) == GET_STR_ALLOC)
 
1152
      {
 
1153
        printf("%s=name%s ", optp->arg_type == OPT_ARG ? "[" : "",
 
1154
               optp->arg_type == OPT_ARG ? "]" : "");
 
1155
        col+= (optp->arg_type == OPT_ARG) ? 8 : 6;
 
1156
      }
 
1157
      else if ((optp->var_type & GET_TYPE_MASK) == GET_NO_ARG ||
 
1158
               (optp->var_type & GET_TYPE_MASK) == GET_BOOL)
 
1159
      {
 
1160
        putchar(' ');
 
1161
        col++;
 
1162
      }
 
1163
      else
 
1164
      {
 
1165
        printf("%s=#%s ", optp->arg_type == OPT_ARG ? "[" : "",
 
1166
               optp->arg_type == OPT_ARG ? "]" : "");
 
1167
        col+= (optp->arg_type == OPT_ARG) ? 5 : 3;
 
1168
      }
 
1169
      if (col > name_space && optp->comment && *optp->comment)
 
1170
      {
 
1171
        putchar('\n');
 
1172
        col= 0;
 
1173
      }
 
1174
    }
 
1175
    for (; col < name_space; col++)
 
1176
      putchar(' ');
 
1177
    if (optp->comment && *optp->comment)
 
1178
    {
 
1179
      const char *comment= _(optp->comment), *end= strchr(comment, '\0');
 
1180
 
 
1181
      while ((uint32_t) (end - comment) > comment_space)
 
1182
      {
 
1183
        for (line_end= comment + comment_space; *line_end != ' '; line_end--)
 
1184
          {}
 
1185
        for (; comment != line_end; comment++)
 
1186
          putchar(*comment);
 
1187
        comment++; /* skip the space, as a newline will take it's place now */
 
1188
        putchar('\n');
 
1189
        for (col= 0; col < name_space; col++)
 
1190
          putchar(' ');
 
1191
      }
 
1192
      printf("%s", comment);
 
1193
    }
 
1194
    putchar('\n');
 
1195
    if ((optp->var_type & GET_TYPE_MASK) == GET_NO_ARG ||
 
1196
             (optp->var_type & GET_TYPE_MASK) == GET_BOOL)
 
1197
    {
 
1198
      if (optp->def_value != 0)
 
1199
      {
 
1200
        printf(_("%*s(Defaults to on; use --skip-%s to disable.)\n"), name_space, "", optp->name);
 
1201
      }
 
1202
    }
 
1203
  }
 
1204
}
 
1205
 
 
1206
 
 
1207
/*
 
1208
  function: my_print_options
 
1209
 
 
1210
  Print variables.
 
1211
*/
 
1212
 
 
1213
void my_print_variables(const struct my_option *options)
 
1214
{
 
1215
  uint32_t name_space= 34, length, nr;
 
1216
  uint64_t bit, llvalue;
 
1217
  char buff[255];
 
1218
  const struct my_option *optp;
 
1219
 
 
1220
  printf(_("\nVariables (--variable-name=value)\n"
 
1221
         "and boolean options {false|true}  Value (after reading options)\n"
 
1222
         "--------------------------------- -----------------------------\n"));
 
1223
  for (optp= options; optp->id; optp++)
 
1224
  {
 
1225
    char* *value= (optp->var_type & GET_ASK_ADDR ?
 
1226
                  (*getopt_get_addr)("", 0, optp) : optp->value);
 
1227
    if (value)
 
1228
    {
 
1229
      printf("%s ", optp->name);
 
1230
      length= (uint32_t) strlen(optp->name)+1;
 
1231
      for (; length < name_space; length++)
 
1232
        putchar(' ');
 
1233
      switch ((optp->var_type & GET_TYPE_MASK)) {
 
1234
      case GET_SET:
 
1235
        if (!(llvalue= *(uint64_t*) value))
 
1236
          printf("%s\n", _("(No default value)"));
 
1237
        else
 
1238
        for (nr= 0, bit= 1; llvalue && nr < optp->typelib->count; nr++, bit<<=1)
 
1239
        {
 
1240
          if (!(bit & llvalue))
 
1241
            continue;
 
1242
          llvalue&= ~bit;
 
1243
          printf( llvalue ? "%s," : "%s\n", get_type(optp->typelib, nr));
 
1244
        }
 
1245
        break;
 
1246
      case GET_ENUM:
 
1247
        printf("%s\n", get_type(optp->typelib, *(uint*) value));
 
1248
        break;
 
1249
      case GET_STR:
 
1250
      case GET_STR_ALLOC:                    /* fall through */
 
1251
        printf("%s\n", *((char**) value) ? *((char**) value) :
 
1252
               _("(No default value)"));
 
1253
        break;
 
1254
      case GET_BOOL:
 
1255
        printf("%s\n", *((bool*) value) ? _("true") : _("false"));
 
1256
        break;
 
1257
      case GET_INT:
 
1258
        printf("%d\n", *((int*) value));
 
1259
        break;
 
1260
      case GET_UINT:
 
1261
        printf("%d\n", *((uint*) value));
 
1262
        break;
 
1263
      case GET_LONG:
 
1264
        printf("%ld\n", *((long*) value));
 
1265
        break;
 
1266
      case GET_UINT32:
 
1267
        printf("%u\n", *((uint32_t*) value));
 
1268
        break;
 
1269
      case GET_ULONG_IS_FAIL:
 
1270
        printf("%lu\n", *((ulong*) value));
 
1271
        break;
 
1272
      case GET_SIZE:
 
1273
        int64_t2str((uint64_t)(*(size_t*)value), buff, 10);
 
1274
        printf("%s\n", buff);
 
1275
        break;
 
1276
      case GET_LL:
 
1277
        printf("%s\n", llstr(*((int64_t*) value), buff));
 
1278
        break;
 
1279
      case GET_ULL:
 
1280
      case GET_UINT64:
 
1281
        int64_t2str(*((uint64_t*) value), buff, 10);
 
1282
        printf("%s\n", buff);
 
1283
        break;
 
1284
      case GET_DOUBLE:
 
1285
        printf("%g\n", *(double*) value);
 
1286
        break;
 
1287
      default:
 
1288
        printf(_("(Disabled)\n"));
 
1289
        break;
 
1290
      }
 
1291
    }
 
1292
  }
 
1293
}