~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/my_getopt.cc

  • Committer: Siddharth Prakash Singh
  • Date: 2010-03-26 19:25:23 UTC
  • mfrom: (1410 drizzle)
  • mto: This revision was merged to the branch mainline in revision 1425.
  • Revision ID: spsneo@spsneo-laptop-20100326192523-ibjlbt1p692vobtj
merging with trunk

Show diffs side-by-side

added added

removed removed

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