~drizzle-trunk/drizzle/development

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