~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/option.cc

  • Committer: Lee Bieber
  • Date: 2011-04-14 19:29:43 UTC
  • mfrom: (2278.1.2 build)
  • Revision ID: kalebral@gmail.com-20110414192943-q1nxcdqupal0anjb
Merge Olaf - Refactor Table Cache
Merge Olaf - Delete unused functions

Show diffs side-by-side

added added

removed removed

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