~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/my_getopt.cc

  • Committer: Andrew Hutchings
  • Date: 2010-03-26 14:54:21 UTC
  • mto: This revision was merged to the branch mainline in revision 1423.
  • Revision ID: andrew.hutchings@sun.com-20100326145421-dtyc5vkmouax01c7
Drop indentation inside namespace one level

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
 
  /*
 
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
94
function: handle_options
95
95
 
96
96
Sort options; put options first, until special end of options (--), or
98
98
one of the options in struct 'my_option', return error in case of ambiguous
99
99
or unknown option. Check that option was given an argument if it requires
100
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)
 
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++)
108
126
  {
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++)
 
127
    char **first= pos;
 
128
    char *cur_arg= *pos;
 
129
    if (cur_arg[0] == '-' && cur_arg[1] && !end_of_options) /* must be opt */
126
130
    {
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
 
          }
 
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;
204
173
          else
205
174
          {
206
 
            length= static_cast<uint32_t>(strlen(opt_str));
207
 
            optend= 0;
208
 
          }
 
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
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
        {
210
217
          /*
211
 
             Find first the right option. Return error in case of an ambiguous,
212
 
             or unknown option
 
218
             Didn't find any matching option. Let's see if someone called
 
219
             option with a special option prefix
213
220
           */
214
 
          optp= longopts;
215
 
          if (!(opt_found= findopt(opt_str, length, &optp, &prev_found)))
 
221
          if (!must_be_var)
216
222
          {
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)
 
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]] == '_'))
279
231
              {
280
232
                /*
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
 
233
                   We were called with a special prefix, we can reuse opt_found
285
234
                 */
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;
 
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 */
313
273
              }
314
274
            }
315
275
          }
316
 
          if (opt_found > 1)
 
276
          if (!opt_found)
317
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
            }
318
291
            if (must_be_var)
319
292
            {
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;
 
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;
324
299
            }
325
300
            else
326
301
            {
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;
 
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;
332
308
            }
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
309
            if (option_is_loose)
341
310
            {
342
311
              (*argc)--;
343
312
              continue;
344
313
            }
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",
 
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",
351
363
                internal::my_progname, optp->name);
352
364
            return EXIT_NO_ARGUMENT_ALLOWED;
353
365
          }
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
 
              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)
 
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"))
402
379
              *((bool*) value)= (bool) 0;
403
380
            else
404
381
            {
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
 
          }
 
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;
424
403
          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++)
 
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)
433
435
            {
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
 
                }
 
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;
502
449
                error= get_one_option(optp->id, optp, argument);
503
450
                if (error != 0)
504
451
                  return error;
505
452
                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
 
        {
522
 
          my_getopt_error_reporter(ERROR_LEVEL,
523
 
              "%s: Error while setting value '%s' to '%s'",
524
 
              internal::my_progname, argument, optp->name);
525
 
          return error;
526
 
        }
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;
 
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
      {
 
522
        my_getopt_error_reporter(ERROR_LEVEL,
 
523
            "%s: Error while setting value '%s' to '%s'",
 
524
            internal::my_progname, argument, optp->name);
 
525
        return error;
 
526
      }
 
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 */
535
532
    }
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;
 
533
    else /* non-option found */
 
534
      (*argv)[argvpos++]= cur_arg;
544
535
  }
545
 
 
546
 
 
547
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
548
function: check_struct_option
549
549
 
550
550
Arguments: Current argument under processing from argv and a variable
556
556
option, returns a pointer to the argument.
557
557
 
558
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.
559
574
   */
560
 
 
561
 
  static char *check_struct_option(char *cur_arg, char *key_name)
 
575
  if ((ptr != NULL) && (end != NULL) && (end - ptr > 1))
562
576
  {
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;
 
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;
584
581
  }
 
582
  key_name[0]= 0;
 
583
  return cur_arg;
 
584
}
585
585
 
586
 
  /*
 
586
/*
587
587
function: setval
588
588
 
589
589
Arguments: opts, argument
590
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)
 
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)
595
599
  {
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
 
      }
657
 
      if (err)
658
 
        return EXIT_UNKNOWN_SUFFIX;
 
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;
659
656
    }
660
 
    return 0;
 
657
    if (err)
 
658
      return EXIT_UNKNOWN_SUFFIX;
661
659
  }
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
 
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
682
#   Number of matching options
683
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)
 
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++)
689
694
  {
690
 
    uint32_t count;
691
 
    struct my_option *opt= (struct my_option *) *opt_res;
692
 
 
693
 
    for (count= 0; opt->name; opt++)
 
695
    if (!getopt_compare_strings(opt->name, optpat, length)) /* match found */
694
696
    {
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
 
        }
 
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++;
713
712
      }
714
713
    }
715
 
    return count;
