]> Creatis software - clitk.git/blob - cmake/gengetopt/gengetopt.cc
Added FindGengetopt.cmake which compiles gengetopt if not installed.
[clitk.git] / cmake / gengetopt / gengetopt.cc
1 /**
2  * Copyright (C) 1999-2007  Free Software Foundation, Inc.
3  *
4  * This file is part of GNU gengetopt
5  *
6  * GNU gengetopt is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3, or (at your option)
9  * any later version.
10  *
11  * GNU gengetopt is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
14  * Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License along
17  * with gengetopt; see the file COPYING. If not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19  */
20
21 #ifdef HAVE_CONFIG_H
22 #include "config.h"
23 #endif
24
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <iostream>
29
30 void gengetopt_free (void);
31
32 /* The following one is generated by gengetopt itself */
33 #include "cmdline.h"
34
35 extern int yyparse () ;
36
37 #include "gengetopt.h"
38 #include "errorcodes.h"
39
40 #include "argsdef.h"
41 #include "global_opts.h"
42
43 #include "my_sstream.h"
44 #include "my_string.h"
45
46 #include "gm.h"
47 #include "groups.h"
48 #include "gm_utils.h"
49
50 #include "skels/copyright.h"
51
52 #include "yyerror.h"
53 #include "globals.h"
54
55 char * gengetopt_package = NULL;
56 char * gengetopt_version = NULL;
57 char * gengetopt_purpose = NULL;
58 char * gengetopt_description = NULL;
59 char * gengetopt_usage = NULL;
60
61 modes_collection_t gengetopt_modes;
62
63 int gengetopt_count_line = 1;
64 char * gengetopt_input_filename = 0;
65 char *current_section = 0;
66 char *current_section_desc = 0;
67 char *current_text = 0;
68 char *current_args = 0;
69
70 /// whether, if not specified, an option is considered optional
71 bool default_to_optional = false;
72
73 int canonize_vars (void);
74 static void set_default_required_properties(void);
75
76 static void print_copyright();
77 static void print_reportbugs();
78
79 static void output_formatted_string(const string &);
80
81 static bool check_dependencies();
82
83 static int gengetopt_create_option (gengetopt_option *&opt, const char * long_opt, char short_opt,
84                           const char * desc,
85                           int type, int flagstat, int required,
86                           const char *default_value,
87                           const char * group_value,
88                           const char * mode_value,
89                           const char * type_str,
90                           const AcceptedValues *acceptedvalues,
91                           int multiple = 0,
92                           int argoptional = 0);
93
94
95 #include <algorithm>
96 #include <iterator>
97
98 using namespace std;
99
100 /// the structure for command line arguments
101 struct gengetopt_args_info args_info ;
102
103 int
104 main (int argc, char **argv)
105 {
106   char *cmdline_parser_name ; /* name of the generated function */
107   char *cmdline_filename ; /* name of generated file */
108   char *c_ext ; /* extenstion of c file */
109   char *header_ext  ; /* extenstion of header file */
110   string output_dir, header_output_dir, src_output_dir; /* output directory (default empty -> current dir)*/
111
112   int i, has_help, has_version;
113   FILE *input_file ;
114
115   if (cmdline_parser (argc, argv, &args_info) != 0) {
116       fprintf (stderr, "Run gengetopt --help to see the list of options.\n");
117       exit(1) ;
118   }
119
120   if (args_info.help_given)
121   {
122     cmdline_parser_print_help ();
123     print_reportbugs ();
124     exit (0);
125   }
126
127   if (args_info.detailed_help_given)
128     {
129       cmdline_parser_print_detailed_help ();
130       print_reportbugs ();
131       exit (0);
132     }
133
134   if (args_info.version_given)
135   {
136     cmdline_parser_print_version ();
137     print_copyright ();
138     exit (0);
139   }
140
141   if ( args_info.input_arg )
142     {
143       gengetopt_input_filename = strdup (args_info.input_arg);
144       input_file = freopen (args_info.input_arg, "r", stdin) ;
145       if (!input_file)
146         {
147           fprintf (stderr, "Error opening input file: %s\n",
148                    args_info.input_arg);
149           exit (1);
150         }
151     } /* else standard input is used */
152
153   if (yyparse () != 0) {
154         gengetopt_free ();
155         return 1;
156   }
157
158   // check whether some options were given in the input file
159   bool no_options = (gengetopt_options.size() == 0);
160
161   if (current_args) {
162     // parse the arguments passed in the "args" part of the input file
163     // by possibily overriding those given at command line
164     if (cmdline_parser_string2 (current_args, &args_info, "gengetopt", 1, 0, 0) != 0) {
165       fprintf (stderr, "Error in the args specification of the input_file.\n");
166       exit(1) ;
167     }
168   }
169
170   cmdline_parser_name = args_info.func_name_arg ;
171   cmdline_filename = args_info.file_name_arg ;
172   c_ext = args_info.c_extension_arg;
173   header_ext = args_info.header_extension_arg;
174
175   default_to_optional = args_info.default_optional_given;
176
177   // now set the default "required" property for options
178   set_default_required_properties();
179
180   if (! check_dependencies()) {
181     gengetopt_free();
182     return 1;
183   }
184
185   // insert options for help and version if not already present
186   gengetopt_option *opt;
187
188   if (current_section)
189     free(current_section);
190   current_section = 0;
191
192   has_version = gengetopt_has_option (VERSION_LONG_OPT, VERSION_SHORT_OPT);
193
194   if (has_version != REQ_LONG_OPTION && !args_info.no_version_given) {
195     gengetopt_create_option (opt, VERSION_LONG_OPT, has_version ? '-' : VERSION_SHORT_OPT,
196                                  VERSION_OPT_DESCR, ARG_NO, 0, 0, 0, 0, 0, 0, 0);
197     gengetopt_options.push_front(opt);
198   }
199
200   if (!args_info.no_help_given && has_hidden_options() && gengetopt_has_option(FULL_HELP_LONG_OPT, 0) == 0) {
201       gengetopt_create_option (opt, FULL_HELP_LONG_OPT, '-',
202                                FULL_HELP_OPT_DESCR, ARG_NO, 0, 0, 0, 0, 0, 0, 0);
203       gengetopt_options.push_front(opt);
204   }
205
206   if (!args_info.no_help_given && has_options_with_details() && gengetopt_has_option(DETAILED_HELP_LONG_OPT, 0) == 0) {
207       gengetopt_create_option (opt, DETAILED_HELP_LONG_OPT, '-',
208               DETAILED_HELP_OPT_DESCR, ARG_NO, 0, 0, 0, 0, 0, 0, 0);
209       gengetopt_options.push_front(opt);
210   }
211
212   has_help = gengetopt_has_option(HELP_LONG_OPT, HELP_SHORT_OPT);
213
214   if (has_help != REQ_LONG_OPTION && !args_info.no_help_given) {
215     gengetopt_create_option (opt, HELP_LONG_OPT, has_help ? '-' : HELP_SHORT_OPT,
216                                  HELP_OPT_DESCR, ARG_NO, 0, 0, 0, 0, 0, 0, 0);
217     gengetopt_options.push_front(opt);
218   }
219
220   // check whether there's pending text after all options and
221   // in case, set it to the last option
222   if (current_text && gengetopt_options.size()) {
223     gengetopt_options.back()->text_after = current_text;
224     gengetopt_set_text(0);
225   }
226
227   if (canonize_vars ()) {
228         gengetopt_free ();
229         return 1;
230   }
231
232   if (args_info.set_package_given) {
233     if (gengetopt_package)
234       free (gengetopt_package);
235     gengetopt_package = args_info.set_package_arg;
236   }
237
238   if (args_info.set_version_given) {
239     if (gengetopt_version)
240       free (gengetopt_version);
241     gengetopt_version = args_info.set_version_arg;
242   }
243
244   ostringstream command_line;
245   for ( i = 0; i < argc ; ++i )
246       command_line << argv[i] << " ";
247
248   // add also possible args specification in the input file
249   if (current_args)
250     command_line << current_args;
251
252   if (args_info.output_dir_given)
253       output_dir = args_info.output_dir_arg;
254   if (args_info.header_output_dir_given)
255       header_output_dir = args_info.header_output_dir_arg;
256   if (args_info.src_output_dir_given)
257       src_output_dir = args_info.src_output_dir_arg;
258
259   CmdlineParserCreator cmdline_parser_creator
260     (cmdline_parser_name,
261      args_info.arg_struct_name_arg,
262      (args_info.unamed_opts_given ? args_info.unamed_opts_arg : 0),
263      cmdline_filename,
264      header_ext,
265      c_ext,
266      args_info.long_help_given,
267      args_info.no_handle_help_given,
268      args_info.no_help_given,
269      args_info.no_handle_version_given,
270      args_info.no_version_given,
271      args_info.no_handle_error_given,
272      args_info.conf_parser_given,
273      args_info.string_parser_given,
274      args_info.gen_version_flag,
275      args_info.include_getopt_given,
276      no_options,
277      command_line.str (),
278      output_dir,
279      header_output_dir,
280      src_output_dir,
281      (args_info.show_required_given ? args_info.show_required_arg : ""));
282
283   if (! gengetopt_package && (args_info.show_version_given || args_info.show_help_given))
284     {
285       cerr << "package not defined; please specify it with --set-package" << endl;
286       return 1;
287     }
288   else if (! gengetopt_version && (args_info.show_version_given || args_info.show_help_given))
289     {
290       cerr << "version not defined; please specify it with --set-version" << endl;
291       return 1;
292     }
293   else if (args_info.show_version_given)
294     {
295       cout << gengetopt_package << " " << gengetopt_version << endl;
296     }
297   else if (args_info.show_help_given ||
298           args_info.show_full_help_given || args_info.show_detailed_help_given)
299     {
300       cout << gengetopt_package << " " << gengetopt_version << "\n" << endl;
301
302       if (gengetopt_purpose) {
303         output_formatted_string(cmdline_parser_creator.generate_purpose());
304         cout << endl;
305       }
306
307       output_formatted_string("Usage: " +
308         cmdline_parser_creator.generate_usage_string(false) + "\n");
309
310       if (gengetopt_description) {
311         output_formatted_string(cmdline_parser_creator.generate_description());
312         cout << endl;
313       }
314
315       // if --show-full-help is specified we have to generate also hidden options
316       OptionHelpList *option_list =
317           cmdline_parser_creator.generate_help_option_list(args_info.show_full_help_given, args_info.show_detailed_help_given);
318
319       std::for_each(option_list->begin(), option_list->end(),
320               output_formatted_string);
321
322       delete option_list;
323     }
324   else if (cmdline_parser_creator.generate ())
325     {
326         gengetopt_free ();
327         return 1;
328     }
329
330   gengetopt_free ();
331
332   return 0;
333 }
334
335 void
336 output_formatted_string(const string &s)
337 {
338   for (string::const_iterator it = s.begin(); it != s.end(); ++it)
339     {
340       if (*it == '\\' && ((it+1) != s.end()) && *(it+1) == 'n') {
341         cout << "\n";
342         ++it;
343       } else if (*it == '\\' && ((it+1) != s.end()) && *(it+1) == '"') {
344         cout << "\"";
345         ++it;
346       } else
347         cout << *it;
348     }
349
350   cout << endl;
351 }
352
353 /* ************* */
354
355 int
356 gengetopt_define_package (char * s)
357 {
358         gengetopt_package = strdup (s);
359         if (gengetopt_package == NULL)
360                 return 1;
361         return 0;
362 }
363
364 int
365 gengetopt_define_version (char * s)
366 {
367         gengetopt_version = strdup (s);
368         if (gengetopt_version == NULL)
369                 return 1;
370         return 0;
371 }
372
373 int
374 gengetopt_define_purpose (char * s)
375 {
376   gengetopt_purpose = strdup (s);
377   if (gengetopt_purpose == NULL)
378     return 1;
379   return 0;
380 }
381
382 int
383 gengetopt_define_description (char * s)
384 {
385   gengetopt_description = strdup (s);
386   if (gengetopt_description == NULL)
387     return 1;
388   return 0;
389 }
390
391 int gengetopt_define_usage (char * s)
392 {
393   gengetopt_usage = strdup (s);
394   if (gengetopt_usage == NULL)
395     return 1;
396   return 0;
397 }
398
399 int
400 gengetopt_add_group (const char *s, const char *desc, int required)
401 {
402   string group_desc;
403   if (desc)
404     group_desc = desc;
405   if ( !gengetopt_groups.insert
406        (make_pair(string(s),Group (group_desc, required != 0))).second )
407     return 1;
408   else
409     return 0;
410 }
411
412 int
413 gengetopt_add_mode (const char *s, const char *desc)
414 {
415   string mode_desc;
416   if (desc)
417     mode_desc = desc;
418   if ( !gengetopt_modes.insert
419        (make_pair(string(s),Mode (mode_desc))).second )
420     return 1;
421   else
422     return 0;
423 }
424
425 void
426 gengetopt_set_section (const char * s, const char *desc)
427 {
428   if (current_section)
429     free (current_section);
430   if (current_section_desc)
431     free (current_section_desc);
432   current_section = strdup (s);
433   if (desc)
434     current_section_desc = strdup (desc);
435   else
436     current_section_desc = 0;
437 }
438
439 void
440 gengetopt_set_text (const char * desc)
441 {
442   /*
443   no need to free it, since it will be then owned by the
444   option only
445
446   if (current_text)
447     free (current_text);
448   */
449
450   // the current text is reset
451   if (!desc) {
452     current_text = 0;
453     return;
454   }
455
456   if (current_text) {
457     // a previous text was collected, so we append the new text
458     // to the current one.
459     string buffer = current_text;
460     buffer += desc;
461     current_text = strdup(buffer.c_str());
462     return;
463   }
464
465   // otherwise simply copy the passed text
466   current_text = strdup (desc);
467 }
468
469 void gengetopt_set_args(const char *a)
470 {
471   if (current_args)
472     free(current_args);
473
474   if (a)
475     current_args = strdup(a);
476   else
477     current_args = 0;
478 }
479
480 int
481 gengetopt_has_option (const char * long_opt, char short_opt)
482 {
483   gengetopt_option * n;
484
485   for (gengetopt_option_list::const_iterator it = gengetopt_options.begin();
486        it != gengetopt_options.end(); ++it)
487     {
488       n = *it;
489       if (!strcmp (n->long_opt, long_opt)) return REQ_LONG_OPTION;
490       if (short_opt && n->short_opt == short_opt)
491         return REQ_SHORT_OPTION;
492     }
493
494   return 0;
495 }
496
497 bool check_numeric_validity(const char *val, int opt_type)
498 {
499     char *end_of_string, *expected_eos;
500
501     expected_eos = (char *) (val + strlen(val));
502
503     switch ( opt_type )
504       {
505       case ARG_INT :
506       case ARG_SHORT :
507       case ARG_LONG :
508       case ARG_LONGLONG :
509         (void) strtol(val, &end_of_string, 0);
510         break;
511
512       case ARG_FLOAT:
513       case ARG_DOUBLE:
514       case ARG_LONGDOUBLE:
515         (void) strtod(val, &end_of_string);
516         break;
517
518       default :
519         // This will allow us to factorise as a single line the
520         // test for correctness of the default value
521         end_of_string = expected_eos;
522         break;
523       }
524     return ( end_of_string == expected_eos );
525 }
526
527 bool
528 check_values(const AcceptedValues *acceptedvalues, int opt_type)
529 {
530     for (AcceptedValues::const_iterator it = acceptedvalues->begin();
531         it != acceptedvalues->end(); ++it) {
532         if (!check_numeric_validity((*it).c_str(), opt_type))
533             return false;
534     }
535
536     return true;
537 }
538
539 int
540 gengetopt_create_option (gengetopt_option *&n, const char * long_opt, char short_opt,
541                       const char * desc,
542                       int type, int flagstat, int required,
543                       const char * default_value,
544                       const char * group_value,
545                       const char * mode_value,
546                       const char * type_str,
547                       const AcceptedValues *acceptedvalues,
548                       int multiple,
549                       int argoptional)
550 {
551   if ((long_opt == NULL) ||
552       (long_opt[0] == 0) ||
553       (desc == NULL))
554     return FOUND_BUG;
555
556   n = new gengetopt_option;
557   if (n == NULL)
558     return NOT_ENOUGH_MEMORY;
559
560   // here we will set required anyway
561   n->required_set = true;
562
563   n->long_opt = strdup (long_opt);
564   if (n->long_opt == NULL)
565     {
566       free (n);
567       return NOT_ENOUGH_MEMORY;
568     }
569
570   n->desc = strdup (desc);
571   if (n->desc == NULL)
572     {
573       free (n->long_opt);
574       free (n);
575       return NOT_ENOUGH_MEMORY;
576     }
577
578   n->short_opt = ((short_opt == '-') ? 0 : short_opt);
579   n->type = type;
580   n->flagstat = flagstat;
581   n->required = required;
582   n->multiple = (multiple != 0);
583   n->arg_is_optional = (argoptional != 0);
584
585   if (type_str != 0)
586     n->type_str = strdup(type_str);
587   else
588     n->type_str = NULL;
589
590   n->section = 0;
591   n->section_desc = 0;
592   if (current_section)
593     n->section = strdup (current_section);
594   if (current_section_desc)
595     n->section_desc = strdup (current_section_desc);
596
597   if (group_value != 0)
598     {
599       n->group_value = strdup(group_value);
600       n->required = 0;
601       groups_collection_t::const_iterator it =
602         gengetopt_groups.find(string(n->group_value));
603       if (it == gengetopt_groups.end())
604         return GROUP_UNDEFINED;
605       n->group_desc = strdup (it->second.desc.c_str ());
606     }
607   else
608     {
609       n->group_value = 0;
610     }
611
612   if (mode_value != 0) {
613       n->mode_value = strdup(mode_value);
614       modes_collection_t::const_iterator it =
615           gengetopt_modes.find(string(n->mode_value));
616       if (it == gengetopt_modes.end())
617           return MODE_UNDEFINED;
618       n->mode_desc = strdup (it->second.desc.c_str ());
619   } else {
620       n->mode_value = 0;
621   }
622
623   if (n->group_value && n->mode_value)
624       return FOUND_BUG;
625
626
627   n->acceptedvalues = acceptedvalues;
628
629   // if (acceptedvalues && type != ARG_NO)
630   // return NOT_REQUESTED_TYPE;
631
632   if (acceptedvalues && ! (n->type))
633     n->type = ARG_STRING;
634
635   n->default_string = 0;
636   n->default_given = (default_value != 0);
637   if (n->default_given)
638     {
639       n->default_string = strdup (default_value);
640       if ( ! check_numeric_validity(default_value, n->type) )
641         {
642           free (n);
643           return INVALID_DEFAULT_VALUE;
644         }
645
646       if (acceptedvalues)
647         {
648           if (! acceptedvalues->contains(n->default_string))
649             return INVALID_DEFAULT_VALUE;
650         }
651     }
652
653   if (acceptedvalues) {
654       if (!check_values(acceptedvalues, n->type))
655           return INVALID_NUMERIC_VALUE;
656   }
657
658   n->var_arg = NULL;
659
660   return 0;
661 }
662
663 int
664 gengetopt_check_option (gengetopt_option *n, bool groupoption, bool modeoption)
665 {
666   if ((n->long_opt == NULL) ||
667       (n->long_opt[0] == 0) ||
668       (n->desc == NULL))
669     return FOUND_BUG;
670
671   if (strcmp(n->long_opt, HELP_LONG_OPT) == 0 && !args_info.no_help_given)
672       return HELP_REDEFINED;
673
674   if (strcmp(n->long_opt, VERSION_LONG_OPT) == 0 && !args_info.no_version_given)
675       return VERSION_REDEFINED;
676
677   n->section = 0;
678   n->section_desc = 0;
679   if (current_section)
680     n->section = strdup (current_section);
681   if (current_section_desc)
682     n->section_desc = strdup (current_section_desc);
683
684   n->text_before = current_text;
685   // reset the description
686   gengetopt_set_text(0);
687
688   if (n->group_value != 0)
689   {
690       if (! groupoption)
691           return NOT_GROUP_OPTION;
692
693       n->required = 0;
694       n->required_set = true;
695
696       groups_collection_t::const_iterator it =
697           gengetopt_groups.find(string(n->group_value));
698       if (it == gengetopt_groups.end())
699           return GROUP_UNDEFINED;
700       n->group_desc = strdup (it->second.desc.c_str ());
701   }
702   else
703   {
704       if (groupoption)
705           return SPECIFY_GROUP;
706   }
707
708   if (n->mode_value != 0)
709   {
710       if (! modeoption)
711           return NOT_MODE_OPTION;
712
713       modes_collection_t::const_iterator it =
714           gengetopt_modes.find(string(n->mode_value));
715       if (it == gengetopt_modes.end())
716           return MODE_UNDEFINED;
717       n->mode_desc = strdup (it->second.desc.c_str ());
718   }
719   else
720   {
721       if (modeoption)
722           return SPECIFY_MODE;
723   }
724
725   if (n->group_value && n->mode_value)
726       return FOUND_BUG;
727
728   // now we have to check for flag options
729   if (n->type == ARG_FLAG)
730   {
731     if (n->flagstat < 0)
732       return SPECIFY_FLAG_STAT;
733
734     if (n->default_string || n->multiple || n->arg_is_optional
735         || n->type_str || n->acceptedvalues || n->required_set)
736       return NOT_VALID_SPECIFICATION;
737
738     n->required = 0;
739     n->required_set = true;
740   }
741   else
742   {
743     if (n->flagstat >= 0)
744       return NOT_VALID_SPECIFICATION;
745   }
746
747   // enum type can only be specified with options with values
748   if (n->type == ARG_ENUM && !(n->acceptedvalues)) {
749       return INVALID_ENUM_TYPE_USE;
750   }
751
752   // if (acceptedvalues && type != ARG_NO)
753   // return NOT_REQUESTED_TYPE;
754
755   if (n->acceptedvalues && ! (n->type))
756     n->type = ARG_STRING;
757
758   n->default_given = (n->default_string != 0);
759   if (n->default_given)
760     {
761       if ( !check_numeric_validity(n->default_string, n->type) )
762         {
763           return INVALID_DEFAULT_VALUE;
764         }
765
766       if (n->acceptedvalues)
767         {
768           if (! n->acceptedvalues->contains(n->default_string))
769             return INVALID_DEFAULT_VALUE;
770         }
771     }
772
773   if (n->acceptedvalues) {
774       if (!check_values(n->acceptedvalues, n->type))
775           return INVALID_NUMERIC_VALUE;
776   }
777
778   n->var_arg = NULL;
779
780   return 0;
781 }
782
783 int
784 gengetopt_add_option (const char * long_opt, char short_opt,
785                       const char * desc,
786                       int type, int flagstat, int required,
787                       const char * default_value,
788                       const char * group_value,
789                       const char * mode_value,
790                       const char * type_str,
791                       const AcceptedValues *acceptedvalues,
792                       int multiple,
793                       int argoptional)
794 {
795   gengetopt_option * n;
796
797   /* search for collisions */
798   int res = gengetopt_has_option(long_opt, short_opt);
799   if (res != 0)
800     return res;
801
802   res = gengetopt_create_option(n, long_opt, short_opt,
803     desc, type, flagstat, required, default_value, group_value, mode_value,
804     type_str, acceptedvalues, multiple, argoptional);
805   if (res != 0)
806     return res;
807
808   gengetopt_options.push_back(n);
809
810   return 0;
811 }
812
813 int
814 gengetopt_add_option (gengetopt_option * n)
815 {
816   /* search for collisions */
817   int res = gengetopt_has_option(n);
818   if (res != 0)
819     return res;
820
821   gengetopt_options.push_back(n);
822
823   return 0;
824 }
825
826 int
827 gengetopt_has_option (gengetopt_option * opt)
828 {
829   gengetopt_option * n;
830
831   for (gengetopt_option_list::const_iterator it = gengetopt_options.begin();
832        it != gengetopt_options.end(); ++it)
833     {
834       n = *it;
835       if (!strcmp (n->long_opt, opt->long_opt))
836         return REQ_LONG_OPTION;
837       if (opt->short_opt && n->short_opt == opt->short_opt)
838         return REQ_SHORT_OPTION;
839     }
840
841   return 0;
842 }
843
844 bool
845 check_dependencies()
846 {
847   gengetopt_option * n;
848   bool result = true;
849
850   for (gengetopt_option_list::const_iterator it = gengetopt_options.begin();
851        it != gengetopt_options.end(); ++it)
852   {
853     n = *it;
854     if (n->dependon) {
855         if (strcmp(n->dependon, n->long_opt) == 0) {
856             yyerror(n, "option depends on itself");
857             result = false;
858             continue;
859         }
860
861         bool found = false;
862         for (gengetopt_option_list::const_iterator it2 = gengetopt_options.begin();
863             it2 != gengetopt_options.end(); ++it2)
864         {
865             if (strcmp(n->dependon, (*it2)->long_opt) == 0) {
866                 found = true;
867                 break;
868             }
869         }
870
871         if (! found) {
872             yyerror (n, "option depends on undefined option");
873             result = false;
874         }
875     }
876   }
877
878   return result;
879 }
880
881 void
882 gengetopt_free (void)
883 {
884   gengetopt_option *p;
885
886   if (gengetopt_package != NULL)
887     free (gengetopt_package);
888
889   for (gengetopt_option_list::iterator it = gengetopt_options.begin(); it != gengetopt_options.end(); ++it)
890   {
891         p = *it;
892         if (p->long_opt != NULL) free (p->long_opt);
893         if (p->desc != NULL) free (p->desc);
894         if (p->var_arg != NULL) free (p->var_arg);
895         if (p->acceptedvalues) delete p->acceptedvalues;
896         delete p;
897   }
898 }
899
900 static void
901 canonize_var (gengetopt_option *p)
902 {
903   char *pvar;
904
905   p->var_arg = strdup (p->long_opt);
906   if (p->var_arg == NULL) {
907       printf ("gengetopt: not enough memory to canonize vars\n");
908       abort();
909   }
910
911   for (pvar = p->var_arg; *pvar; pvar++)
912     if (*pvar == '.' || *pvar == '-') *pvar = '_';
913 }
914
915 int
916 canonize_vars (void)
917 {
918   for_each(gengetopt_options.begin(), gengetopt_options.end(), canonize_var);
919
920   return 0;
921 }
922
923 static void
924 set_default_required_prop (gengetopt_option *p)
925 {
926     if (!p->required_set)
927         p->required = (default_to_optional ? 0 : 1);
928 }
929
930 static void set_default_required_properties(void)
931 {
932   for_each(gengetopt_options.begin(), gengetopt_options.end(), set_default_required_prop);
933 }
934
935 void
936 print_copyright()
937 {
938   copyright_gen_class copyright_g;
939
940   copyright_g.set_year ("1999-2009");
941   copyright_g.generate_copyright (cout);
942 }
943
944 void
945 print_reportbugs()
946 {
947   cout << endl;
948   cout << "Maintained by Lorenzo Bettini <http://www.lorenzobettini.it>" << endl;
949   cout << "Report bugs to <bug-gengetopt at gnu.org>" << endl;
950 }