~ubuntu-branches/ubuntu/hardy/gengetopt/hardy

« back to all changes in this revision

Viewing changes to tests/test_modes_cmd.c.test

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2008-01-29 14:55:40 UTC
  • mfrom: (1.1.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20080129145540-bkah1bl330gpelmh
Tags: 2.22-1ubuntu1
* Merge with Debian; remaining changes:
  - Fix build failures with g++-4.3.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
  File autogenerated by gengetopt 
 
3
  generated with the following command:
 
4
  ../src/gengetopt --gen-version --input=test_modes_cmd.ggo --func-name=test_modes_cmd_parser --file-name=test_modes_cmd --unamed-opt --show-required 
 
5
 
 
6
  The developers of gengetopt consider the fixed text that goes in all
 
7
  gengetopt output files to be in the public domain:
 
8
  we make no copyright claims on it.
 
9
*/
 
10
 
 
11
/* If we use autoconf.  */
 
12
#ifdef HAVE_CONFIG_H
 
13
#include "config.h"
 
14
#endif
 
15
 
 
16
#include <stdio.h>
 
17
#include <stdlib.h>
 
18
#include <string.h>
 
19
 
 
20
#include "getopt.h"
 
21
 
 
22
#include "test_modes_cmd.h"
 
23
 
 
24
const char *gengetopt_args_info_purpose = "";
 
25
 
 
26
const char *gengetopt_args_info_usage = "Usage: test_modes [OPTIONS]... [FILES]...";
 
27
 
 
28
const char *gengetopt_args_info_description = "";
 
29
 
 
30
const char *gengetopt_args_info_help[] = {
 
31
  "  -h, --help              Print help and exit",
 
32
  "  -V, --version           Print version and exit",
 
33
  "\nsome non mode options:",
 
34
  "  -N, --no-mode           a generic option not beloging to any mode",
 
35
  "      --no-mode2=STRING   another generic option not beloging to any mode",
 
36
  "\nsome modes just for testing:",
 
37
  "\n Mode: mode1\n  any option of this mode is in contrast with any option of the other mode\n  Notice that this description is quite long so it may spawn many lines...      \n          fortunately gengetopt will wrap it for you :-)",
 
38
  "  -a, --opta              string a",
 
39
  "  -A, --optA[=STRING]     string A (mandatory)",
 
40
  "  -M, --optAmul[=STRING]  string M",
 
41
  "  -b, --optb              string b",
 
42
  "\n Mode: mode 2",
 
43
  "      --optc              string c",
 
44
  "  -d, --optd              string d (mandatory)",
 
45
  "\n Mode: my mode",
 
46
  "  -m, --mopt=INT          option of my mode",
 
47
    0
 
48
};
 
49
 
 
50
typedef enum {ARG_NO
 
51
  , ARG_STRING
 
52
  , ARG_INT
 
53
} test_modes_cmd_parser_arg_type;
 
54
 
 
55
static
 
56
void clear_given (struct gengetopt_args_info *args_info);
 
57
static
 
58
void clear_args (struct gengetopt_args_info *args_info);
 
59
 
 
60
static int
 
61
test_modes_cmd_parser_internal (int argc, char * const *argv, struct gengetopt_args_info *args_info,
 
62
                        struct test_modes_cmd_parser_params *params, const char *additional_error);
 
63
 
 
64
static int
 
65
test_modes_cmd_parser_required2 (struct gengetopt_args_info *args_info, const char *prog_name, const char *additional_error);
 
66
 
 
67
static char *
 
68
gengetopt_strdup (const char *s);
 
69
 
 
70
static
 
71
void clear_given (struct gengetopt_args_info *args_info)
 
72
{
 
73
  args_info->help_given = 0 ;
 
74
  args_info->version_given = 0 ;
 
75
  args_info->no_mode_given = 0 ;
 
76
  args_info->no_mode2_given = 0 ;
 
77
  args_info->opta_given = 0 ;
 
78
  args_info->optA_given = 0 ;
 
79
  args_info->optAmul_given = 0 ;
 
80
  args_info->optb_given = 0 ;
 
81
  args_info->optc_given = 0 ;
 
82
  args_info->optd_given = 0 ;
 
83
  args_info->mopt_given = 0 ;
 
84
  args_info->mode_2_mode_counter = 0 ;
 
85
  args_info->mode1_mode_counter = 0 ;
 
86
  args_info->my_mode_mode_counter = 0 ;
 
87
}
 
88
 
 
89
static
 
90
void clear_args (struct gengetopt_args_info *args_info)
 
91
{
 
92
  args_info->no_mode2_arg = NULL;
 
93
  args_info->no_mode2_orig = NULL;
 
94
  args_info->optA_arg = NULL;
 
95
  args_info->optA_orig = NULL;
 
96
  args_info->optAmul_arg = NULL;
 
97
  args_info->optAmul_orig = NULL;
 
98
  args_info->mopt_orig = NULL;
 
99
  
 
100
}
 
101
 
 
102
static
 
103
void init_args_info(struct gengetopt_args_info *args_info)
 
104
{
 
105
 
 
106
 
 
107
  args_info->help_help = gengetopt_args_info_help[0] ;
 
108
  args_info->version_help = gengetopt_args_info_help[1] ;
 
109
  args_info->no_mode_help = gengetopt_args_info_help[3] ;
 
110
  args_info->no_mode2_help = gengetopt_args_info_help[4] ;
 
111
  args_info->opta_help = gengetopt_args_info_help[7] ;
 
112
  args_info->opta_min = -1;
 
113
  args_info->opta_max = -1;
 
114
  args_info->optA_help = gengetopt_args_info_help[8] ;
 
115
  args_info->optAmul_help = gengetopt_args_info_help[9] ;
 
116
  args_info->optAmul_min = -1;
 
117
  args_info->optAmul_max = -1;
 
118
  args_info->optb_help = gengetopt_args_info_help[10] ;
 
119
  args_info->optc_help = gengetopt_args_info_help[12] ;
 
120
  args_info->optd_help = gengetopt_args_info_help[13] ;
 
121
  args_info->mopt_help = gengetopt_args_info_help[15] ;
 
122
  
 
123
}
 
124
 
 
125
void
 
126
test_modes_cmd_parser_print_version (void)
 
127
{
 
128
  printf ("%s %s\n", TEST_MODES_CMD_PARSER_PACKAGE, TEST_MODES_CMD_PARSER_VERSION);
 
129
}
 
130
 
 
131
static void print_help_common(void) {
 
132
  test_modes_cmd_parser_print_version ();
 
133
 
 
134
  if (strlen(gengetopt_args_info_purpose) > 0)
 
135
    printf("\n%s\n", gengetopt_args_info_purpose);
 
136
 
 
137
  if (strlen(gengetopt_args_info_usage) > 0)
 
138
    printf("\n%s\n", gengetopt_args_info_usage);
 
139
 
 
140
  printf("\n");
 
141
 
 
142
  if (strlen(gengetopt_args_info_description) > 0)
 
143
    printf("%s\n", gengetopt_args_info_description);
 
144
}
 
145
 
 
146
void
 
147
test_modes_cmd_parser_print_help (void)
 
148
{
 
149
  int i = 0;
 
150
  print_help_common();
 
151
  while (gengetopt_args_info_help[i])
 
152
    printf("%s\n", gengetopt_args_info_help[i++]);
 
153
}
 
154
 
 
155
void
 
156
test_modes_cmd_parser_init (struct gengetopt_args_info *args_info)
 
157
{
 
158
  clear_given (args_info);
 
159
  clear_args (args_info);
 
160
  init_args_info (args_info);
 
161
 
 
162
  args_info->inputs = NULL;
 
163
  args_info->inputs_num = 0;
 
164
}
 
165
 
 
166
void
 
167
test_modes_cmd_parser_params_init(struct test_modes_cmd_parser_params *params)
 
168
{
 
169
  if (params)
 
170
    { 
 
171
      params->override = 0;
 
172
      params->initialize = 1;
 
173
      params->check_required = 1;
 
174
      params->check_ambiguity = 0;
 
175
      params->print_errors = 1;
 
176
    }
 
177
}
 
178
 
 
179
struct test_modes_cmd_parser_params *
 
180
test_modes_cmd_parser_params_create(void)
 
181
{
 
182
  struct test_modes_cmd_parser_params *params = 
 
183
    (struct test_modes_cmd_parser_params *)malloc(sizeof(struct test_modes_cmd_parser_params));
 
184
  test_modes_cmd_parser_params_init(params);  
 
185
  return params;
 
186
}
 
187
 
 
188
static void
 
189
free_string_field (char **s)
 
190
{
 
191
  if (*s)
 
192
    {
 
193
      free (*s);
 
194
      *s = 0;
 
195
    }
 
196
}
 
197
 
 
198
/** @brief generic value variable */
 
199
union generic_value {
 
200
    int int_arg;
 
201
    char *string_arg;
 
202
};
 
203
 
 
204
/** @brief holds temporary values for multiple options */
 
205
struct generic_list
 
206
{
 
207
  union generic_value arg;
 
208
  char *orig;
 
209
  struct generic_list *next;
 
210
};
 
211
 
 
212
/**
 
213
 * @brief add a node at the head of the list 
 
214
 */
 
215
static void add_node(struct generic_list **list) {
 
216
  struct generic_list *new_node = (struct generic_list *) malloc (sizeof (struct generic_list));
 
217
  new_node->next = *list;
 
218
  *list = new_node;
 
219
  new_node->arg.string_arg = NULL;
 
220
  new_node->orig = NULL;
 
221
}
 
222
 
 
223
 
 
224
static void
 
225
free_multiple_string_field(unsigned int len, char ***arg, char ***orig)
 
226
{
 
227
  unsigned int i;
 
228
  if (*arg) {
 
229
    for (i = 0; i < len; ++i)
 
230
      {
 
231
        free_string_field(&((*arg)[i]));
 
232
        free_string_field(&((*orig)[i]));
 
233
      }
 
234
    free_string_field(&((*arg)[0])); /* free default string */
 
235
 
 
236
    free (*arg);
 
237
    *arg = 0;
 
238
    free (*orig);
 
239
    *orig = 0;
 
240
  }
 
241
}
 
242
 
 
243
static void
 
244
test_modes_cmd_parser_release (struct gengetopt_args_info *args_info)
 
245
{
 
246
  unsigned int i;
 
247
  free_string_field (&(args_info->no_mode2_arg));
 
248
  free_string_field (&(args_info->no_mode2_orig));
 
249
  free_string_field (&(args_info->optA_arg));
 
250
  free_string_field (&(args_info->optA_orig));
 
251
  free_multiple_string_field (args_info->optAmul_given, &(args_info->optAmul_arg), &(args_info->optAmul_orig));
 
252
  free_string_field (&(args_info->mopt_orig));
 
253
  
 
254
  
 
255
  for (i = 0; i < args_info->inputs_num; ++i)
 
256
    free (args_info->inputs [i]);
 
257
 
 
258
  if (args_info->inputs_num)
 
259
    free (args_info->inputs);
 
260
 
 
261
  clear_given (args_info);
 
262
}
 
263
 
 
264
 
 
265
static void
 
266
write_into_file(FILE *outfile, const char *opt, const char *arg, char *values[])
 
267
{
 
268
  if (arg) {
 
269
    fprintf(outfile, "%s=\"%s\"\n", opt, arg);
 
270
  } else {
 
271
    fprintf(outfile, "%s\n", opt);
 
272
  }
 
273
}
 
274
 
 
275
static void
 
276
write_multiple_into_file(FILE *outfile, int len, const char *opt, char **arg, char *values[])
 
277
{
 
278
  int i;
 
279
  
 
280
  for (i = 0; i < len; ++i)
 
281
    write_into_file(outfile, opt, (arg ? arg[i] : 0), values);
 
282
}
 
283
 
 
284
int
 
285
test_modes_cmd_parser_dump(FILE *outfile, struct gengetopt_args_info *args_info)
 
286
{
 
287
  int i = 0;
 
288
 
 
289
  if (!outfile)
 
290
    {
 
291
      fprintf (stderr, "%s: cannot dump options to stream\n", TEST_MODES_CMD_PARSER_PACKAGE);
 
292
      return EXIT_FAILURE;
 
293
    }
 
294
 
 
295
  if (args_info->help_given)
 
296
    write_into_file(outfile, "help", 0, 0 );
 
297
  if (args_info->version_given)
 
298
    write_into_file(outfile, "version", 0, 0 );
 
299
  if (args_info->no_mode_given)
 
300
    write_into_file(outfile, "no-mode", 0, 0 );
 
301
  if (args_info->no_mode2_given)
 
302
    write_into_file(outfile, "no-mode2", args_info->no_mode2_orig, 0);
 
303
  write_multiple_into_file(outfile, args_info->opta_given, "opta", 0, 0);
 
304
  if (args_info->optA_given)
 
305
    write_into_file(outfile, "optA", args_info->optA_orig, 0);
 
306
  write_multiple_into_file(outfile, args_info->optAmul_given, "optAmul", args_info->optAmul_orig, 0);
 
307
  if (args_info->optb_given)
 
308
    write_into_file(outfile, "optb", 0, 0 );
 
309
  if (args_info->optc_given)
 
310
    write_into_file(outfile, "optc", 0, 0 );
 
311
  if (args_info->optd_given)
 
312
    write_into_file(outfile, "optd", 0, 0 );
 
313
  if (args_info->mopt_given)
 
314
    write_into_file(outfile, "mopt", args_info->mopt_orig, 0);
 
315
  
 
316
 
 
317
  i = EXIT_SUCCESS;
 
318
  return i;
 
319
}
 
320
 
 
321
int
 
322
test_modes_cmd_parser_file_save(const char *filename, struct gengetopt_args_info *args_info)
 
323
{
 
324
  FILE *outfile;
 
325
  int i = 0;
 
326
 
 
327
  outfile = fopen(filename, "w");
 
328
 
 
329
  if (!outfile)
 
330
    {
 
331
      fprintf (stderr, "%s: cannot open file for writing: %s\n", TEST_MODES_CMD_PARSER_PACKAGE, filename);
 
332
      return EXIT_FAILURE;
 
333
    }
 
334
 
 
335
  i = test_modes_cmd_parser_dump(outfile, args_info);
 
336
  fclose (outfile);
 
337
 
 
338
  return i;
 
339
}
 
340
 
 
341
void
 
342
test_modes_cmd_parser_free (struct gengetopt_args_info *args_info)
 
343
{
 
344
  test_modes_cmd_parser_release (args_info);
 
345
}
 
346
 
 
347
/** @brief replacement of strdup, which is not standard */
 
348
char *
 
349
gengetopt_strdup (const char *s)
 
350
{
 
351
  char *result = NULL;
 
352
  if (!s)
 
353
    return result;
 
354
 
 
355
  result = (char*)malloc(strlen(s) + 1);
 
356
  if (result == (char*)0)
 
357
    return (char*)0;
 
358
  strcpy(result, s);
 
359
  return result;
 
360
}
 
361
 
 
362
static char *
 
363
get_multiple_arg_token(const char *arg)
 
364
{
 
365
  char *tok, *ret;
 
366
  size_t len, num_of_escape;
 
367
  int i, j;
 
368
 
 
369
  if (!arg)
 
370
    return NULL;
 
371
 
 
372
  tok = strchr (arg, ',');
 
373
  num_of_escape = 0;
 
374
 
 
375
  /* make sure it is not escaped */
 
376
  while (tok)
 
377
    {
 
378
      if (*(tok-1) == '\\')
 
379
        {
 
380
          /* find the next one */
 
381
          tok = strchr (tok+1, ',');
 
382
          ++num_of_escape;
 
383
        }
 
384
      else
 
385
        break;
 
386
    }
 
387
 
 
388
  if (tok)
 
389
    len = (size_t)(tok - arg + 1);
 
390
  else
 
391
    len = strlen (arg) + 1;
 
392
 
 
393
  len -= num_of_escape;
 
394
 
 
395
  ret = (char *) malloc (len);
 
396
 
 
397
  i = 0;
 
398
  j = 0;
 
399
  while (arg[i] && (j < len-1))
 
400
    {
 
401
      if (arg[i] == '\\' && 
 
402
          arg[ i + 1 ] && 
 
403
          arg[ i + 1 ] == ',')
 
404
        ++i;
 
405
 
 
406
      ret[j++] = arg[i++];
 
407
    }
 
408
 
 
409
  ret[len-1] = '\0';
 
410
 
 
411
  return ret;
 
412
}
 
413
 
 
414
static char *
 
415
get_multiple_arg_token_next(const char *arg)
 
416
{
 
417
  char *tok;
 
418
 
 
419
  if (!arg)
 
420
    return NULL;
 
421
 
 
422
  tok = strchr (arg, ',');
 
423
 
 
424
  /* make sure it is not escaped */
 
425
  while (tok)
 
426
    {
 
427
      if (*(tok-1) == '\\')
 
428
        {
 
429
          /* find the next one */
 
430
          tok = strchr (tok+1, ',');
 
431
        }
 
432
      else
 
433
        break;
 
434
    }
 
435
 
 
436
  if (! tok || strlen(tok) == 1)
 
437
    return 0;
 
438
 
 
439
  return tok+1;
 
440
}
 
441
 
 
442
static int
 
443
check_multiple_option_occurrences(const char *prog_name, unsigned int option_given, int min, int max, const char *option_desc);
 
444
 
 
445
int
 
446
check_multiple_option_occurrences(const char *prog_name, unsigned int option_given, int min, int max, const char *option_desc)
 
447
{
 
448
  int error = 0;
 
449
 
 
450
  if (option_given && ! (min < 0 && max < 0))
 
451
    {
 
452
      if (min >= 0 && max >= 0)
 
453
        {
 
454
          if (min == max)
 
455
            {
 
456
              /* specific occurrences */
 
457
              if (option_given != min)
 
458
                {
 
459
                  fprintf (stderr, "%s: %s option occurrences must be %d\n",
 
460
                    prog_name, option_desc, min);
 
461
                  error = 1;
 
462
                }
 
463
            }
 
464
          else if (option_given < min
 
465
              || option_given > max)
 
466
            {
 
467
              /* range occurrences */
 
468
              fprintf (stderr, "%s: %s option occurrences must be between %d and %d\n",
 
469
                prog_name, option_desc, min, max);
 
470
              error = 1;
 
471
            }
 
472
        }
 
473
      else if (min >= 0)
 
474
        {
 
475
          /* at least check */
 
476
          if (option_given < min)
 
477
            {
 
478
              fprintf (stderr, "%s: %s option occurrences must be at least %d\n",
 
479
                prog_name, option_desc, min);
 
480
              error = 1;
 
481
            }
 
482
        }
 
483
      else if (max >= 0)
 
484
        {
 
485
          /* at most check */
 
486
          if (option_given > max)
 
487
            {
 
488
              fprintf (stderr, "%s: %s option occurrences must be at most %d\n",
 
489
                prog_name, option_desc, max);
 
490
              error = 1;
 
491
            }
 
492
        }
 
493
    }
 
494
    
 
495
  return error;
 
496
}
 
497
int
 
498
test_modes_cmd_parser (int argc, char * const *argv, struct gengetopt_args_info *args_info)
 
499
{
 
500
  return test_modes_cmd_parser2 (argc, argv, args_info, 0, 1, 1);
 
501
}
 
502
 
 
503
int
 
504
test_modes_cmd_parser_ext (int argc, char * const *argv, struct gengetopt_args_info *args_info,
 
505
                   struct test_modes_cmd_parser_params *params)
 
506
{
 
507
  int result;
 
508
  result = test_modes_cmd_parser_internal (argc, argv, args_info, params, NULL);
 
509
 
 
510
  if (result == EXIT_FAILURE)
 
511
    {
 
512
      test_modes_cmd_parser_free (args_info);
 
513
      exit (EXIT_FAILURE);
 
514
    }
 
515
  
 
516
  return result;
 
517
}
 
518
 
 
519
int
 
520
test_modes_cmd_parser2 (int argc, char * const *argv, struct gengetopt_args_info *args_info, int override, int initialize, int check_required)
 
521
{
 
522
  int result;
 
523
  struct test_modes_cmd_parser_params params;
 
524
  
 
525
  params.override = override;
 
526
  params.initialize = initialize;
 
527
  params.check_required = check_required;
 
528
  params.check_ambiguity = 0;
 
529
  params.print_errors = 1;
 
530
 
 
531
  result = test_modes_cmd_parser_internal (argc, argv, args_info, &params, NULL);
 
532
 
 
533
  if (result == EXIT_FAILURE)
 
534
    {
 
535
      test_modes_cmd_parser_free (args_info);
 
536
      exit (EXIT_FAILURE);
 
537
    }
 
538
  
 
539
  return result;
 
540
}
 
541
 
 
542
int
 
543
test_modes_cmd_parser_required (struct gengetopt_args_info *args_info, const char *prog_name)
 
544
{
 
545
  int result = EXIT_SUCCESS;
 
546
 
 
547
  if (test_modes_cmd_parser_required2(args_info, prog_name, NULL) > 0)
 
548
    result = EXIT_FAILURE;
 
549
 
 
550
  if (result == EXIT_FAILURE)
 
551
    {
 
552
      test_modes_cmd_parser_free (args_info);
 
553
      exit (EXIT_FAILURE);
 
554
    }
 
555
  
 
556
  return result;
 
557
}
 
558
 
 
559
int
 
560
test_modes_cmd_parser_required2 (struct gengetopt_args_info *args_info, const char *prog_name, const char *additional_error)
 
561
{
 
562
  int error = 0;
 
563
 
 
564
  /* checks for required options */
 
565
  if (args_info->mode1_mode_counter && check_multiple_option_occurrences(prog_name, args_info->opta_given, args_info->opta_min, args_info->opta_max, "'--opta' ('-a')"))
 
566
     error = 1;
 
567
  
 
568
  if (args_info->mode1_mode_counter && ! args_info->optA_given)
 
569
    {
 
570
      fprintf (stderr, "%s: '--optA' ('-A') option required%s\n", prog_name, (additional_error ? additional_error : ""));
 
571
      error = 1;
 
572
    }
 
573
  
 
574
  if (args_info->mode1_mode_counter && check_multiple_option_occurrences(prog_name, args_info->optAmul_given, args_info->optAmul_min, args_info->optAmul_max, "'--optAmul' ('-M')"))
 
575
     error = 1;
 
576
  
 
577
  if (args_info->mode_2_mode_counter && ! args_info->optd_given)
 
578
    {
 
579
      fprintf (stderr, "%s: '--optd' ('-d') option required%s\n", prog_name, (additional_error ? additional_error : ""));
 
580
      error = 1;
 
581
    }
 
582
  
 
583
  
 
584
  /* checks for dependences among options */
 
585
 
 
586
  return error;
 
587
}
 
588
 
 
589
 
 
590
static char *package_name = 0;
 
591
 
 
592
/**
 
593
 * @brief updates an option
 
594
 * @param field the generic pointer to the field to update
 
595
 * @param orig_field the pointer to the orig field
 
596
 * @param field_given the pointer to the number of occurrence of this option
 
597
 * @param prev_given the pointer to the number of occurrence already seen
 
598
 * @param value the argument for this option (if null no arg was specified)
 
599
 * @param possible_values the possible values for this option (if specified)
 
600
 * @param default_value the default value (in case the option only accepts fixed values)
 
601
 * @param arg_type the type of this option
 
602
 * @param check_ambiguity @see test_modes_cmd_parser_params.check_ambiguity
 
603
 * @param override @see test_modes_cmd_parser_params.override
 
604
 * @param no_free whether to free a possible previous value
 
605
 * @param multiple_option whether this is a multiple option
 
606
 * @param long_opt the corresponding long option
 
607
 * @param short_opt the corresponding short option (or '-' if none)
 
608
 * @param additional_error possible further error specification
 
609
 */
 
610
static
 
611
int update_arg(void *field, char **orig_field,
 
612
               unsigned int *field_given, unsigned int *prev_given, 
 
613
               char *value, char *possible_values[], const char *default_value,
 
614
               test_modes_cmd_parser_arg_type arg_type,
 
615
               int check_ambiguity, int override,
 
616
               int no_free, int multiple_option,
 
617
               const char *long_opt, char short_opt,
 
618
               const char *additional_error)
 
619
{
 
620
  char *stop_char = 0;
 
621
  const char *val = value;
 
622
  int found;
 
623
  char **string_field;
 
624
 
 
625
  stop_char = 0;
 
626
  found = 0;
 
627
 
 
628
  if (!multiple_option && prev_given && (*prev_given || (check_ambiguity && *field_given)))
 
629
    {
 
630
      if (short_opt != '-')
 
631
        fprintf (stderr, "%s: `--%s' (`-%c') option given more than once%s\n", 
 
632
               package_name, long_opt, short_opt,
 
633
               (additional_error ? additional_error : ""));
 
634
      else
 
635
        fprintf (stderr, "%s: `--%s' option given more than once%s\n", 
 
636
               package_name, long_opt,
 
637
               (additional_error ? additional_error : ""));
 
638
      return 1; /* failure */
 
639
    }
 
640
 
 
641
    
 
642
  if (field_given && *field_given && ! override)
 
643
    return 0;
 
644
  if (prev_given)
 
645
    (*prev_given)++;
 
646
  if (field_given)
 
647
    (*field_given)++;
 
648
  if (possible_values)
 
649
    val = possible_values[found];
 
650
 
 
651
  switch(arg_type) {
 
652
  case ARG_INT:
 
653
    if (val) *((int *)field) = strtol (val, &stop_char, 0);
 
654
    break;
 
655
  case ARG_STRING:
 
656
    if (val) {
 
657
      string_field = (char **)field;
 
658
      if (!no_free && *string_field)
 
659
        free (*string_field); /* free previous string */
 
660
      *string_field = gengetopt_strdup (val);
 
661
    }
 
662
    break;
 
663
  default:
 
664
    break;
 
665
  };
 
666
 
 
667
  /* check numeric conversion */
 
668
  switch(arg_type) {
 
669
  case ARG_INT:
 
670
    if (val && !(stop_char && *stop_char == '\0')) {
 
671
      fprintf(stderr, "%s: invalid numeric value: %s\n", package_name, val);
 
672
      return 1; /* failure */
 
673
    }
 
674
    break;
 
675
  default:
 
676
    ;
 
677
  };
 
678
 
 
679
  /* store the original value */
 
680
  switch(arg_type) {
 
681
  case ARG_NO:
 
682
    break;
 
683
  default:
 
684
    if (value && orig_field) {
 
685
      if (no_free) {
 
686
        *orig_field = value;
 
687
      } else {
 
688
        if (*orig_field)
 
689
          free (*orig_field); /* free previous string */
 
690
        *orig_field = gengetopt_strdup (value);
 
691
      }
 
692
    }
 
693
  };
 
694
 
 
695
  return 0; /* OK */
 
696
}
 
697
 
 
698
/**
 
699
 * @brief store information about a multiple option in a temporary list
 
700
 * @param list where to (temporarily) store multiple options
 
701
 */
 
702
static
 
703
int update_multiple_arg_temp(struct generic_list **list,
 
704
               unsigned int *prev_given, const char *val,
 
705
               char *possible_values[], const char *default_value,
 
706
               test_modes_cmd_parser_arg_type arg_type,
 
707
               const char *long_opt, char short_opt,
 
708
               const char *additional_error)
 
709
{
 
710
  char *multi_token, *multi_next; /* store single arguments */
 
711
 
 
712
  if (arg_type == ARG_NO) {
 
713
    (*prev_given)++;
 
714
    return 0; /* OK */
 
715
  }
 
716
 
 
717
  multi_token = get_multiple_arg_token(val);
 
718
  multi_next = get_multiple_arg_token_next (val);
 
719
 
 
720
  while (1)
 
721
    {
 
722
      add_node (list);
 
723
      if (update_arg((void *)&((*list)->arg), &((*list)->orig), 0,
 
724
          prev_given, multi_token, possible_values, default_value, 
 
725
          arg_type, 0, 1, 1, 1, long_opt, short_opt, additional_error)) {
 
726
        if (multi_token) free(multi_token);
 
727
        return 1; /* failure */
 
728
      }
 
729
 
 
730
      if (multi_next)
 
731
        {
 
732
          multi_token = get_multiple_arg_token(multi_next);
 
733
          multi_next = get_multiple_arg_token_next (multi_next);
 
734
        }
 
735
      else
 
736
        break;
 
737
    }
 
738
 
 
739
  return 0; /* OK */
 
740
}
 
741
 
 
742
/**
 
743
 * @brief free the passed list (including possible string argument)
 
744
 */
 
745
static
 
746
void free_list(struct generic_list *list, short string_arg)
 
747
{
 
748
  if (list) {
 
749
    struct generic_list *tmp;
 
750
    while (list)
 
751
      {
 
752
        tmp = list;
 
753
        if (string_arg && list->arg.string_arg)
 
754
          free (list->arg.string_arg);
 
755
        if (list->orig)
 
756
          free (list->orig);
 
757
        list = list->next;
 
758
        free (tmp);
 
759
      }
 
760
  }
 
761
}
 
762
 
 
763
/**
 
764
 * @brief updates a multiple option starting from the passed list
 
765
 */
 
766
static
 
767
void update_multiple_arg(void *field, char ***orig_field,
 
768
               unsigned int field_given, unsigned int prev_given, union generic_value *default_value,
 
769
               test_modes_cmd_parser_arg_type arg_type,
 
770
               struct generic_list *list)
 
771
{
 
772
  int i;
 
773
  struct generic_list *tmp;
 
774
 
 
775
  if (prev_given && list) {
 
776
    *orig_field = (char **) realloc (*orig_field, (field_given + prev_given) * sizeof (char *));
 
777
 
 
778
    switch(arg_type) {
 
779
    case ARG_INT:
 
780
      *((int **)field) = (int *)realloc (*((int **)field), (field_given + prev_given) * sizeof (int)); break;
 
781
    case ARG_STRING:
 
782
      *((char ***)field) = (char **)realloc (*((char ***)field), (field_given + prev_given) * sizeof (char *)); break;
 
783
    default:
 
784
      break;
 
785
    };
 
786
    
 
787
    for (i = (prev_given - 1); i >= 0; --i)
 
788
      {
 
789
        tmp = list;
 
790
        
 
791
        switch(arg_type) {
 
792
        case ARG_INT:
 
793
          (*((int **)field))[i + field_given] = tmp->arg.int_arg; break;
 
794
        case ARG_STRING:
 
795
          (*((char ***)field))[i + field_given] = tmp->arg.string_arg; break;
 
796
        default:
 
797
          break;
 
798
        }        
 
799
        (*orig_field) [i + field_given] = list->orig;
 
800
        list = list->next;
 
801
        free (tmp);
 
802
      }
 
803
  } else { /* set the default value */
 
804
    if (default_value && ! field_given) {
 
805
      switch(arg_type) {
 
806
      case ARG_INT:
 
807
        if (! *((int **)field)) {
 
808
          *((int **)field) = (int *)malloc (sizeof (int));
 
809
          (*((int **)field))[0] = default_value->int_arg; 
 
810
        }
 
811
        break;
 
812
      case ARG_STRING:
 
813
        if (! *((char ***)field)) {
 
814
          *((char ***)field) = (char **)malloc (sizeof (char *));
 
815
          (*((char ***)field))[0] = gengetopt_strdup(default_value->string_arg);
 
816
        }
 
817
        break;
 
818
      default: break;
 
819
      }
 
820
      if (!(*orig_field)) {
 
821
        *orig_field = (char **) malloc (sizeof (char *));
 
822
        (*orig_field)[0] = NULL;
 
823
      }
 
824
    }
 
825
  }
 
826
}
 
827
 
 
828
static int check_modes(int given1[], const char *options1[],
 
829
                       int given2[], const char *options2[])
 
830
{
 
831
  int i = 0, j = 0, errors = 0;
 
832
  
 
833
  while (given1[i] >= 0) {
 
834
    if (given1[i]) {
 
835
      while (given2[j] >= 0) {
 
836
        if (given2[j]) {
 
837
          ++errors;
 
838
          fprintf(stderr, "%s: option %s conflicts with option %s\n",
 
839
                  package_name, options1[i], options2[j]);
 
840
        }
 
841
        ++j;
 
842
      }
 
843
    }
 
844
    ++i;
 
845
  }
 
846
  
 
847
  return errors;
 
848
}
 
849
 
 
850
int
 
851
test_modes_cmd_parser_internal (int argc, char * const *argv, struct gengetopt_args_info *args_info,
 
852
                        struct test_modes_cmd_parser_params *params, const char *additional_error)
 
853
{
 
854
  int c;        /* Character of the parsed option.  */
 
855
 
 
856
  struct generic_list * optAmul_list = NULL;
 
857
  int error = 0;
 
858
  struct gengetopt_args_info local_args_info;
 
859
  
 
860
  int override;
 
861
  int initialize;
 
862
  int check_required;
 
863
  int check_ambiguity;
 
864
  
 
865
  package_name = argv[0];
 
866
  
 
867
  override = params->override;
 
868
  initialize = params->initialize;
 
869
  check_required = params->check_required;
 
870
  check_ambiguity = params->check_ambiguity;
 
871
 
 
872
  if (initialize)
 
873
    test_modes_cmd_parser_init (args_info);
 
874
 
 
875
  test_modes_cmd_parser_init (&local_args_info);
 
876
 
 
877
  optarg = 0;
 
878
  optind = 0;
 
879
  opterr = params->print_errors;
 
880
  optopt = '?';
 
881
 
 
882
  while (1)
 
883
    {
 
884
      int option_index = 0;
 
885
 
 
886
      static struct option long_options[] = {
 
887
        { "help",       0, NULL, 'h' },
 
888
        { "version",    0, NULL, 'V' },
 
889
        { "no-mode",    0, NULL, 'N' },
 
890
        { "no-mode2",   1, NULL, 0 },
 
891
        { "opta",       0, NULL, 'a' },
 
892
        { "optA",       2, NULL, 'A' },
 
893
        { "optAmul",    2, NULL, 'M' },
 
894
        { "optb",       0, NULL, 'b' },
 
895
        { "optc",       0, NULL, 0 },
 
896
        { "optd",       0, NULL, 'd' },
 
897
        { "mopt",       1, NULL, 'm' },
 
898
        { NULL, 0, NULL, 0 }
 
899
      };
 
900
 
 
901
      c = getopt_long (argc, argv, "hVNaA::M::bdm:", long_options, &option_index);
 
902
 
 
903
      if (c == -1) break;       /* Exit from `while (1)' loop.  */
 
904
 
 
905
      switch (c)
 
906
        {
 
907
        case 'h':       /* Print help and exit.  */
 
908
          test_modes_cmd_parser_print_help ();
 
909
          test_modes_cmd_parser_free (&local_args_info);
 
910
          exit (EXIT_SUCCESS);
 
911
 
 
912
        case 'V':       /* Print version and exit.  */
 
913
          test_modes_cmd_parser_print_version ();
 
914
          test_modes_cmd_parser_free (&local_args_info);
 
915
          exit (EXIT_SUCCESS);
 
916
 
 
917
        case 'N':       /* a generic option not beloging to any mode.  */
 
918
        
 
919
        
 
920
          if (update_arg( 0 , 
 
921
               0 , &(args_info->no_mode_given),
 
922
              &(local_args_info.no_mode_given), optarg, 0, 0, ARG_NO,
 
923
              check_ambiguity, override, 0, 0,
 
924
              "no-mode", 'N',
 
925
              additional_error))
 
926
            goto failure;
 
927
        
 
928
          break;
 
929
        case 'a':       /* string a.  */
 
930
          args_info->mode1_mode_counter += 1;
 
931
        
 
932
          local_args_info.opta_given++;
 
933
        
 
934
          break;
 
935
        case 'A':       /* string A.  */
 
936
          args_info->mode1_mode_counter += 1;
 
937
        
 
938
        
 
939
          if (update_arg( (void *)&(args_info->optA_arg), 
 
940
               &(args_info->optA_orig), &(args_info->optA_given),
 
941
              &(local_args_info.optA_given), optarg, 0, 0, ARG_STRING,
 
942
              check_ambiguity, override, 0, 0,
 
943
              "optA", 'A',
 
944
              additional_error))
 
945
            goto failure;
 
946
        
 
947
          break;
 
948
        case 'M':       /* string M.  */
 
949
          args_info->mode1_mode_counter += 1;
 
950
        
 
951
          if (update_multiple_arg_temp(&optAmul_list, 
 
952
              &(local_args_info.optAmul_given), optarg, 0, 0, ARG_STRING,
 
953
              "optAmul", 'M',
 
954
              additional_error))
 
955
            goto failure;
 
956
        
 
957
          break;
 
958
        case 'b':       /* string b.  */
 
959
          args_info->mode1_mode_counter += 1;
 
960
        
 
961
        
 
962
          if (update_arg( 0 , 
 
963
               0 , &(args_info->optb_given),
 
964
              &(local_args_info.optb_given), optarg, 0, 0, ARG_NO,
 
965
              check_ambiguity, override, 0, 0,
 
966
              "optb", 'b',
 
967
              additional_error))
 
968
            goto failure;
 
969
        
 
970
          break;
 
971
        case 'd':       /* string d.  */
 
972
          args_info->mode_2_mode_counter += 1;
 
973
        
 
974
        
 
975
          if (update_arg( 0 , 
 
976
               0 , &(args_info->optd_given),
 
977
              &(local_args_info.optd_given), optarg, 0, 0, ARG_NO,
 
978
              check_ambiguity, override, 0, 0,
 
979
              "optd", 'd',
 
980
              additional_error))
 
981
            goto failure;
 
982
        
 
983
          break;
 
984
        case 'm':       /* option of my mode.  */
 
985
          args_info->my_mode_mode_counter += 1;
 
986
        
 
987
        
 
988
          if (update_arg( (void *)&(args_info->mopt_arg), 
 
989
               &(args_info->mopt_orig), &(args_info->mopt_given),
 
990
              &(local_args_info.mopt_given), optarg, 0, 0, ARG_INT,
 
991
              check_ambiguity, override, 0, 0,
 
992
              "mopt", 'm',
 
993
              additional_error))
 
994
            goto failure;
 
995
        
 
996
          break;
 
997
 
 
998
        case 0: /* Long option with no short option */
 
999
          /* another generic option not beloging to any mode.  */
 
1000
          if (strcmp (long_options[option_index].name, "no-mode2") == 0)
 
1001
          {
 
1002
          
 
1003
          
 
1004
            if (update_arg( (void *)&(args_info->no_mode2_arg), 
 
1005
                 &(args_info->no_mode2_orig), &(args_info->no_mode2_given),
 
1006
                &(local_args_info.no_mode2_given), optarg, 0, 0, ARG_STRING,
 
1007
                check_ambiguity, override, 0, 0,
 
1008
                "no-mode2", '-',
 
1009
                additional_error))
 
1010
              goto failure;
 
1011
          
 
1012
          }
 
1013
          /* string c.  */
 
1014
          else if (strcmp (long_options[option_index].name, "optc") == 0)
 
1015
          {
 
1016
            args_info->mode_2_mode_counter += 1;
 
1017
          
 
1018
          
 
1019
            if (update_arg( 0 , 
 
1020
                 0 , &(args_info->optc_given),
 
1021
                &(local_args_info.optc_given), optarg, 0, 0, ARG_NO,
 
1022
                check_ambiguity, override, 0, 0,
 
1023
                "optc", '-',
 
1024
                additional_error))
 
1025
              goto failure;
 
1026
          
 
1027
          }
 
1028
          
 
1029
          break;
 
1030
        case '?':       /* Invalid option.  */
 
1031
          /* `getopt_long' already printed an error message.  */
 
1032
          goto failure;
 
1033
 
 
1034
        default:        /* bug: option not considered.  */
 
1035
          fprintf (stderr, "%s: option unknown: %c%s\n", TEST_MODES_CMD_PARSER_PACKAGE, c, (additional_error ? additional_error : ""));
 
1036
          abort ();
 
1037
        } /* switch */
 
1038
    } /* while */
 
1039
 
 
1040
 
 
1041
  update_multiple_arg((void *)&(args_info->optAmul_arg),
 
1042
    &(args_info->optAmul_orig), args_info->optAmul_given,
 
1043
    local_args_info.optAmul_given, 0 , 
 
1044
    ARG_STRING, optAmul_list);
 
1045
 
 
1046
  args_info->opta_given += local_args_info.opta_given;
 
1047
  local_args_info.opta_given = 0;
 
1048
  args_info->optAmul_given += local_args_info.optAmul_given;
 
1049
  local_args_info.optAmul_given = 0;
 
1050
  
 
1051
  if (args_info->mode_2_mode_counter && args_info->mode1_mode_counter) {
 
1052
    error += check_modes(
 
1053
      (int []){args_info->optc_given, args_info->optd_given,  -1},
 
1054
      (const char *[]){"--optc", "--optd",  0},
 
1055
      (int []){args_info->opta_given, args_info->optA_given, args_info->optAmul_given, args_info->optb_given,  -1},
 
1056
      (const char *[]){"--opta", "--optA", "--optAmul", "--optb",  0});
 
1057
  }
 
1058
  if (args_info->mode_2_mode_counter && args_info->my_mode_mode_counter) {
 
1059
    error += check_modes(
 
1060
      (int []){args_info->optc_given, args_info->optd_given,  -1},
 
1061
      (const char *[]){"--optc", "--optd",  0},
 
1062
      (int []){args_info->mopt_given,  -1},
 
1063
      (const char *[]){"--mopt",  0});
 
1064
  }
 
1065
  if (args_info->mode1_mode_counter && args_info->my_mode_mode_counter) {
 
1066
    error += check_modes(
 
1067
      (int []){args_info->opta_given, args_info->optA_given, args_info->optAmul_given, args_info->optb_given,  -1},
 
1068
      (const char *[]){"--opta", "--optA", "--optAmul", "--optb",  0},
 
1069
      (int []){args_info->mopt_given,  -1},
 
1070
      (const char *[]){"--mopt",  0});
 
1071
  }
 
1072
  
 
1073
  if (check_required)
 
1074
    {
 
1075
      error += test_modes_cmd_parser_required2 (args_info, argv[0], additional_error);
 
1076
    }
 
1077
 
 
1078
  test_modes_cmd_parser_release (&local_args_info);
 
1079
 
 
1080
  if ( error )
 
1081
    return (EXIT_FAILURE);
 
1082
 
 
1083
  if (optind < argc)
 
1084
    {
 
1085
      int i = 0 ;
 
1086
      int found_prog_name = 0;
 
1087
      /* whether program name, i.e., argv[0], is in the remaining args
 
1088
         (this may happen with some implementations of getopt,
 
1089
          but surely not with the one included by gengetopt) */
 
1090
 
 
1091
      i = optind;
 
1092
      while (i < argc)
 
1093
        if (argv[i++] == argv[0]) {
 
1094
          found_prog_name = 1;
 
1095
          break;
 
1096
        }
 
1097
      i = 0;
 
1098
 
 
1099
      args_info->inputs_num = argc - optind - found_prog_name;
 
1100
      args_info->inputs =
 
1101
        (char **)(malloc ((args_info->inputs_num)*sizeof(char *))) ;
 
1102
      while (optind < argc)
 
1103
        if (argv[optind++] != argv[0])
 
1104
          args_info->inputs[ i++ ] = gengetopt_strdup (argv[optind-1]) ;
 
1105
    }
 
1106
 
 
1107
  return 0;
 
1108
 
 
1109
failure:
 
1110
  free_list (optAmul_list, 1 );
 
1111
  
 
1112
  test_modes_cmd_parser_release (&local_args_info);
 
1113
  return (EXIT_FAILURE);
 
1114
}