1 /*
2   File autogenerated by gengetopt version 2.23
3   generated with the following command:
4   /usr/bin/gengetopt -N --no-version --input=/home/andriish/Projects/HepMC3/examples/ConvertExample/cmdline.ggo --file-name cmdline --output-dir=/home/andriish/Projects/HepMC3/examples/ConvertExample --include-getopt --show-required --unnamed-opts=inputfile outputfile
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 #ifndef FIX_UNUSED
21 #define FIX_UNUSED(X) (void) (X) /* avoid warnings for unused params */
22 #endif
23 
24 
25 #include "cmdline.h"
26 
27 const char *gengetopt_args_info_purpose = "Convert between different file formats of Monte Carlo event record.\nExample:\n        convert_example -i hepmc2 -o treeroot input.hepmc output.root\n";
28 
29 const char *gengetopt_args_info_usage = "Usage: convert_example [OPTION]... [inputfile outputfile]...";
30 
31 const char *gengetopt_args_info_versiontext = "";
32 
33 const char *gengetopt_args_info_description = "";
34 
35 const char *gengetopt_args_info_help[] = {
36   "  -h, --help                    Print help and exit",
37   "  -i, --input-format=STRING     Input format  (possible values=\"hepmc2\",\n                                  \"auto\", \"hepmc3\", \"hpe\", \"root\",\n                                  \"treeroot\", \"lhef\", \"gz\", \"uproot\", \"plugin\")\n                                  (mandatory)",
38   "  -o, --output-format=STRING    Output format  (possible values=\"hepmc2\",\n                                  \"hepmc3\", \"hpe\", \"root\", \"treeroot\",\n                                  \"treerootopal\", \"hpezeus\", \"dump\",\n                                  \"plugin\", \"dot\", \"none\") (mandatory)",
39   "  -e, --extensions=STRING       Extensions, in a form extension=value, could be\n                                  passed to readers/writers",
40   "      --events-limit=LONG       Limit of events to read from input\n                                  (default=`100000000')",
41   "      --first-event-number=LONG Lowest allowed event number\n                                  (default=`-100000000')",
42   "      --last-event-number=LONG  Highest allowed event number\n                                  (default=`100000000')",
43   "      --print-every-events-parsed=LONG\n                                Frequency of parsing information printouts\n                                  (default=`100')",
44     0
45 };
46 
47 typedef enum {ARG_NO
48   , ARG_STRING
49   , ARG_LONG
50 } cmdline_parser_arg_type;
51 
52 static
53 void clear_given (struct gengetopt_args_info *args_info);
54 static
55 void clear_args (struct gengetopt_args_info *args_info);
56 
57 static int
58 cmdline_parser_internal (int argc, char **argv, struct gengetopt_args_info *args_info,
59                         struct cmdline_parser_params *params, const char *additional_error);
60 
61 static int
62 cmdline_parser_required2 (struct gengetopt_args_info *args_info, const char *prog_name, const char *additional_error);
63 
64 const char *cmdline_parser_input_format_values[] = {"hepmc2", "auto", "hepmc3", "hpe", "root", "treeroot", "lhef", "gz","uproot", "plugin", 0}; /*< Possible values for input-format. */
65 const char *cmdline_parser_output_format_values[] = {"hepmc2", "hepmc3", "hpe", "root", "treeroot", "treerootopal", "hpezeus", "dump", "plugin", "dot", "none", 0}; /*< Possible values for output-format. */
66 
67 static char *
68 gengetopt_strdup (const char *s);
69 
70 static
clear_given(struct gengetopt_args_info * args_info)71 void clear_given (struct gengetopt_args_info *args_info)
72 {
73   args_info->help_given = 0 ;
74   args_info->input_format_given = 0 ;
75   args_info->output_format_given = 0 ;
76   args_info->extensions_given = 0 ;
77   args_info->events_limit_given = 0 ;
78   args_info->first_event_number_given = 0 ;
79   args_info->last_event_number_given = 0 ;
80   args_info->print_every_events_parsed_given = 0 ;
81 }
82 
83 static
clear_args(struct gengetopt_args_info * args_info)84 void clear_args (struct gengetopt_args_info *args_info)
85 {
86   FIX_UNUSED (args_info);
87   args_info->input_format_arg = NULL;
88   args_info->input_format_orig = NULL;
89   args_info->output_format_arg = NULL;
90   args_info->output_format_orig = NULL;
91   args_info->extensions_arg = NULL;
92   args_info->extensions_orig = NULL;
93   args_info->events_limit_arg = 100000000;
94   args_info->events_limit_orig = NULL;
95   args_info->first_event_number_arg = -100000000;
96   args_info->first_event_number_orig = NULL;
97   args_info->last_event_number_arg = 100000000;
98   args_info->last_event_number_orig = NULL;
99   args_info->print_every_events_parsed_arg = 100;
100   args_info->print_every_events_parsed_orig = NULL;
101 
102 }
103 
104 static
init_args_info(struct gengetopt_args_info * args_info)105 void init_args_info(struct gengetopt_args_info *args_info)
106 {
107 
108 
109   args_info->help_help = gengetopt_args_info_help[0] ;
110   args_info->input_format_help = gengetopt_args_info_help[1] ;
111   args_info->output_format_help = gengetopt_args_info_help[2] ;
112   args_info->extensions_help = gengetopt_args_info_help[3] ;
113   args_info->extensions_min = 0;
114   args_info->extensions_max = 0;
115   args_info->events_limit_help = gengetopt_args_info_help[4] ;
116   args_info->first_event_number_help = gengetopt_args_info_help[5] ;
117   args_info->last_event_number_help = gengetopt_args_info_help[6] ;
118   args_info->print_every_events_parsed_help = gengetopt_args_info_help[7] ;
119 
120 }
121 
122 void
cmdline_parser_print_version(void)123 cmdline_parser_print_version (void)
124 {
125   printf ("%s %s\n",
126      (strlen(CMDLINE_PARSER_PACKAGE_NAME) ? CMDLINE_PARSER_PACKAGE_NAME : CMDLINE_PARSER_PACKAGE),
127      CMDLINE_PARSER_VERSION);
128 
129   if (strlen(gengetopt_args_info_versiontext) > 0)
130     printf("\n%s\n", gengetopt_args_info_versiontext);
131 }
132 
print_help_common(void)133 static void print_help_common(void)
134 {
135 	size_t len_purpose = strlen(gengetopt_args_info_purpose);
136 	size_t len_usage = strlen(gengetopt_args_info_usage);
137 
138 	if (len_usage > 0) {
139 		printf("%s\n", gengetopt_args_info_usage);
140 	}
141 	if (len_purpose > 0) {
142 		printf("%s\n", gengetopt_args_info_purpose);
143 	}
144 
145 	if (len_usage || len_purpose) {
146 		printf("\n");
147 	}
148 
149 	if (strlen(gengetopt_args_info_description) > 0) {
150 		printf("%s\n\n", gengetopt_args_info_description);
151 	}
152 }
153 
154 void
cmdline_parser_print_help(void)155 cmdline_parser_print_help (void)
156 {
157   int i = 0;
158   print_help_common();
159   while (gengetopt_args_info_help[i])
160     printf("%s\n", gengetopt_args_info_help[i++]);
161 }
162 
163 void
cmdline_parser_init(struct gengetopt_args_info * args_info)164 cmdline_parser_init (struct gengetopt_args_info *args_info)
165 {
166   clear_given (args_info);
167   clear_args (args_info);
168   init_args_info (args_info);
169 
170   args_info->inputs = 0;
171   args_info->inputs_num = 0;
172 }
173 
174 void
cmdline_parser_params_init(struct cmdline_parser_params * params)175 cmdline_parser_params_init(struct cmdline_parser_params *params)
176 {
177   if (params)
178     {
179       params->override = 0;
180       params->initialize = 1;
181       params->check_required = 1;
182       params->check_ambiguity = 0;
183       params->print_errors = 1;
184     }
185 }
186 
187 struct cmdline_parser_params *
cmdline_parser_params_create(void)188 cmdline_parser_params_create(void)
189 {
190   struct cmdline_parser_params *params =
191     (struct cmdline_parser_params *)malloc(sizeof(struct cmdline_parser_params));
192   cmdline_parser_params_init(params);
193   return params;
194 }
195 
196 static void
free_string_field(char ** s)197 free_string_field (char **s)
198 {
199   if (*s)
200     {
201       free (*s);
202       *s = 0;
203     }
204 }
205 
206 /** @brief generic value variable */
207 union generic_value {
208     long long_arg;
209     char *string_arg;
210     const char *default_string_arg;
211 };
212 
213 /** @brief holds temporary values for multiple options */
214 struct generic_list
215 {
216   union generic_value arg;
217   char *orig;
218   struct generic_list *next;
219 };
220 
221 /**
222  * @brief add a node at the head of the list
223  */
add_node(struct generic_list ** list)224 static void add_node(struct generic_list **list) {
225   struct generic_list *new_node = (struct generic_list *) malloc (sizeof (struct generic_list));
226   new_node->next = *list;
227   *list = new_node;
228   new_node->arg.string_arg = 0;
229   new_node->orig = 0;
230 }
231 
232 
233 static void
free_multiple_string_field(unsigned int len,char *** arg,char *** orig)234 free_multiple_string_field(unsigned int len, char ***arg, char ***orig)
235 {
236   unsigned int i;
237   if (*arg) {
238     for (i = 0; i < len; ++i)
239       {
240         free_string_field(&((*arg)[i]));
241         free_string_field(&((*orig)[i]));
242       }
243     free_string_field(&((*arg)[0])); /* free default string */
244 
245     free (*arg);
246     *arg = 0;
247     free (*orig);
248     *orig = 0;
249   }
250 }
251 
252 static void
cmdline_parser_release(struct gengetopt_args_info * args_info)253 cmdline_parser_release (struct gengetopt_args_info *args_info)
254 {
255   unsigned int i;
256   free_string_field (&(args_info->input_format_arg));
257   free_string_field (&(args_info->input_format_orig));
258   free_string_field (&(args_info->output_format_arg));
259   free_string_field (&(args_info->output_format_orig));
260   free_multiple_string_field (args_info->extensions_given, &(args_info->extensions_arg), &(args_info->extensions_orig));
261   free_string_field (&(args_info->events_limit_orig));
262   free_string_field (&(args_info->first_event_number_orig));
263   free_string_field (&(args_info->last_event_number_orig));
264   free_string_field (&(args_info->print_every_events_parsed_orig));
265 
266 
267   for (i = 0; i < args_info->inputs_num; ++i)
268     free (args_info->inputs [i]);
269 
270   if (args_info->inputs_num)
271     free (args_info->inputs);
272 
273   clear_given (args_info);
274 }
275 
276 /**
277  * @param val the value to check
278  * @param values the possible values
279  * @return the index of the matched value:
280  * -1 if no value matched,
281  * -2 if more than one value has matched
282  */
283 static int
check_possible_values(const char * val,const char * values[])284 check_possible_values(const char *val, const char *values[])
285 {
286   int i, found, last;
287   size_t len;
288 
289   if (!val)   /* otherwise strlen() crashes below */
290     return -1; /* -1 means no argument for the option */
291 
292   found = last = 0;
293 
294   for (i = 0, len = strlen(val); values[i]; ++i)
295     {
296       if (strncmp(val, values[i], len) == 0)
297         {
298           ++found;
299           last = i;
300           if (strlen(values[i]) == len)
301             return i; /* exact macth no need to check more */
302         }
303     }
304 
305   if (found == 1) /* one match: OK */
306     return last;
307 
308   return (found ? -2 : -1); /* return many values or none matched */
309 }
310 
311 
312 static void
write_into_file(FILE * outfile,const char * opt,const char * arg,const char * values[])313 write_into_file(FILE *outfile, const char *opt, const char *arg, const char *values[])
314 {
315   int found = -1;
316   if (arg) {
317     if (values) {
318       found = check_possible_values(arg, values);
319     }
320     if (found >= 0)
321       fprintf(outfile, "%s=\"%s\" # %s\n", opt, arg, values[found]);
322     else
323       fprintf(outfile, "%s=\"%s\"\n", opt, arg);
324   } else {
325     fprintf(outfile, "%s\n", opt);
326   }
327 }
328 
329 static void
write_multiple_into_file(FILE * outfile,int len,const char * opt,char ** arg,const char * values[])330 write_multiple_into_file(FILE *outfile, int len, const char *opt, char **arg, const char *values[])
331 {
332   int i;
333 
334   for (i = 0; i < len; ++i)
335     write_into_file(outfile, opt, (arg ? arg[i] : 0), values);
336 }
337 
338 int
cmdline_parser_dump(FILE * outfile,struct gengetopt_args_info * args_info)339 cmdline_parser_dump(FILE *outfile, struct gengetopt_args_info *args_info)
340 {
341   int i = 0;
342 
343   if (!outfile)
344     {
345       fprintf (stderr, "%s: cannot dump options to stream\n", CMDLINE_PARSER_PACKAGE);
346       return EXIT_FAILURE;
347     }
348 
349   if (args_info->help_given)
350     write_into_file(outfile, "help", 0, 0 );
351   if (args_info->input_format_given)
352     write_into_file(outfile, "input-format", args_info->input_format_orig, cmdline_parser_input_format_values);
353   if (args_info->output_format_given)
354     write_into_file(outfile, "output-format", args_info->output_format_orig, cmdline_parser_output_format_values);
355   write_multiple_into_file(outfile, args_info->extensions_given, "extensions", args_info->extensions_orig, 0);
356   if (args_info->events_limit_given)
357     write_into_file(outfile, "events-limit", args_info->events_limit_orig, 0);
358   if (args_info->first_event_number_given)
359     write_into_file(outfile, "first-event-number", args_info->first_event_number_orig, 0);
360   if (args_info->last_event_number_given)
361     write_into_file(outfile, "last-event-number", args_info->last_event_number_orig, 0);
362   if (args_info->print_every_events_parsed_given)
363     write_into_file(outfile, "print-every-events-parsed", args_info->print_every_events_parsed_orig, 0);
364 
365 
366   i = EXIT_SUCCESS;
367   return i;
368 }
369 
370 int
cmdline_parser_file_save(const char * filename,struct gengetopt_args_info * args_info)371 cmdline_parser_file_save(const char *filename, struct gengetopt_args_info *args_info)
372 {
373   FILE *outfile;
374   int i = 0;
375 
376   outfile = fopen(filename, "w");
377 
378   if (!outfile)
379     {
380       fprintf (stderr, "%s: cannot open file for writing: %s\n", CMDLINE_PARSER_PACKAGE, filename);
381       return EXIT_FAILURE;
382     }
383 
384   i = cmdline_parser_dump(outfile, args_info);
385   fclose (outfile);
386 
387   return i;
388 }
389 
390 void
cmdline_parser_free(struct gengetopt_args_info * args_info)391 cmdline_parser_free (struct gengetopt_args_info *args_info)
392 {
393   cmdline_parser_release (args_info);
394 }
395 
396 /** @brief replacement of strdup, which is not standard */
397 char *
gengetopt_strdup(const char * s)398 gengetopt_strdup (const char *s)
399 {
400   char *result = 0;
401   if (!s)
402     return result;
403 
404   result = (char*)malloc(strlen(s) + 1);
405   if (result == (char*)0)
406     return (char*)0;
407   strcpy(result, s);
408   return result;
409 }
410 
411 static char *
get_multiple_arg_token(const char * arg)412 get_multiple_arg_token(const char *arg)
413 {
414   const char *tok;
415   char *ret;
416   size_t len, num_of_escape, i, j;
417 
418   if (!arg)
419     return 0;
420 
421   tok = strchr (arg, ',');
422   num_of_escape = 0;
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           ++num_of_escape;
432         }
433       else
434         break;
435     }
436 
437   if (tok)
438     len = (size_t)(tok - arg + 1);
439   else
440     len = strlen (arg) + 1;
441 
442   len -= num_of_escape;
443 
444   ret = (char *) malloc (len);
445 
446   i = 0;
447   j = 0;
448   while (arg[i] && (j < len-1))
449     {
450       if (arg[i] == '\\' &&
451 	  arg[ i + 1 ] &&
452 	  arg[ i + 1 ] == ',')
453         ++i;
454 
455       ret[j++] = arg[i++];
456     }
457 
458   ret[len-1] = '\0';
459 
460   return ret;
461 }
462 
463 static const char *
get_multiple_arg_token_next(const char * arg)464 get_multiple_arg_token_next(const char *arg)
465 {
466   const char *tok;
467 
468   if (!arg)
469     return 0;
470 
471   tok = strchr (arg, ',');
472 
473   /* make sure it is not escaped */
474   while (tok)
475     {
476       if (*(tok-1) == '\\')
477         {
478           /* find the next one */
479           tok = strchr (tok+1, ',');
480         }
481       else
482         break;
483     }
484 
485   if (! tok || strlen(tok) == 1)
486     return 0;
487 
488   return tok+1;
489 }
490 
491 static int
492 check_multiple_option_occurrences(const char *prog_name, unsigned int option_given, unsigned int min, unsigned int max, const char *option_desc);
493 
494 int
check_multiple_option_occurrences(const char * prog_name,unsigned int option_given,unsigned int min,unsigned int max,const char * option_desc)495 check_multiple_option_occurrences(const char *prog_name, unsigned int option_given, unsigned int min, unsigned int max, const char *option_desc)
496 {
497   int error_occurred = 0;
498 
499   if (option_given && (min > 0 || max > 0))
500     {
501       if (min > 0 && max > 0)
502         {
503           if (min == max)
504             {
505               /* specific occurrences */
506               if (option_given != (unsigned int) min)
507                 {
508                   fprintf (stderr, "%s: %s option occurrences must be %d\n",
509                     prog_name, option_desc, min);
510                   error_occurred = 1;
511                 }
512             }
513           else if (option_given < (unsigned int) min
514                 || option_given > (unsigned int) max)
515             {
516               /* range occurrences */
517               fprintf (stderr, "%s: %s option occurrences must be between %d and %d\n",
518                 prog_name, option_desc, min, max);
519               error_occurred = 1;
520             }
521         }
522       else if (min > 0)
523         {
524           /* at least check */
525           if (option_given < min)
526             {
527               fprintf (stderr, "%s: %s option occurrences must be at least %d\n",
528                 prog_name, option_desc, min);
529               error_occurred = 1;
530             }
531         }
532       else if (max > 0)
533         {
534           /* at most check */
535           if (option_given > max)
536             {
537               fprintf (stderr, "%s: %s option occurrences must be at most %d\n",
538                 prog_name, option_desc, max);
539               error_occurred = 1;
540             }
541         }
542     }
543 
544   return error_occurred;
545 }
546 int
cmdline_parser(int argc,char ** argv,struct gengetopt_args_info * args_info)547 cmdline_parser (int argc, char **argv, struct gengetopt_args_info *args_info)
548 {
549   return cmdline_parser2 (argc, argv, args_info, 0, 1, 1);
550 }
551 
552 int
cmdline_parser_ext(int argc,char ** argv,struct gengetopt_args_info * args_info,struct cmdline_parser_params * params)553 cmdline_parser_ext (int argc, char **argv, struct gengetopt_args_info *args_info,
554                    struct cmdline_parser_params *params)
555 {
556   int result;
557   result = cmdline_parser_internal (argc, argv, args_info, params, 0);
558 
559   if (result == EXIT_FAILURE)
560     {
561       cmdline_parser_free (args_info);
562       exit (EXIT_FAILURE);
563     }
564 
565   return result;
566 }
567 
568 int
cmdline_parser2(int argc,char ** argv,struct gengetopt_args_info * args_info,int override,int initialize,int check_required)569 cmdline_parser2 (int argc, char **argv, struct gengetopt_args_info *args_info, int override, int initialize, int check_required)
570 {
571   int result;
572   struct cmdline_parser_params params;
573 
574   params.override = override;
575   params.initialize = initialize;
576   params.check_required = check_required;
577   params.check_ambiguity = 0;
578   params.print_errors = 1;
579 
580   result = cmdline_parser_internal (argc, argv, args_info, &params, 0);
581 
582   if (result == EXIT_FAILURE)
583     {
584       cmdline_parser_free (args_info);
585       exit (EXIT_FAILURE);
586     }
587 
588   return result;
589 }
590 
591 int
cmdline_parser_required(struct gengetopt_args_info * args_info,const char * prog_name)592 cmdline_parser_required (struct gengetopt_args_info *args_info, const char *prog_name)
593 {
594   int result = EXIT_SUCCESS;
595 
596   if (cmdline_parser_required2(args_info, prog_name, 0) > 0)
597     result = EXIT_FAILURE;
598 
599   if (result == EXIT_FAILURE)
600     {
601       cmdline_parser_free (args_info);
602       exit (EXIT_FAILURE);
603     }
604 
605   return result;
606 }
607 
608 int
cmdline_parser_required2(struct gengetopt_args_info * args_info,const char * prog_name,const char * additional_error)609 cmdline_parser_required2 (struct gengetopt_args_info *args_info, const char *prog_name, const char *additional_error)
610 {
611   int error_occurred = 0;
612   FIX_UNUSED (additional_error);
613 
614   /* checks for required options */
615   if (! args_info->input_format_given)
616     {
617       fprintf (stderr, "%s: '--input-format' ('-i') option required%s\n", prog_name, (additional_error ? additional_error : ""));
618       error_occurred = 1;
619     }
620 
621   if (! args_info->output_format_given)
622     {
623       fprintf (stderr, "%s: '--output-format' ('-o') option required%s\n", prog_name, (additional_error ? additional_error : ""));
624       error_occurred = 1;
625     }
626 
627   if (check_multiple_option_occurrences(prog_name, args_info->extensions_given, args_info->extensions_min, args_info->extensions_max, "'--extensions' ('-e')"))
628      error_occurred = 1;
629 
630 
631   /* checks for dependences among options */
632 
633   return error_occurred;
634 }
635 
636 /*
637  * Extracted from the glibc source tree, version 2.3.6
638  *
639  * Licensed under the GPL as per the whole glibc source tree.
640  *
641  * This file was modified so that getopt_long can be called
642  * many times without risking previous memory to be spoiled.
643  *
644  * Modified by Andre Noll and Lorenzo Bettini for use in
645  * GNU gengetopt generated files.
646  *
647  */
648 
649 /*
650  * we must include anything we need since this file is not thought to be
651  * inserted in a file already using getopt.h
652  *
653  * Lorenzo
654  */
655 
656 struct option
657 {
658   const char *name;
659   /* has_arg can't be an enum because some compilers complain about
660      type mismatches in all the code that assumes it is an int.  */
661   int has_arg;
662   int *flag;
663   int val;
664 };
665 
666 /* This version of `getopt' appears to the caller like standard Unix `getopt'
667    but it behaves differently for the user, since it allows the user
668    to intersperse the options with the other arguments.
669 
670    As `getopt' works, it permutes the elements of ARGV so that,
671    when it is done, all the options precede everything else.  Thus
672    all application programs are extended to handle flexible argument order.
673 */
674 /*
675    If the field `flag' is not NULL, it points to a variable that is set
676    to the value given in the field `val' when the option is found, but
677    left unchanged if the option is not found.
678 
679    To have a long-named option do something other than set an `int' to
680    a compiled-in constant, such as set a value from `custom_optarg', set the
681    option's `flag' field to zero and its `val' field to a nonzero
682    value (the equivalent single-letter option character, if there is
683    one).  For long options that have a zero `flag' field, `getopt'
684    returns the contents of the `val' field.  */
685 
686 /* Names for the values of the `has_arg' field of `struct option'.  */
687 #ifndef no_argument
688 #define no_argument		0
689 #endif
690 
691 #ifndef required_argument
692 #define required_argument	1
693 #endif
694 
695 #ifndef optional_argument
696 #define optional_argument	2
697 #endif
698 
699 struct custom_getopt_data {
700 	/*
701 	 * These have exactly the same meaning as the corresponding global variables,
702 	 * except that they are used for the reentrant versions of getopt.
703 	 */
704 	int custom_optind;
705 	int custom_opterr;
706 	int custom_optopt;
707 	char *custom_optarg;
708 
709 	/* True if the internal members have been initialized.  */
710 	int initialized;
711 
712 	/*
713 	 * The next char to be scanned in the option-element in which the last option
714 	 * character we returned was found.  This allows us to pick up the scan where
715 	 * we left off.  If this is zero, or a null string, it means resume the scan by
716 	 * advancing to the next ARGV-element.
717 	 */
718 	char *nextchar;
719 
720 	/*
721 	 * Describe the part of ARGV that contains non-options that have been skipped.
722 	 * `first_nonopt' is the index in ARGV of the first of them; `last_nonopt' is
723 	 * the index after the last of them.
724 	 */
725 	int first_nonopt;
726 	int last_nonopt;
727 };
728 
729 /*
730  * the variables optarg, optind, opterr and optopt are renamed with
731  * the custom_ prefix so that they don't interfere with getopt ones.
732  *
733  * Moreover they're static so they are visible only from within the
734  * file where this very file will be included.
735  */
736 
737 /*
738  * For communication from `custom_getopt' to the caller.  When `custom_getopt' finds an
739  * option that takes an argument, the argument value is returned here.
740  */
741 static char *custom_optarg;
742 
743 /*
744  * Index in ARGV of the next element to be scanned.  This is used for
745  * communication to and from the caller and for communication between
746  * successive calls to `custom_getopt'.
747  *
748  * On entry to `custom_getopt', 1 means this is the first call; initialize.
749  *
750  * When `custom_getopt' returns -1, this is the index of the first of the non-option
751  * elements that the caller should itself scan.
752  *
753  * Otherwise, `custom_optind' communicates from one call to the next how much of ARGV
754  * has been scanned so far.
755  *
756  * 1003.2 says this must be 1 before any call.
757  */
758 static int custom_optind = 1;
759 
760 /*
761  * Callers store zero here to inhibit the error message for unrecognized
762  * options.
763  */
764 static int custom_opterr = 1;
765 
766 /*
767  * Set to an option character which was unrecognized.  This must be initialized
768  * on some systems to avoid linking in the system's own getopt implementation.
769  */
770 static int custom_optopt = '?';
771 
772 /*
773  * Exchange two adjacent subsequences of ARGV.  One subsequence is elements
774  * [first_nonopt,last_nonopt) which contains all the non-options that have been
775  * skipped so far.  The other is elements [last_nonopt,custom_optind), which contains
776  * all the options processed since those non-options were skipped.
777  * `first_nonopt' and `last_nonopt' are relocated so that they describe the new
778  * indices of the non-options in ARGV after they are moved.
779  */
exchange(char ** argv,struct custom_getopt_data * d)780 static void exchange(char **argv, struct custom_getopt_data *d)
781 {
782 	int bottom = d->first_nonopt;
783 	int middle = d->last_nonopt;
784 	int top = d->custom_optind;
785 	char *tem;
786 
787 	/*
788 	 * Exchange the shorter segment with the far end of the longer segment.
789 	 * That puts the shorter segment into the right place.  It leaves the
790 	 * longer segment in the right place overall, but it consists of two
791 	 * parts that need to be swapped next.
792 	 */
793 	while (top > middle && middle > bottom) {
794 		if (top - middle > middle - bottom) {
795 			/* Bottom segment is the short one.  */
796 			int len = middle - bottom;
797 			int i;
798 
799 			/* Swap it with the top part of the top segment.  */
800 			for (i = 0; i < len; i++) {
801 				tem = argv[bottom + i];
802 				argv[bottom + i] =
803 					argv[top - (middle - bottom) + i];
804 				argv[top - (middle - bottom) + i] = tem;
805 			}
806 			/* Exclude the moved bottom segment from further swapping.  */
807 			top -= len;
808 		} else {
809 			/* Top segment is the short one.  */
810 			int len = top - middle;
811 			int i;
812 
813 			/* Swap it with the bottom part of the bottom segment.  */
814 			for (i = 0; i < len; i++) {
815 				tem = argv[bottom + i];
816 				argv[bottom + i] = argv[middle + i];
817 				argv[middle + i] = tem;
818 			}
819 			/* Exclude the moved top segment from further swapping.  */
820 			bottom += len;
821 		}
822 	}
823 	/* Update records for the slots the non-options now occupy.  */
824 	d->first_nonopt += (d->custom_optind - d->last_nonopt);
825 	d->last_nonopt = d->custom_optind;
826 }
827 
828 /* Initialize the internal data when the first call is made.  */
custom_getopt_initialize(struct custom_getopt_data * d)829 static void custom_getopt_initialize(struct custom_getopt_data *d)
830 {
831 	/*
832 	 * Start processing options with ARGV-element 1 (since ARGV-element 0
833 	 * is the program name); the sequence of previously skipped non-option
834 	 * ARGV-elements is empty.
835 	 */
836 	d->first_nonopt = d->last_nonopt = d->custom_optind;
837 	d->nextchar = NULL;
838 	d->initialized = 1;
839 }
840 
841 #define NONOPTION_P (argv[d->custom_optind][0] != '-' || argv[d->custom_optind][1] == '\0')
842 
843 /* return: zero: continue, nonzero: return given value to user */
shuffle_argv(int argc,char * const * argv,const struct option * longopts,struct custom_getopt_data * d)844 static int shuffle_argv(int argc, char *const *argv,const struct option *longopts,
845 	struct custom_getopt_data *d)
846 {
847 	/*
848 	 * Give FIRST_NONOPT & LAST_NONOPT rational values if CUSTOM_OPTIND has been
849 	 * moved back by the user (who may also have changed the arguments).
850 	 */
851 	if (d->last_nonopt > d->custom_optind)
852 		d->last_nonopt = d->custom_optind;
853 	if (d->first_nonopt > d->custom_optind)
854 		d->first_nonopt = d->custom_optind;
855 	/*
856 	 * If we have just processed some options following some
857 	 * non-options, exchange them so that the options come first.
858 	 */
859 	if (d->first_nonopt != d->last_nonopt &&
860 			d->last_nonopt != d->custom_optind)
861 		exchange((char **) argv, d);
862 	else if (d->last_nonopt != d->custom_optind)
863 		d->first_nonopt = d->custom_optind;
864 	/*
865 	 * Skip any additional non-options and extend the range of
866 	 * non-options previously skipped.
867 	 */
868 	while (d->custom_optind < argc && NONOPTION_P)
869 		d->custom_optind++;
870 	d->last_nonopt = d->custom_optind;
871 	/*
872 	 * The special ARGV-element `--' means premature end of options.  Skip
873 	 * it like a null option, then exchange with previous non-options as if
874 	 * it were an option, then skip everything else like a non-option.
875 	 */
876 	if (d->custom_optind != argc && !strcmp(argv[d->custom_optind], "--")) {
877 		d->custom_optind++;
878 		if (d->first_nonopt != d->last_nonopt
879 				&& d->last_nonopt != d->custom_optind)
880 			exchange((char **) argv, d);
881 		else if (d->first_nonopt == d->last_nonopt)
882 			d->first_nonopt = d->custom_optind;
883 		d->last_nonopt = argc;
884 		d->custom_optind = argc;
885 	}
886 	/*
887 	 * If we have done all the ARGV-elements, stop the scan and back over
888 	 * any non-options that we skipped and permuted.
889 	 */
890 	if (d->custom_optind == argc) {
891 		/*
892 		 * Set the next-arg-index to point at the non-options that we
893 		 * previously skipped, so the caller will digest them.
894 		 */
895 		if (d->first_nonopt != d->last_nonopt)
896 			d->custom_optind = d->first_nonopt;
897 		return -1;
898 	}
899 	/*
900 	 * If we have come to a non-option and did not permute it, either stop
901 	 * the scan or describe it to the caller and pass it by.
902 	 */
903 	if (NONOPTION_P) {
904 		d->custom_optarg = argv[d->custom_optind++];
905 		return 1;
906 	}
907 	/*
908 	 * We have found another option-ARGV-element. Skip the initial
909 	 * punctuation.
910 	 */
911 	d->nextchar = (argv[d->custom_optind] + 1 + (longopts != NULL && argv[d->custom_optind][1] == '-'));
912 	return 0;
913 }
914 
915 /*
916  * Check whether the ARGV-element is a long option.
917  *
918  * If there's a long option "fubar" and the ARGV-element is "-fu", consider
919  * that an abbreviation of the long option, just like "--fu", and not "-f" with
920  * arg "u".
921  *
922  * This distinction seems to be the most useful approach.
923  *
924  */
check_long_opt(int argc,char * const * argv,const char * optstring,const struct option * longopts,int * longind,int print_errors,struct custom_getopt_data * d)925 static int check_long_opt(int argc, char *const *argv, const char *optstring,
926 		const struct option *longopts, int *longind,
927 		int print_errors, struct custom_getopt_data *d)
928 {
929 	char *nameend;
930 	const struct option *p;
931 	const struct option *pfound = NULL;
932 	int exact = 0;
933 	int ambig = 0;
934 	int indfound = -1;
935 	int option_index;
936 
937 	for (nameend = d->nextchar; *nameend && *nameend != '='; nameend++)
938 		/* Do nothing.  */ ;
939 
940 	/* Test all long options for either exact match or abbreviated matches */
941 	for (p = longopts, option_index = 0; p->name; p++, option_index++)
942 		if (!strncmp(p->name, d->nextchar, nameend - d->nextchar)) {
943 			if ((unsigned int) (nameend - d->nextchar)
944 					== (unsigned int) strlen(p->name)) {
945 				/* Exact match found.  */
946 				pfound = p;
947 				indfound = option_index;
948 				exact = 1;
949 				break;
950 			} else if (pfound == NULL) {
951 				/* First nonexact match found.  */
952 				pfound = p;
953 				indfound = option_index;
954 			} else if (pfound->has_arg != p->has_arg
955 					|| pfound->flag != p->flag
956 					|| pfound->val != p->val)
957 				/* Second or later nonexact match found.  */
958 				ambig = 1;
959 		}
960 	if (ambig && !exact) {
961 		if (print_errors) {
962 			fprintf(stderr,
963 				"%s: option `%s' is ambiguous\n",
964 				argv[0], argv[d->custom_optind]);
965 		}
966 		d->nextchar += strlen(d->nextchar);
967 		d->custom_optind++;
968 		d->custom_optopt = 0;
969 		return '?';
970 	}
971 	if (pfound) {
972 		option_index = indfound;
973 		d->custom_optind++;
974 		if (*nameend) {
975 			if (pfound->has_arg != no_argument)
976 				d->custom_optarg = nameend + 1;
977 			else {
978 				if (print_errors) {
979 					if (argv[d->custom_optind - 1][1] == '-') {
980 						/* --option */
981 						fprintf(stderr, "%s: option `--%s' doesn't allow an argument\n",
982 							argv[0], pfound->name);
983 					} else {
984 						/* +option or -option */
985 						fprintf(stderr, "%s: option `%c%s' doesn't allow an argument\n",
986 							argv[0], argv[d->custom_optind - 1][0], pfound->name);
987 					}
988 
989 				}
990 				d->nextchar += strlen(d->nextchar);
991 				d->custom_optopt = pfound->val;
992 				return '?';
993 			}
994 		} else if (pfound->has_arg == required_argument) {
995 			if (d->custom_optind < argc)
996 				d->custom_optarg = argv[d->custom_optind++];
997 			else {
998 				if (print_errors) {
999 					fprintf(stderr,
1000 						"%s: option `%s' requires an argument\n",
1001 						argv[0],
1002 						argv[d->custom_optind - 1]);
1003 				}
1004 				d->nextchar += strlen(d->nextchar);
1005 				d->custom_optopt = pfound->val;
1006 				return optstring[0] == ':' ? ':' : '?';
1007 			}
1008 		}
1009 		d->nextchar += strlen(d->nextchar);
1010 		if (longind != NULL)
1011 			*longind = option_index;
1012 		if (pfound->flag) {
1013 			*(pfound->flag) = pfound->val;
1014 			return 0;
1015 		}
1016 		return pfound->val;
1017 	}
1018 	/*
1019 	 * Can't find it as a long option.  If this is not getopt_long_only, or
1020 	 * the option starts with '--' or is not a valid short option, then
1021 	 * it's an error.  Otherwise interpret it as a short option.
1022 	 */
1023 	if (print_errors) {
1024 		if (argv[d->custom_optind][1] == '-') {
1025 			/* --option */
1026 			fprintf(stderr,
1027 				"%s: unrecognized option `--%s'\n",
1028 				argv[0], d->nextchar);
1029 		} else {
1030 			/* +option or -option */
1031 			fprintf(stderr,
1032 				"%s: unrecognized option `%c%s'\n",
1033 				argv[0], argv[d->custom_optind][0],
1034 				d->nextchar);
1035 		}
1036 	}
1037 	d->nextchar = (char *) "";
1038 	d->custom_optind++;
1039 	d->custom_optopt = 0;
1040 	return '?';
1041 }
1042 
check_short_opt(int argc,char * const * argv,const char * optstring,int print_errors,struct custom_getopt_data * d)1043 static int check_short_opt(int argc, char *const *argv, const char *optstring,
1044 		int print_errors, struct custom_getopt_data *d)
1045 {
1046 	char c = *d->nextchar++;
1047 	const char *temp = strchr(optstring, c);
1048 
1049 	/* Increment `custom_optind' when we start to process its last character.  */
1050 	if (*d->nextchar == '\0')
1051 		++d->custom_optind;
1052 	if (!temp || c == ':') {
1053 		if (print_errors)
1054 			fprintf(stderr, "%s: invalid option -- %c\n", argv[0], c);
1055 
1056 		d->custom_optopt = c;
1057 		return '?';
1058 	}
1059 	if (temp[1] == ':') {
1060 		if (temp[2] == ':') {
1061 			/* This is an option that accepts an argument optionally.  */
1062 			if (*d->nextchar != '\0') {
1063 				d->custom_optarg = d->nextchar;
1064 				d->custom_optind++;
1065 			} else
1066 				d->custom_optarg = NULL;
1067 			d->nextchar = NULL;
1068 		} else {
1069 			/* This is an option that requires an argument.  */
1070 			if (*d->nextchar != '\0') {
1071 				d->custom_optarg = d->nextchar;
1072 				/*
1073 				 * If we end this ARGV-element by taking the
1074 				 * rest as an arg, we must advance to the next
1075 				 * element now.
1076 				 */
1077 				d->custom_optind++;
1078 			} else if (d->custom_optind == argc) {
1079 				if (print_errors) {
1080 					fprintf(stderr,
1081 						"%s: option requires an argument -- %c\n",
1082 						argv[0], c);
1083 				}
1084 				d->custom_optopt = c;
1085 				if (optstring[0] == ':')
1086 					c = ':';
1087 				else
1088 					c = '?';
1089 			} else
1090 				/*
1091 				 * We already incremented `custom_optind' once;
1092 				 * increment it again when taking next ARGV-elt
1093 				 * as argument.
1094 				 */
1095 				d->custom_optarg = argv[d->custom_optind++];
1096 			d->nextchar = NULL;
1097 		}
1098 	}
1099 	return c;
1100 }
1101 
1102 /*
1103  * Scan elements of ARGV for option characters given in OPTSTRING.
1104  *
1105  * If an element of ARGV starts with '-', and is not exactly "-" or "--",
1106  * then it is an option element.  The characters of this element
1107  * (aside from the initial '-') are option characters.  If `getopt'
1108  * is called repeatedly, it returns successively each of the option characters
1109  * from each of the option elements.
1110  *
1111  * If `getopt' finds another option character, it returns that character,
1112  * updating `custom_optind' and `nextchar' so that the next call to `getopt' can
1113  * resume the scan with the following option character or ARGV-element.
1114  *
1115  * If there are no more option characters, `getopt' returns -1.
1116  * Then `custom_optind' is the index in ARGV of the first ARGV-element
1117  * that is not an option.  (The ARGV-elements have been permuted
1118  * so that those that are not options now come last.)
1119  *
1120  * OPTSTRING is a string containing the legitimate option characters.
1121  * If an option character is seen that is not listed in OPTSTRING,
1122  * return '?' after printing an error message.  If you set `custom_opterr' to
1123  * zero, the error message is suppressed but we still return '?'.
1124  *
1125  * If a char in OPTSTRING is followed by a colon, that means it wants an arg,
1126  * so the following text in the same ARGV-element, or the text of the following
1127  * ARGV-element, is returned in `custom_optarg'.  Two colons mean an option that
1128  * wants an optional arg; if there is text in the current ARGV-element,
1129  * it is returned in `custom_optarg', otherwise `custom_optarg' is set to zero.
1130  *
1131  * If OPTSTRING starts with `-' or `+', it requests different methods of
1132  * handling the non-option ARGV-elements.
1133  * See the comments about RETURN_IN_ORDER and REQUIRE_ORDER, above.
1134  *
1135  * Long-named options begin with `--' instead of `-'.
1136  * Their names may be abbreviated as long as the abbreviation is unique
1137  * or is an exact match for some defined option.  If they have an
1138  * argument, it follows the option name in the same ARGV-element, separated
1139  * from the option name by a `=', or else the in next ARGV-element.
1140  * When `getopt' finds a long-named option, it returns 0 if that option's
1141  * `flag' field is nonzero, the value of the option's `val' field
1142  * if the `flag' field is zero.
1143  *
1144  * The elements of ARGV aren't really const, because we permute them.
1145  * But we pretend they're const in the prototype to be compatible
1146  * with other systems.
1147  *
1148  * LONGOPTS is a vector of `struct option' terminated by an
1149  * element containing a name which is zero.
1150  *
1151  * LONGIND returns the index in LONGOPT of the long-named option found.
1152  * It is only valid when a long-named option has been found by the most
1153  * recent call.
1154  *
1155  * Return the option character from OPTS just read.  Return -1 when there are
1156  * no more options.  For unrecognized options, or options missing arguments,
1157  * `custom_optopt' is set to the option letter, and '?' is returned.
1158  *
1159  * The OPTS string is a list of characters which are recognized option letters,
1160  * optionally followed by colons, specifying that that letter takes an
1161  * argument, to be placed in `custom_optarg'.
1162  *
1163  * If a letter in OPTS is followed by two colons, its argument is optional.
1164  * This behavior is specific to the GNU `getopt'.
1165  *
1166  * The argument `--' causes premature termination of argument scanning,
1167  * explicitly telling `getopt' that there are no more options.  If OPTS begins
1168  * with `--', then non-option arguments are treated as arguments to the option
1169  * '\0'.  This behavior is specific to the GNU `getopt'.
1170  */
1171 
getopt_internal_r(int argc,char * const * argv,const char * optstring,const struct option * longopts,int * longind,struct custom_getopt_data * d)1172 static int getopt_internal_r(int argc, char *const *argv, const char *optstring,
1173 		const struct option *longopts, int *longind,
1174 		struct custom_getopt_data *d)
1175 {
1176 	int ret, print_errors = d->custom_opterr;
1177 
1178 	if (optstring[0] == ':')
1179 		print_errors = 0;
1180 	if (argc < 1)
1181 		return -1;
1182 	d->custom_optarg = NULL;
1183 
1184 	/*
1185 	 * This is a big difference with GNU getopt, since optind == 0
1186 	 * means initialization while here 1 means first call.
1187 	 */
1188 	if (d->custom_optind == 0 || !d->initialized) {
1189 		if (d->custom_optind == 0)
1190 			d->custom_optind = 1;	/* Don't scan ARGV[0], the program name.  */
1191 		custom_getopt_initialize(d);
1192 	}
1193 	if (d->nextchar == NULL || *d->nextchar == '\0') {
1194 		ret = shuffle_argv(argc, argv, longopts, d);
1195 		if (ret)
1196 			return ret;
1197 	}
1198 	if (longopts && (argv[d->custom_optind][1] == '-' ))
1199 		return check_long_opt(argc, argv, optstring, longopts,
1200 			longind, print_errors, d);
1201 	return check_short_opt(argc, argv, optstring, print_errors, d);
1202 }
1203 
custom_getopt_internal(int argc,char * const * argv,const char * optstring,const struct option * longopts,int * longind)1204 static int custom_getopt_internal(int argc, char *const *argv, const char *optstring,
1205 	const struct option *longopts, int *longind)
1206 {
1207 	int result;
1208 	/* Keep a global copy of all internal members of d */
1209 	static struct custom_getopt_data d;
1210 
1211 	d.custom_optind = custom_optind;
1212 	d.custom_opterr = custom_opterr;
1213 	result = getopt_internal_r(argc, argv, optstring, longopts,
1214 		longind, &d);
1215 	custom_optind = d.custom_optind;
1216 	custom_optarg = d.custom_optarg;
1217 	custom_optopt = d.custom_optopt;
1218 	return result;
1219 }
1220 
custom_getopt_long(int argc,char * const * argv,const char * options,const struct option * long_options,int * opt_index)1221 static int custom_getopt_long (int argc, char *const *argv, const char *options,
1222 	const struct option *long_options, int *opt_index)
1223 {
1224 	return custom_getopt_internal(argc, argv, options, long_options,
1225 		opt_index);
1226 }
1227 
1228 
1229 static char *package_name = 0;
1230 
1231 /**
1232  * @brief updates an option
1233  * @param field the generic pointer to the field to update
1234  * @param orig_field the pointer to the orig field
1235  * @param field_given the pointer to the number of occurrence of this option
1236  * @param prev_given the pointer to the number of occurrence already seen
1237  * @param value the argument for this option (if null no arg was specified)
1238  * @param possible_values the possible values for this option (if specified)
1239  * @param default_value the default value (in case the option only accepts fixed values)
1240  * @param arg_type the type of this option
1241  * @param check_ambiguity @see cmdline_parser_params.check_ambiguity
1242  * @param override @see cmdline_parser_params.override
1243  * @param no_free whether to free a possible previous value
1244  * @param multiple_option whether this is a multiple option
1245  * @param long_opt the corresponding long option
1246  * @param short_opt the corresponding short option (or '-' if none)
1247  * @param additional_error possible further error specification
1248  */
1249 static
update_arg(void * field,char ** orig_field,unsigned int * field_given,unsigned int * prev_given,char * value,const char * possible_values[],const char * default_value,cmdline_parser_arg_type arg_type,int check_ambiguity,int override,int no_free,int multiple_option,const char * long_opt,char short_opt,const char * additional_error)1250 int update_arg(void *field, char **orig_field,
1251                unsigned int *field_given, unsigned int *prev_given,
1252                char *value, const char *possible_values[],
1253                const char *default_value,
1254                cmdline_parser_arg_type arg_type,
1255                int check_ambiguity, int override,
1256                int no_free, int multiple_option,
1257                const char *long_opt, char short_opt,
1258                const char *additional_error)
1259 {
1260   char *stop_char = 0;
1261   const char *val = value;
1262   int found;
1263   char **string_field;
1264   FIX_UNUSED (field);
1265 
1266   stop_char = 0;
1267   found = 0;
1268 
1269   if (!multiple_option && prev_given && (*prev_given || (check_ambiguity && *field_given)))
1270     {
1271       if (short_opt != '-')
1272         fprintf (stderr, "%s: `--%s' (`-%c') option given more than once%s\n",
1273                package_name, long_opt, short_opt,
1274                (additional_error ? additional_error : ""));
1275       else
1276         fprintf (stderr, "%s: `--%s' option given more than once%s\n",
1277                package_name, long_opt,
1278                (additional_error ? additional_error : ""));
1279       return 1; /* failure */
1280     }
1281 
1282   if (possible_values && (found = check_possible_values((value ? value : default_value), possible_values)) < 0)
1283     {
1284       if (short_opt != '-')
1285         fprintf (stderr, "%s: %s argument, \"%s\", for option `--%s' (`-%c')%s\n",
1286           package_name, (found == -2) ? "ambiguous" : "invalid", value, long_opt, short_opt,
1287           (additional_error ? additional_error : ""));
1288       else
1289         fprintf (stderr, "%s: %s argument, \"%s\", for option `--%s'%s\n",
1290           package_name, (found == -2) ? "ambiguous" : "invalid", value, long_opt,
1291           (additional_error ? additional_error : ""));
1292       return 1; /* failure */
1293     }
1294 
1295   if (field_given && *field_given && ! override)
1296     return 0;
1297   if (prev_given)
1298     (*prev_given)++;
1299   if (field_given)
1300     (*field_given)++;
1301   if (possible_values)
1302     val = possible_values[found];
1303 
1304   switch(arg_type) {
1305   case ARG_LONG:
1306     if (val) *((long *)field) = (long)strtol (val, &stop_char, 0);
1307     break;
1308   case ARG_STRING:
1309     if (val) {
1310       string_field = (char **)field;
1311       if (!no_free && *string_field)
1312         free (*string_field); /* free previous string */
1313       *string_field = gengetopt_strdup (val);
1314     }
1315     break;
1316   default:
1317     break;
1318   };
1319 
1320   /* check numeric conversion */
1321   switch(arg_type) {
1322   case ARG_LONG:
1323     if (val && !(stop_char && *stop_char == '\0')) {
1324       fprintf(stderr, "%s: invalid numeric value: %s\n", package_name, val);
1325       return 1; /* failure */
1326     }
1327     break;
1328   default:
1329     ;
1330   };
1331 
1332   /* store the original value */
1333   switch(arg_type) {
1334   case ARG_NO:
1335     break;
1336   default:
1337     if (value && orig_field) {
1338       if (no_free) {
1339         *orig_field = value;
1340       } else {
1341         if (*orig_field)
1342           free (*orig_field); /* free previous string */
1343         *orig_field = gengetopt_strdup (value);
1344       }
1345     }
1346   };
1347 
1348   return 0; /* OK */
1349 }
1350 
1351 /**
1352  * @brief store information about a multiple option in a temporary list
1353  * @param list where to (temporarily) store multiple options
1354  */
1355 static
update_multiple_arg_temp(struct generic_list ** list,unsigned int * prev_given,const char * val,const char * possible_values[],const char * default_value,cmdline_parser_arg_type arg_type,const char * long_opt,char short_opt,const char * additional_error)1356 int update_multiple_arg_temp(struct generic_list **list,
1357                unsigned int *prev_given, const char *val,
1358                const char *possible_values[], const char *default_value,
1359                cmdline_parser_arg_type arg_type,
1360                const char *long_opt, char short_opt,
1361                const char *additional_error)
1362 {
1363   /* store single arguments */
1364   char *multi_token;
1365   const char *multi_next;
1366 
1367   if (arg_type == ARG_NO) {
1368     (*prev_given)++;
1369     return 0; /* OK */
1370   }
1371 
1372   multi_token = get_multiple_arg_token(val);
1373   multi_next = get_multiple_arg_token_next (val);
1374 
1375   while (1)
1376     {
1377       add_node (list);
1378       if (update_arg((void *)&((*list)->arg), &((*list)->orig), 0,
1379           prev_given, multi_token, possible_values, default_value,
1380           arg_type, 0, 1, 1, 1, long_opt, short_opt, additional_error)) {
1381         if (multi_token) free(multi_token);
1382         return 1; /* failure */
1383       }
1384 
1385       if (multi_next)
1386         {
1387           multi_token = get_multiple_arg_token(multi_next);
1388           multi_next = get_multiple_arg_token_next (multi_next);
1389         }
1390       else
1391         break;
1392     }
1393 
1394   return 0; /* OK */
1395 }
1396 
1397 /**
1398  * @brief free the passed list (including possible string argument)
1399  */
1400 static
free_list(struct generic_list * list,short string_arg)1401 void free_list(struct generic_list *list, short string_arg)
1402 {
1403   if (list) {
1404     struct generic_list *tmp;
1405     while (list)
1406       {
1407         tmp = list;
1408         if (string_arg && list->arg.string_arg)
1409           free (list->arg.string_arg);
1410         if (list->orig)
1411           free (list->orig);
1412         list = list->next;
1413         free (tmp);
1414       }
1415   }
1416 }
1417 
1418 /**
1419  * @brief updates a multiple option starting from the passed list
1420  */
1421 static
update_multiple_arg(void * field,char *** orig_field,unsigned int field_given,unsigned int prev_given,union generic_value * default_value,cmdline_parser_arg_type arg_type,struct generic_list * list)1422 void update_multiple_arg(void *field, char ***orig_field,
1423                unsigned int field_given, unsigned int prev_given, union generic_value *default_value,
1424                cmdline_parser_arg_type arg_type,
1425                struct generic_list *list)
1426 {
1427   int i;
1428   struct generic_list *tmp;
1429 
1430   if (prev_given && list) {
1431     *orig_field = (char **) realloc (*orig_field, (field_given + prev_given) * sizeof (char *));
1432 
1433     switch(arg_type) {
1434     case ARG_LONG:
1435       *((long **)field) = (long *)realloc (*((long **)field), (field_given + prev_given) * sizeof (long)); break;
1436     case ARG_STRING:
1437       *((char ***)field) = (char **)realloc (*((char ***)field), (field_given + prev_given) * sizeof (char *)); break;
1438     default:
1439       break;
1440     };
1441 
1442     for (i = (prev_given - 1); i >= 0; --i)
1443       {
1444         tmp = list;
1445 
1446         switch(arg_type) {
1447         case ARG_LONG:
1448           (*((long **)field))[i + field_given] = tmp->arg.long_arg; break;
1449         case ARG_STRING:
1450           (*((char ***)field))[i + field_given] = tmp->arg.string_arg; break;
1451         default:
1452           break;
1453         }
1454         (*orig_field) [i + field_given] = list->orig;
1455         list = list->next;
1456         free (tmp);
1457       }
1458   } else { /* set the default value */
1459     if (default_value && ! field_given) {
1460       switch(arg_type) {
1461       case ARG_LONG:
1462         if (! *((long **)field)) {
1463           *((long **)field) = (long *)malloc (sizeof (long));
1464           (*((long **)field))[0] = default_value->long_arg;
1465         }
1466         break;
1467       case ARG_STRING:
1468         if (! *((char ***)field)) {
1469           *((char ***)field) = (char **)malloc (sizeof (char *));
1470           (*((char ***)field))[0] = gengetopt_strdup(default_value->string_arg);
1471         }
1472         break;
1473       default: break;
1474       }
1475       if (!(*orig_field)) {
1476         *orig_field = (char **) malloc (sizeof (char *));
1477         (*orig_field)[0] = 0;
1478       }
1479     }
1480   }
1481 }
1482 
1483 int
cmdline_parser_internal(int argc,char ** argv,struct gengetopt_args_info * args_info,struct cmdline_parser_params * params,const char * additional_error)1484 cmdline_parser_internal (
1485   int argc, char **argv, struct gengetopt_args_info *args_info,
1486                         struct cmdline_parser_params *params, const char *additional_error)
1487 {
1488   int c;	/* Character of the parsed option.  */
1489 
1490   struct generic_list * extensions_list = NULL;
1491   int error_occurred = 0;
1492   struct gengetopt_args_info local_args_info;
1493 
1494   int override;
1495   int initialize;
1496   int check_required;
1497   int check_ambiguity;
1498 
1499   char *optarg;
1500   int optind;
1501   int opterr;
1502   int optopt;
1503 
1504   package_name = argv[0];
1505 
1506   /* TODO: Why is this here? It is not used anywhere. */
1507   override = params->override;
1508   FIX_UNUSED(override);
1509 
1510   initialize = params->initialize;
1511   check_required = params->check_required;
1512 
1513   /* TODO: Why is this here? It is not used anywhere. */
1514   check_ambiguity = params->check_ambiguity;
1515   FIX_UNUSED(check_ambiguity);
1516 
1517   if (initialize)
1518     cmdline_parser_init (args_info);
1519 
1520   cmdline_parser_init (&local_args_info);
1521 
1522   optarg = 0;
1523   optind = 0;
1524   opterr = params->print_errors;
1525   optopt = '?';
1526 
1527   while (1)
1528     {
1529       int option_index = 0;
1530 
1531       static struct option long_options[] = {
1532         { "help",	0, NULL, 'h' },
1533         { "input-format",	1, NULL, 'i' },
1534         { "output-format",	1, NULL, 'o' },
1535         { "extensions",	1, NULL, 'e' },
1536         { "events-limit",	1, NULL, 0 },
1537         { "first-event-number",	1, NULL, 0 },
1538         { "last-event-number",	1, NULL, 0 },
1539         { "print-every-events-parsed",	1, NULL, 0 },
1540         { 0,  0, 0, 0 }
1541       };
1542 
1543       custom_optarg = optarg;
1544       custom_optind = optind;
1545       custom_opterr = opterr;
1546       custom_optopt = optopt;
1547 
1548       c = custom_getopt_long (argc, argv, "hi:o:e:", long_options, &option_index);
1549 
1550       optarg = custom_optarg;
1551       optind = custom_optind;
1552       opterr = custom_opterr;
1553       optopt = custom_optopt;
1554 
1555       if (c == -1) break;	/* Exit from `while (1)' loop.  */
1556 
1557       switch (c)
1558         {
1559         case 'h':	/* Print help and exit.  */
1560           cmdline_parser_print_help ();
1561           cmdline_parser_free (&local_args_info);
1562           exit (EXIT_SUCCESS);
1563 
1564         case 'i':	/* Input format.  */
1565 
1566 
1567           if (update_arg( (void *)&(args_info->input_format_arg),
1568                &(args_info->input_format_orig), &(args_info->input_format_given),
1569               &(local_args_info.input_format_given), optarg, cmdline_parser_input_format_values, 0, ARG_STRING,
1570               check_ambiguity, override, 0, 0,
1571               "input-format", 'i',
1572               additional_error))
1573             goto failure;
1574 
1575           break;
1576         case 'o':	/* Output format.  */
1577 
1578 
1579           if (update_arg( (void *)&(args_info->output_format_arg),
1580                &(args_info->output_format_orig), &(args_info->output_format_given),
1581               &(local_args_info.output_format_given), optarg, cmdline_parser_output_format_values, 0, ARG_STRING,
1582               check_ambiguity, override, 0, 0,
1583               "output-format", 'o',
1584               additional_error))
1585             goto failure;
1586 
1587           break;
1588         case 'e':	/* Extensions, in a form extension=value, could be passed to readers/writers.  */
1589 
1590           if (update_multiple_arg_temp(&extensions_list,
1591               &(local_args_info.extensions_given), optarg, 0, 0, ARG_STRING,
1592               "extensions", 'e',
1593               additional_error))
1594             goto failure;
1595 
1596           break;
1597 
1598         case 0:	/* Long option with no short option */
1599           /* Limit of events to read from input.  */
1600           if (strcmp (long_options[option_index].name, "events-limit") == 0)
1601           {
1602 
1603 
1604             if (update_arg( (void *)&(args_info->events_limit_arg),
1605                  &(args_info->events_limit_orig), &(args_info->events_limit_given),
1606                 &(local_args_info.events_limit_given), optarg, 0, "100000000", ARG_LONG,
1607                 check_ambiguity, override, 0, 0,
1608                 "events-limit", '-',
1609                 additional_error))
1610               goto failure;
1611 
1612           }
1613           /* Lowest allowed event number.  */
1614           else if (strcmp (long_options[option_index].name, "first-event-number") == 0)
1615           {
1616 
1617 
1618             if (update_arg( (void *)&(args_info->first_event_number_arg),
1619                  &(args_info->first_event_number_orig), &(args_info->first_event_number_given),
1620                 &(local_args_info.first_event_number_given), optarg, 0, "-100000000", ARG_LONG,
1621                 check_ambiguity, override, 0, 0,
1622                 "first-event-number", '-',
1623                 additional_error))
1624               goto failure;
1625 
1626           }
1627           /* Highest allowed event number.  */
1628           else if (strcmp (long_options[option_index].name, "last-event-number") == 0)
1629           {
1630 
1631 
1632             if (update_arg( (void *)&(args_info->last_event_number_arg),
1633                  &(args_info->last_event_number_orig), &(args_info->last_event_number_given),
1634                 &(local_args_info.last_event_number_given), optarg, 0, "100000000", ARG_LONG,
1635                 check_ambiguity, override, 0, 0,
1636                 "last-event-number", '-',
1637                 additional_error))
1638               goto failure;
1639 
1640           }
1641           /* Frequency of parsing information printouts.  */
1642           else if (strcmp (long_options[option_index].name, "print-every-events-parsed") == 0)
1643           {
1644 
1645 
1646             if (update_arg( (void *)&(args_info->print_every_events_parsed_arg),
1647                  &(args_info->print_every_events_parsed_orig), &(args_info->print_every_events_parsed_given),
1648                 &(local_args_info.print_every_events_parsed_given), optarg, 0, "100", ARG_LONG,
1649                 check_ambiguity, override, 0, 0,
1650                 "print-every-events-parsed", '-',
1651                 additional_error))
1652               goto failure;
1653 
1654           }
1655 
1656           break;
1657         case '?':	/* Invalid option.  */
1658           /* `getopt_long' already printed an error message.  */
1659           goto failure;
1660 
1661         default:	/* bug: option not considered.  */
1662           fprintf (stderr, "%s: option unknown: %c%s\n", CMDLINE_PARSER_PACKAGE, c, (additional_error ? additional_error : ""));
1663           abort ();
1664         } /* switch */
1665     } /* while */
1666 
1667 
1668   update_multiple_arg((void *)&(args_info->extensions_arg),
1669     &(args_info->extensions_orig), args_info->extensions_given,
1670     local_args_info.extensions_given, 0,
1671     ARG_STRING, extensions_list);
1672 
1673   args_info->extensions_given += local_args_info.extensions_given;
1674   local_args_info.extensions_given = 0;
1675 
1676   if (check_required)
1677     {
1678       error_occurred += cmdline_parser_required2 (args_info, argv[0], additional_error);
1679     }
1680 
1681   cmdline_parser_release (&local_args_info);
1682 
1683   if ( error_occurred )
1684     return (EXIT_FAILURE);
1685 
1686   if (optind < argc)
1687     {
1688       int i = 0 ;
1689       int found_prog_name = 0;
1690       /* whether program name, i.e., argv[0], is in the remaining args
1691          (this may happen with some implementations of getopt,
1692           but surely not with the one included by gengetopt) */
1693 
1694 
1695       args_info->inputs_num = argc - optind - found_prog_name;
1696       args_info->inputs =
1697         (char **)(malloc ((args_info->inputs_num)*sizeof(char *))) ;
1698       while (optind < argc)
1699         args_info->inputs[ i++ ] = gengetopt_strdup (argv[optind++]) ;
1700     }
1701 
1702   return 0;
1703 
1704 failure:
1705   free_list (extensions_list, 1 );
1706 
1707   cmdline_parser_release (&local_args_info);
1708   return (EXIT_FAILURE);
1709 }
1710 /* vim: set ft=c noet ts=8 sts=8 sw=8 tw=80 nojs spell : */
1711