716
714
  }
717
 
 
718
 
 
719
 
  /*
 
715
  return count;
 
716
}
 
717
 
 
718
 
 
719
/*
720
720
function: compare_strings
721
721
 
722
722
Works like strncmp, other than 1.) considers '-' and '_' the same.
723
723
2.) Returns -1 if strings differ, 0 if they are equal
724
 
   */
 
724
 */
725
725
 
726
 
  bool getopt_compare_strings(register const char *s, register const char *t,
727
 
      uint32_t length)
 
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++)
728
731
  {
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;
 
732
    if ((*s != '-' ? *s : '_') != (*t != '-' ? *t : '_'))
 
733
      return 1;
736
734
  }
 
735
  return 0;
 
736
}
737
737
 
738
 
  /*
 
738
/*
739
739
function: eval_num_suffix
740
740
 
741
741
Transforms a number with a suffix to real number. Suffix can
742
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
 
  /*
 
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
778
function: getopt_ll
779
779
 
780
780
Evaluates and returns the value that user gave as an argument
783
783
defined in the given my_option struct, this function will check
784
784
that those values are honored.
785
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
 
  /*
 
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
795
function: getopt_ll_limit_value
796
796
 
797
797
Applies min/max/block_size to a numeric value of an option.
798
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
 
  /*
 
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
855
function: getopt_ull
856
856
 
857
857
This is the same as getopt_ll, but is meant for uint64_t
858
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:
992
 
      case GET_ENUM:
993
 
        *((uint*) variable)= (uint32_t) value;
994
 
        break;
995
 
      case GET_LONG:
996
 
        *((long*) variable)= (long) value;
997
 
        break;
998
 
      case GET_UINT32:
999
 
        *((uint32_t*) variable)= (uint32_t) value;
1000
 
        break;
1001
 
      case GET_ULONG_IS_FAIL:
1002
 
        *((ulong*) variable)= (ulong) value;
1003
 
        break;
1004
 
      case GET_LL:
1005
 
        *((int64_t*) variable)= (int64_t) value;
1006
 
        break;
1007
 
      case GET_SIZE:
1008
 
        *((size_t*) variable)= (size_t) value;
1009
 
        break;
1010
 
      case GET_ULL:
1011
 
      case GET_SET:
1012
 
      case GET_UINT64:
1013
 
        *((uint64_t*) variable)=  (uint64_t) value;
1014
 
        break;
1015
 
      case GET_DOUBLE:
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:
 
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:
 
992
    case GET_ENUM:
 
993
      *((uint*) variable)= (uint32_t) value;
 
994
      break;
 
995
    case GET_LONG:
 
996
      *((long*) variable)= (long) value;
 
997
      break;
 
998
    case GET_UINT32:
 
999
      *((uint32_t*) variable)= (uint32_t) value;
 
1000
      break;
 
1001
    case GET_ULONG_IS_FAIL:
 
1002
      *((ulong*) variable)= (ulong) value;
 
1003
      break;
 
1004
    case GET_LL:
 
1005
      *((int64_t*) variable)= (int64_t) value;
 
1006
      break;
 
1007
    case GET_SIZE:
 
1008
      *((size_t*) variable)= (size_t) value;
 
1009
      break;
 
1010
    case GET_ULL:
 
1011
    case GET_SET:
 
1012
    case GET_UINT64:
 
1013
      *((uint64_t*) variable)=  (uint64_t) value;
 
1014
      break;
 
1015
    case GET_DOUBLE:
 
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
      {
1064
1037
        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
 
  /*
 
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
1117
function: my_print_options
1118
1118
 
1119
1119
Print help for all options and variables.
1120
 
   */
1121
 
 
1122
 
  void my_print_help(const struct my_option *options)
 
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++)
1123
1129
  {
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;
 
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++;
1134
1156
      }
1135
1157
      else
1136
1158
      {
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
 
        {
 
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++)
1154
1184
          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
 
        }
 
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);
1196
1195
      }
1197
1196
    }
1198
1197
  }
1199
 
 
1200
 
 
1201
 
  /*
 
1198
}
 
1199
 
 
1200
 
 
1201
/*
1202
1202
function: my_print_options
1203
1203
 
1204
1204
Print variables.
1205
 
   */
1206
 
 
1207
 
  void my_print_variables(const struct my_option *options)
 
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++)
1208
1218
  {
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++)
 
1219
    char* *value= (optp->var_type & GET_ASK_ADDR ?
 
1220
        (*getopt_get_addr)("", 0, optp) : optp->value);
 
1221
    if (value)
1218
1222
    {
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
 
        }
 
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;
1285
1284
      }
1286
1285
    }
1287
1286
  }
 
1287
}
1288
1288
 
1289
1289
} /* namespace drizzled */