~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to mysys/my_getopt.cc

  • Committer: Monty Taylor
  • Date: 2009-04-14 19:16:51 UTC
  • mto: (997.2.5 mordred)
  • mto: This revision was merged to the branch mainline in revision 994.
  • Revision ID: mordred@inaugust.com-20090414191651-ltbww6hpqks8k7qk
Clarified instructions in README.

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