~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/option.cc

  • Committer: Olaf van der Spek
  • Date: 2011-07-04 19:11:47 UTC
  • mto: This revision was merged to the branch mainline in revision 2367.
  • Revision ID: olafvdspek@gmail.com-20110704191147-s99ojek811zi1fzj
RemoveĀ unusedĀ Name_resolution_context::error_reporter

Show diffs side-by-side

added added

removed removed

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