Line data Source code
1 : // Copyright (c) 2006-2022 Made to Order Software Corp. All Rights Reserved
2 : //
3 : // https://snapwebsites.org/project/advgetopt
4 : // contact@m2osw.com
5 : //
6 : // This program 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 2 of the License, or
9 : // (at your option) any later version.
10 : //
11 : // This program is distributed in the hope that it will be useful,
12 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : // GNU General Public License for more details.
15 : //
16 : // You should have received a copy of the GNU General Public License along
17 : // with this program; if not, write to the Free Software Foundation, Inc.,
18 : // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 :
20 : /** \file
21 : * \brief Advanced getopt implementation.
22 : *
23 : * The advgetopt class and implementation is an advanced library to parse
24 : * command line parameters from static definitions specified by the caller.
25 : *
26 : * The class supports the command line options, options found in a default
27 : * configuration file or in a user defined configuration file.
28 : *
29 : * The class also includes support for displaying error messages and help
30 : * information about all the command line arguments.
31 : */
32 :
33 :
34 : /** \mainpage
35 : * The advanced getopt library to handle your command line tools seemlessly.
36 : *
37 : * The library offers an advanced way to parse command line arguments,
38 : * an environment variable, and configuration files in a seamless manner.
39 : * The advgetopt::getopt class is what is used everywhere for that purpose.
40 : *
41 : * The class can be used in a very restrictive mode, meaning that all
42 : * the parameters must clearly be defined by the application. It can also
43 : * be used in a dynamic way where the parameters are dynamically added
44 : * to the list of available options.
45 : *
46 : * The library supports multiple levels in your options. The simplest
47 : * is to use a scope operator like so:
48 : *
49 : * \code
50 : * level1::level2::level3::etc = 123
51 : * \endcode
52 : *
53 : * \note
54 : * The library understands the scope operator (::), the period (.), and
55 : * the slash (/) as level separator. So the following are equivalent.
56 : * Internally, all are changed to the scope operator (::).
57 : *
58 : * \code
59 : * level1::level2::level3::etc = 123
60 : * level1.level2.level3.etc = 123
61 : * level1/level2/level3/etc = 123
62 : * \endcode
63 : *
64 : * The labels in a .ini format (i.e. `[name]` defines sections) are viewed
65 : * as a first level. That name automatically get prepended to the parameters
66 : * appearing under them. Additional levels can be added by using the
67 : * scope operator, again.
68 : *
69 : * \code
70 : * [level1]
71 : * level2::level3::etc = 123
72 : * \endcode
73 : *
74 : * Support for other formats may be added later. For example, we could
75 : * read XML and JSON files. Right now, we are focused on Unix configuration
76 : * files and pretty much never even need two levels.
77 : *
78 : * The library is capable of writing your configuration back to file. It
79 : * will know when a value was modified and only the modified values get
80 : * saved to the read/write configuration file(s). (Either the user file
81 : * or the system file under the `\<proc>.d/...` sub-path.)
82 : */
83 :
84 : // self
85 : //
86 : #include "advgetopt/advgetopt.h"
87 :
88 : #include "advgetopt/exception.h"
89 :
90 :
91 : // cppthread
92 : //
93 : #include <cppthread/log.h>
94 :
95 :
96 : // libutf8
97 : //
98 : #include <libutf8/iterator.h>
99 :
100 :
101 : // boost
102 : //
103 : #include <boost/algorithm/string/replace.hpp>
104 :
105 :
106 : // last include
107 : //
108 : #include <snapdev/poison.h>
109 :
110 :
111 :
112 :
113 :
114 : /** \brief The advgetopt environment to parse command line options.
115 : *
116 : * This namespace encompasses all the declarations and implementations
117 : * of functions used to parse and access the command line options.
118 : */
119 : namespace advgetopt
120 : {
121 :
122 :
123 : namespace
124 : {
125 :
126 :
127 : /** \brief Definitions of the system options.
128 : *
129 : * The system options are options we add automatically (if the user asked
130 : * for them) and handle automatically when they are found.
131 : *
132 : * The following are the currently supported system options:
133 : *
134 : * \li `--help`
135 : *
136 : * Print out the usage() with most of the command line arguments.
137 : *
138 : * \li '--long-help'
139 : *
140 : * Print all the command line arguments with usage().
141 : *
142 : * The long help is is only added if the list of options include at least
143 : * one group flag (GETOPT_FLAG_SHOW_GROUP1 or GETOPT_FLAG_SHOW_GROUP2).
144 : * See the getopt::parse_options_from_group_names() in advgetopt_usage.cpp.
145 : *
146 : * \li '--\<name>-help'
147 : *
148 : * Print the help from the group named \<name>.
149 : *
150 : * These command line options are added only when groups are defined.
151 : *
152 : * \li `--version`
153 : *
154 : * Print out the version.
155 : *
156 : * \li `--copyright`
157 : *
158 : * Print out the copyright notice.
159 : *
160 : * \li `--license`
161 : *
162 : * Print out the license notice.
163 : *
164 : * \li `--build-date`
165 : *
166 : * Print out the build time and date.
167 : *
168 : * \li `--environment-variable-name`
169 : *
170 : * Print out the build time and date.
171 : *
172 : * \li `--configuration-filenames`
173 : *
174 : * Print out the list of configuration file names that the system checks
175 : * for configuration data.
176 : *
177 : * \li `--path-to-option-definitions`
178 : *
179 : * Print out the path to files which define options for this tool.
180 : *
181 : * \li `--source-option-sources`
182 : *
183 : * Print out all the options and their sources. This shows you where a
184 : * value come from: command line, environment variable, configuration file,
185 : * etc.
186 : *
187 : * \todo
188 : * Add a `--config` option to allow the user to name one specific
189 : * configuration file to use with an executable.
190 : */
191 : option const g_system_options[] =
192 : {
193 : define_option(
194 : Name("build-date")
195 : , Flags(standalone_command_flags<GETOPT_FLAG_GROUP_COMMANDS>())
196 : , Help("print out the time and date when %p was built and exit.")
197 : ),
198 : define_option(
199 : Name("compiler-version")
200 : , Flags(standalone_command_flags<GETOPT_FLAG_GROUP_COMMANDS>())
201 : , Help("print the version of the compiler used to compile the advgetopt library.")
202 : ),
203 : define_option(
204 : Name("configuration-filenames")
205 : , Flags(standalone_command_flags<GETOPT_FLAG_GROUP_COMMANDS>())
206 : , Help("print out the list of configuration files checked out by this tool.")
207 : ),
208 : define_option(
209 : Name("copyright")
210 : , ShortName('C')
211 : , Flags(standalone_command_flags<GETOPT_FLAG_GROUP_COMMANDS>())
212 : , Help("print out the copyright of %p and exit.")
213 : ),
214 : define_option(
215 : Name("environment-variable-name")
216 : , Flags(standalone_command_flags<GETOPT_FLAG_GROUP_COMMANDS>())
217 : , Help("print out the name of the environment variable supported by %p (if any.)")
218 : ),
219 : define_option(
220 : Name("has-sanitizer")
221 : , Flags(standalone_command_flags<GETOPT_FLAG_GROUP_COMMANDS>())
222 : , Help("print whether the advgetopt was compiled with the sanitizer extension.")
223 : ),
224 : define_option(
225 : Name("help")
226 : , ShortName('h')
227 : , Flags(standalone_command_flags<GETOPT_FLAG_GROUP_COMMANDS
228 : , GETOPT_FLAG_SHOW_USAGE_ON_ERROR>())
229 : , Help("print out this help screen and exit.")
230 : ),
231 : define_option(
232 : Name("license")
233 : , ShortName('L')
234 : , Flags(standalone_command_flags<GETOPT_FLAG_GROUP_COMMANDS>())
235 : , Help("print out the license of %p and exit.")
236 : ),
237 : define_option(
238 : Name("path-to-option-definitions")
239 : , Flags(standalone_command_flags<GETOPT_FLAG_GROUP_COMMANDS>())
240 : , Help("print out the path to the option definitions.")
241 : ),
242 : define_option(
243 : Name("print-option")
244 : , Flags(command_flags<GETOPT_FLAG_GROUP_COMMANDS
245 : , GETOPT_FLAG_REQUIRED>())
246 : , Help("print the value of the named option after loading all the command line options.")
247 : ),
248 : define_option(
249 : Name("show-option-sources")
250 : , Flags(standalone_command_flags<GETOPT_FLAG_GROUP_COMMANDS>())
251 : , Help("parse all the options and then print out the source of each value and each override.")
252 : ),
253 : define_option(
254 : Name("version")
255 : , ShortName('V')
256 : , Flags(standalone_command_flags<GETOPT_FLAG_GROUP_COMMANDS>())
257 : , Help("print out the version of %p and exit.")
258 : ),
259 : end_options()
260 : };
261 :
262 :
263 : /** \brief Optional list of options.
264 : *
265 : * This optional list of options is added only when the
266 : * f_configuration_filename parameter has a valid filename.
267 : *
268 : * The following are the currently added options:
269 : *
270 : * \li `--config-dir`
271 : *
272 : * This option allows for adding more configuration directories.
273 : * These work the same way as directories defined in the
274 : * f_configuration_directories.
275 : */
276 : option const g_if_configuration_filename_system_options[] =
277 : {
278 : define_option(
279 : Name("config-dir")
280 : , Flags(any_flags<GETOPT_FLAG_COMMAND_LINE
281 : , GETOPT_FLAG_ENVIRONMENT_VARIABLE
282 : , GETOPT_FLAG_REQUIRED
283 : , GETOPT_FLAG_MULTIPLE
284 : , GETOPT_FLAG_GROUP_OPTIONS>())
285 : , Help("add one or more configuration directory paths to search for configuration files.")
286 : ),
287 : end_options()
288 : };
289 :
290 :
291 :
292 :
293 : /** \brief Check whether this parameter is an argument.
294 : *
295 : * An argument is defined as a command line parameter that starts with
296 : * a dash and is not just "-".
297 : *
298 : * Note that "--" is viewed as an argument (this function returns true)
299 : * and the getopt class takes it as a command meaning any other parameter
300 : * is not an argument.
301 : */
302 260 : bool is_arg(char const * a)
303 : {
304 : // "-" and "--" are not options; however "--" returns true
305 : // because after a "--" we take the data as default arguments
306 260 : return a[0] == '-' && a[1] != '\0';
307 : }
308 :
309 :
310 :
311 : /** \brief Check for a "--show-option-sources" flag.
312 : *
313 : * When this flag is defined, we turn on the trace mode in the option_info
314 : * class (which is a global flag). That way we can honor the
315 : * "--show-option-sources" when we are done parsing the configuration files,
316 : * environment variable, and command line.
317 : *
318 : * \param[in] argc The number of items in the \p argv array.
319 : * \param[in] argv The arguments.
320 : */
321 537 : void check_for_show_sources(int argc, char * argv[])
322 : {
323 : static bool found = false;
324 :
325 537 : if(!found && argv != nullptr)
326 : {
327 1107 : for(int idx(1); idx < argc; ++idx)
328 : {
329 714 : if(strcmp(argv[idx], "--show-option-sources") == 0)
330 : {
331 1 : found = true;
332 1 : option_info::set_trace_sources(true);
333 : }
334 : }
335 : }
336 537 : }
337 :
338 :
339 :
340 : } // no name namespace
341 :
342 :
343 :
344 : /** \class getopt_exception
345 : * \brief Base exception of the advgetopt class.
346 : *
347 : * This exception is the base exception of all the advgetopt exceptions.
348 : * Catching this exception allows you to capture all the getopt exceptions.
349 : */
350 :
351 :
352 : /** \class getopt_exception_default
353 : * \brief No default and no value specified.
354 : *
355 : * When a parameter is not specified and no default is available, this
356 : * exception is raised.
357 : */
358 :
359 :
360 : /** \class getopt_exception_undefined
361 : * \brief Attempting to access something that is undefined.
362 : *
363 : * This exception is used when you attempt to access data that was not
364 : * defined. For example, if your tool tries to read parameter "version"
365 : * and that was not defined in the list of options, this exception is
366 : * raised.
367 : */
368 :
369 :
370 : /** \class getopt_exception_invalid
371 : * \brief Attempted to use some invalid data.
372 : *
373 : * This exception is used whenever an attempt is made to access data that
374 : * does not make sense (is invalid.)
375 : *
376 : * For example, the table of options makes use of enumerations for different
377 : * parts. If one of these has a value which does not represent a valid
378 : * enumeration value, then this exception is raised.
379 : */
380 :
381 :
382 : /** \class getopt
383 : * \brief Class used to parse command line options.
384 : *
385 : * This class is the one used by all the wpkg tools to parse the command line
386 : * options. It is very advanced and is capable to read many different types
387 : * of options with a letter (-h) and a word (--verbose) with no parameters,
388 : * one parameter, any number of parameters, and a set of "filenames" (lose
389 : * options that are not specific to an option.)
390 : */
391 :
392 :
393 : /** \struct option
394 : * \brief Structure representing an option.
395 : *
396 : * When creating a getopt() object you have to pass an array of options. That
397 : * array is defined as a set of option structures.
398 : *
399 : * The last option must be an end_options(). It has its f_flags set to
400 : * GETOPT_FLAG_END and all the other parameters are set to zero (i.e. no
401 : * name, no short name, etc.)
402 : *
403 : * Note that with the newer version of the library, you are not expected
404 : * to manually define an array of options. Instead, you want to use the
405 : * C++ functions such as Name(), ShortName(), Flags(), etc. These functions
406 : * are capable of verifying that at least some of the values are valid at
407 : * compile time.
408 : */
409 :
410 :
411 : /** \brief Initialize the getopt object.
412 : *
413 : * \section into Introduction
414 : *
415 : * This constructor initializes a getopt object. It also reads and parses
416 : * the corresponding option configuration file if it exists (based on the
417 : * project name defined in the environment parameter.)
418 : *
419 : * \section program_name Program Name
420 : *
421 : * Once constructed, if you want to have access to the program name, make
422 : * sure to call this function with your `argv` variable:
423 : *
424 : * \code
425 : * opt.parse_program_name(argv);
426 : * \endcode
427 : *
428 : * Remember that the program name is often used in error messages so having
429 : * it defined early is generally a good idea.
430 : *
431 : * \section dynamism Dynamic Options
432 : *
433 : * This constructor is most often used when you want to dynamically add
434 : * options to your executable with the parse_options_info() function.
435 : * For example, the list of options may vary slightly depending on what
436 : * your command is named when launched.
437 : *
438 : * For example:
439 : *
440 : * \code
441 : * if(time(nullptr) & 1)
442 : * {
443 : * opt.parse_options_info(odd_options);
444 : * }
445 : * else
446 : * {
447 : * opt.parse_options_info(even_options);
448 : * }
449 : * \endcode
450 : *
451 : * \section aliases Linking Aliases
452 : *
453 : * After you added all your dynamic options, you want to make sure that
454 : * aliases are linked to the final option. You should always call that
455 : * function because you can't be sure whether someone will add such an
456 : * alias in the .ini option file.
457 : *
458 : * \code
459 : * opt.link_aliases();
460 : * \endcode
461 : *
462 : * You can call this function any number of times. So if you add yet
463 : * more dynamic options at a later time, just make sure to call it
464 : * again in case aliases were added.
465 : *
466 : * \section parse Parse the Arguments
467 : *
468 : * Finally, you want to call the following functions in that order to
469 : * parse the data from configuration files, the environment variable,
470 : * and the list of command line arguments:
471 : *
472 : * \code
473 : * opt.parse_configuration_files();
474 : * opt.parse_environment_variable();
475 : * opt.parse_arguments(argc, argv, option_source_t::SOURCE_COMMAND_LINE);
476 : * \endcode
477 : *
478 : * The order is important because the last command line option found is
479 : * the one kept. So if the same argument is found in the configuration
480 : * file, the environment variable and the command line, the one on the
481 : * command line is kept. In most cases it makes no difference for standalone
482 : * flags, but arguments that expect a parameter will be changed to the last
483 : * specified value.
484 : *
485 : * If you want to determine the configuration filenames, you may use the
486 : * process_configuration_file() function directly instead of the
487 : * parse_configuration_files() function. This also gives you the ability
488 : * to test whether a configuration file was indeed read.
489 : *
490 : * Note that the parse_arguments() last parameter (only_environment_variable)
491 : * is expected to be left along when you call it with `argc` and `argv`.
492 : *
493 : * If you just have a string instead of an `argv` variable, call the
494 : * parse_string() function instead. It will transform your string in an
495 : * array of arguments and then call the parse_arguments() for you.
496 : *
497 : * \attention
498 : * Note that the program name does not get defined until you call the
499 : * parse_program_name() function since that information comes from the
500 : * first arguments of your command line which we do not get on
501 : * construction in this case.
502 : *
503 : * \attention
504 : * Since the arguments are not known to the getopt system yet, the
505 : * GETOPT_ENVIRONMENT_FLAG_PROCESS_SYSTEM_PARAMETERS is not used in
506 : * this case.
507 : *
508 : * \param[in] opt_env The list of options that your program supports.
509 : *
510 : * \sa link_aliases()
511 : * \sa parse_arguments()
512 : * \sa parse_configuration_files()
513 : * \sa parse_environment_variable()
514 : * \sa parse_string()
515 : * \sa process_configuration_file()
516 : *
517 : * \sa initialize_parser()
518 : * \sa finish_parsing()
519 : */
520 103 : getopt::getopt(options_environment const & opt_env)
521 : {
522 103 : initialize_parser(opt_env);
523 103 : }
524 :
525 :
526 : /** \brief Initialize the getopt object.
527 : *
528 : * The constructor initializes a getopt object and parse the specified
529 : * argv array. If defined, it also parses a configuration file and
530 : * an environment variable.
531 : *
532 : * The order in which parameters are parsed is important since only the
533 : * last value is kept:
534 : *
535 : * \li Each existing configuration file in the order defined in the vector;
536 : * \li The environment variable;
537 : * \li the argv array.
538 : *
539 : * The constructor calls the reset() function to start the parsing. It is
540 : * possible to call the reset() function at any time to parse a new set
541 : * of parameters.
542 : *
543 : * The argv array cannot be nullptr and the array cannot be empty. It must have
544 : * at least one entry representing the program name (argv[0]).
545 : *
546 : * The configuration_files vector can be empty in which case no configuration
547 : * files are read.
548 : *
549 : * The environment_variable_name can be nullptr or the empty string in which case
550 : * it is ignored.
551 : *
552 : * \note
553 : * All the data gets copied while parsed. If the argv array is deleted on
554 : * return, the getopt object remains valid.
555 : *
556 : * \exception getopt_exit
557 : * This function calls finish_parsing() which may throw this exception.
558 : * See that function for details.
559 : *
560 : * \param[in] opt_env The list of options that your program supports.
561 : * \param[in] argc The number of arguments in argv.
562 : * \param[in] argv An array of strings representing arguments.
563 : *
564 : * \sa initialize_parser()
565 : * \sa finish_parsing()
566 : */
567 262 : getopt::getopt(options_environment const & opt_env
568 : , int argc
569 289 : , char * argv[])
570 : {
571 : // TODO: I do not think that this check_for_show_sources() is required
572 : // because we also do it in finish_parsing()
573 : //
574 262 : check_for_show_sources(argc, argv);
575 :
576 262 : initialize_parser(opt_env);
577 252 : finish_parsing(argc, argv);
578 235 : }
579 :
580 :
581 : /** \brief Initialize the parser.
582 : *
583 : * This function is called from the two constructors. It initializes the
584 : * basic options from the user definitions, the file when there is one,
585 : * the group names, and if allowed the system command line options.
586 : *
587 : * This is enough to then parse arguments or configuration files, although
588 : * in most cases this is used to allow for additional environment options
589 : * to be inserted before calling the finish_parsing() function.
590 : *
591 : * \param[in] opt_env The list of options that your program supports.
592 : */
593 365 : void getopt::initialize_parser(options_environment const & opt_env)
594 : {
595 365 : f_variables = std::make_shared<variables>();
596 365 : f_options_environment = opt_env;
597 :
598 365 : parse_options_info(f_options_environment.f_options, false);
599 357 : parse_options_from_file();
600 355 : parse_options_from_group_names();
601 355 : if(has_flag(GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS | GETOPT_ENVIRONMENT_FLAG_PROCESS_SYSTEM_PARAMETERS))
602 : {
603 95 : parse_options_info(g_system_options, true);
604 95 : if(f_options_environment.f_configuration_filename != nullptr
605 19 : && *f_options_environment.f_configuration_filename != '\0')
606 : {
607 : // add the "--config-dir <path> ..." option
608 : //
609 16 : parse_options_info(g_if_configuration_filename_system_options, true);
610 : }
611 : }
612 :
613 355 : define_environment_variable_data();
614 355 : }
615 :
616 :
617 : /** \brief Actually parse everything.
618 : *
619 : * This function allows you to run the second half of the initialization
620 : * process. We've broken this process up in two, so you can initialize
621 : * a getopt object, add some other options, then finish up the
622 : * initialization process by calling this function.
623 : *
624 : * The command line arguments, configuration files.
625 : *
626 : * \exception getopt_exit
627 : * If the GETOPT_ENVIRONMENT_FLAG_PROCESS_SYSTEM_PARAMETERS is set and
628 : * a system command was specified on the command, such as --help or
629 : * --version, then that command is run and the function throws this
630 : * exception.
631 : *
632 : * \param[in] argc The number of arguments in argv.
633 : * \param[in] argv An array of strings representing arguments.
634 : */
635 276 : void getopt::finish_parsing(int argc, char * argv[])
636 : {
637 276 : if(argv == nullptr)
638 : {
639 1 : throw getopt_logic_error("argv pointer cannot be nullptr");
640 : }
641 :
642 275 : check_for_show_sources(argc, argv);
643 :
644 275 : parse_program_name(argv);
645 275 : if(f_options_by_name.empty())
646 : {
647 3 : throw getopt_logic_error("an empty list of options is not legal, you must defined at least one (i.e. --version, --help...)");
648 : }
649 :
650 272 : link_aliases();
651 :
652 268 : parse_configuration_files(argc, argv);
653 268 : f_parsed = false;
654 268 : parse_environment_variable();
655 268 : f_parsed = false;
656 268 : parse_arguments(argc, argv, option_source_t::SOURCE_COMMAND_LINE, false);
657 :
658 268 : if(has_flag(GETOPT_ENVIRONMENT_FLAG_PROCESS_SYSTEM_PARAMETERS))
659 : {
660 14 : flag_t const result(process_system_options(std::cout));
661 14 : if((result & SYSTEM_OPTION_COMMANDS_MASK) != 0)
662 : {
663 7 : throw getopt_exit("system command processed.", 0);
664 : }
665 : }
666 :
667 261 : if(cppthread::log.get_errors() != 0)
668 : {
669 23 : throw getopt_exit("errors were found on your command line, environment variable, or configuration file.", 1);
670 : }
671 238 : }
672 :
673 :
674 : /** \brief Verify that the parser is done.
675 : *
676 : * This function ensures that the parser is done. If the parser is not yet
677 : * done, then the function raises an exception. This allows me to detect
678 : * that I am trying to access a parameter before the whole parsing process
679 : * is done (i.e. I had a call to is_defined("config-dir") happening in the
680 : * configuration handling way before the environment variables and command
681 : * line arguments were parsed, that would never work!)
682 : *
683 : * \exception getopt_initialization
684 : * This exception is raised if the parser is not done yet.
685 : */
686 3209 : void getopt::is_parsed() const
687 : {
688 3209 : if(!f_parsed
689 7 : && (f_options_environment.f_environment_flags & GETOPT_ENVIRONMENT_FLAG_AUTO_DONE) == 0)
690 : {
691 : throw getopt_initialization(
692 : "function called too soon, parser is not done yet"
693 : " (i.e. is_defined(), get_string(), get_long(),"
694 7 : " get_double() cannot be called until the parser is done)");
695 : }
696 3202 : }
697 :
698 :
699 : /** \brief Return a reference to the options environment.
700 : *
701 : * This function returns a reference to the options environment that
702 : * was passed to the constructor. This is useful to functions that
703 : * do not otherwise have access to that object.
704 : *
705 : * \return This getopt options environment.
706 : */
707 1 : options_environment const & getopt::get_options_environment() const
708 : {
709 1 : return f_options_environment;
710 : }
711 :
712 :
713 : /** \brief Check whether an environment flag is set or not.
714 : *
715 : * This function checks the environment flags for the specified \p flag.
716 : * When the flag is set, the function returns true.
717 : *
718 : * You may test multiple flags at the same time, if any one of them is set,
719 : * then the function returns true.
720 : *
721 : * \param[in] flag The flag to check out.
722 : *
723 : * \return true if the flag is set.
724 : */
725 789 : bool getopt::has_flag(flag_t flag) const
726 : {
727 789 : return (f_options_environment.f_environment_flags & flag) != 0;
728 : }
729 :
730 :
731 : /** \brief Retrieve the environment variable string.
732 : *
733 : * This function retrieves the environment variable string and saves it
734 : * in the f_environment_variable field. This is used to parse that string
735 : * and add option values, and also by the configuration file loader to see
736 : * whether a --config-dir was used in there.
737 : */
738 356 : void getopt::define_environment_variable_data()
739 : {
740 356 : f_environment_variable.clear();
741 :
742 356 : if(f_options_environment.f_environment_variable_name == nullptr
743 121 : || *f_options_environment.f_environment_variable_name == '\0')
744 : {
745 : // no name
746 : //
747 240 : return;
748 : }
749 :
750 116 : char const * s(getenv(f_options_environment.f_environment_variable_name));
751 116 : if(s == nullptr)
752 : {
753 : // no environment variable with that name
754 : //
755 66 : return;
756 : }
757 :
758 50 : f_environment_variable = s;
759 : }
760 :
761 :
762 : /** \brief Check for an environment variable.
763 : *
764 : * If the name of an environment variable is specified in the option
765 : * environment structure, then it is read as a command line string.
766 : * This function parses the string in an array of strings and then parses
767 : * it as an argv array (just like the argv parameter defined in a main()
768 : * function).
769 : *
770 : * Since the environment variable is checked after the configuration files,
771 : * the options defined in the variable can change the definitions from
772 : * the configuration files.
773 : *
774 : * Like in the configuration files, only options can be specified in the
775 : * environment variable and commands generate an error. The system knows
776 : * since options that can be included in the environment variable are
777 : * marked by the GETOPT_FLAG_ENVIRONMENT_VARIABLE flag. In other words,
778 : * you may allow options to appear on the command line, in configuration
779 : * files, in environment variables or a mix of all of these locations.
780 : *
781 : * \note
782 : * If you change the environment variable between the creation of the
783 : * getopt object and a call to this function, you want to call the
784 : * define_environment_variable_data() again to make sure it can be
785 : * parsed.
786 : */
787 275 : void getopt::parse_environment_variable()
788 : {
789 : // first test the global environment variable
790 : //
791 275 : if(!f_environment_variable.empty())
792 : {
793 52 : parse_string(
794 : f_environment_variable
795 : , option_source_t::SOURCE_ENVIRONMENT_VARIABLE
796 : , true);
797 : }
798 :
799 : // second check each option environment variable
800 : //
801 1483 : for(auto const & opt : f_options_by_name)
802 : {
803 2416 : std::string const name(opt.second->get_environment_variable_name());
804 :
805 : // get the value, only set the option if the variable is set
806 : //
807 2416 : std::string value;
808 1208 : if(opt.second->get_environment_variable_value(
809 : value
810 : , f_options_environment.f_environment_variable_intro))
811 : {
812 26 : add_option_from_string(
813 : opt.second
814 : , value
815 26 : , std::string()
816 : , option_source_t::SOURCE_ENVIRONMENT_VARIABLE);
817 : }
818 : }
819 :
820 275 : f_parsed = true;
821 275 : }
822 :
823 :
824 : /** \brief Parse a string similar to a command line argument.
825 : *
826 : * This function parses a line of command line arguments from a string.
827 : * Especially, it is used to parse the environment variable which is
828 : * a string of arguments.
829 : *
830 : * This can be used to parse the command line string as received under
831 : * MS-Windows (i.e. an unparsed one long string of arguments, where
832 : * you also need to do the glob() calls yourself.)
833 : *
834 : * This function actually transforms the input string in an array of
835 : * strings and then calls the parse_arguments() function.
836 : *
837 : * \note
838 : * The input allows for an empty string in which case pretty much nothing
839 : * happens.
840 : *
841 : * \param[in] str The string that is going to be parsed.
842 : * \param[in] source Where the value comes from.
843 : * \param[in] only_environment_variable Whether only options marked with
844 : * the GETOPT_FLAG_ENVIRONMENT_VARIABLE flag are accepted.
845 : */
846 53 : void getopt::parse_string(
847 : std::string const & str
848 : , option_source_t source
849 : , bool only_environment_variable)
850 : {
851 105 : string_list_t args(split_environment(str));
852 53 : if(args.empty())
853 : {
854 : // nothing extra to do
855 : //
856 1 : return;
857 : }
858 :
859 : // TODO: expand the arguments that include unquoted '*', '?', '[...]'
860 : // (note that we remove the quotes at the moment so we'd have
861 : // to keep track of that specific problem...)
862 :
863 : // the argv array has to be a null terminated bare string pointers
864 : //
865 104 : std::vector<char *> sub_argv;
866 :
867 52 : sub_argv.resize(args.size() + 2);
868 :
869 : // argv[0] is the program name
870 : //
871 52 : sub_argv[0] = const_cast<char *>(f_program_fullname.c_str());
872 :
873 : // the other arguments are from the variable
874 : //
875 257 : for(size_t idx(0); idx < args.size(); ++idx)
876 : {
877 205 : sub_argv[idx + 1] = const_cast<char *>(args[idx].c_str());
878 : }
879 :
880 : // this is probably already a nullptr
881 : //
882 52 : sub_argv[args.size() + 1] = nullptr;
883 :
884 : // now convert those parameters in values
885 : //
886 104 : parse_arguments(
887 52 : static_cast<int>(sub_argv.size() - 1)
888 : , sub_argv.data()
889 : , source
890 : , only_environment_variable);
891 : }
892 :
893 :
894 : /** \brief Transform a string in an array of arguments.
895 : *
896 : * This function is used to transform a string to an array of arguments
897 : * that can then be used with the parse_arguments() function.
898 : *
899 : * For example, it is used to parse the environment variable string.
900 : *
901 : * \note
902 : * The input string may include quotes. These will be removed. There is
903 : * currently no support for the backslash character.
904 : *
905 : * \param[in] environment The string to be split in arguments.
906 : *
907 : * \return An array of strings.
908 : */
909 59 : string_list_t getopt::split_environment(std::string const & environment)
910 : {
911 : // this is exactly like the command line only in an environment variable
912 : // so parse the parameters just like the shell
913 : //
914 59 : string_list_t args;
915 118 : std::string a;
916 59 : char const * s(environment.c_str());
917 3745 : while(*s != '\0')
918 : {
919 1843 : if(isspace(*s))
920 : {
921 167 : if(!a.empty())
922 : {
923 165 : args.push_back(a);
924 165 : a.clear();
925 : }
926 1 : do
927 : {
928 168 : ++s;
929 : }
930 168 : while(isspace(*s));
931 : }
932 1676 : else if(*s == '"'
933 1673 : || *s == '\'')
934 : {
935 : // support quotations and remove them from the argument
936 : //
937 5 : char const quote(*s++);
938 359 : while(*s != '\0'
939 182 : && *s != quote)
940 : {
941 177 : a += *s++;
942 : }
943 5 : if(*s != '\0')
944 : {
945 5 : ++s;
946 5 : }
947 : }
948 : else
949 : {
950 1671 : a += *s++;
951 : }
952 : }
953 :
954 59 : if(!a.empty())
955 : {
956 51 : args.push_back(a);
957 : }
958 :
959 118 : return args;
960 : }
961 :
962 :
963 : /** \brief Parse an array of arguments.
964 : *
965 : * This function accepts an array of arguments as received by the main()
966 : * function. By default, though, you pass the argc/argv parameters to
967 : * the getopt() constructor which automatically calls this function.
968 : *
969 : * This functin is public so you can call it with additional lists of
970 : * arguments. If that list of arguments comes as a string, you may want
971 : * to call the parse_string() function instead. It will transform your
972 : * string in a list of parameters for you.
973 : *
974 : * When the \p only_environment_variable parameter is set to true, then
975 : * it is considered that the input arguments were found in an environment
976 : * variables and they are only accepted if the corresponding option
977 : * definition includes the GETOPT_FLAG_ENVIRONMENT_VARIABLE flag.
978 : *
979 : * When the \p only_environment_variable parameter is set to false, the
980 : * arguments are viewed as command line arguments and the corresponding
981 : * options must include the GETOPT_FLAG_COMMAND_LINE flag.
982 : *
983 : * Variables get overridden by the newest values found in the list of
984 : * arguments.
985 : *
986 : * Note that the command line arguments are the only ones that should
987 : * include a command (opposed to an option that alters the behavior of
988 : * your commands.) However, the advgetopt system expects you to properly
989 : * define what can be used in a configuration file, in an environment
990 : * variable, or directly on the command line. It is not in charge of
991 : * that part in itself.
992 : *
993 : * \note
994 : * The code may find some errors in the tables passed to the advgetopt
995 : * environment (i.e. a duplicate definition.) When such errors are
996 : * detected, an exception is raised. Errors found on the command line
997 : * generate a log message. If you setup a callback, you can then decide
998 : * to either call exit(1) or raise your own exception.
999 : *
1000 : * \note
1001 : * The function does NOT check whether the list of arguments (argv) is
1002 : * terminated by nullptr. The argc parameter must be correct.
1003 : *
1004 : * \param[in] argc The number of arguments in argv.
1005 : * \param[in] argv The argument strings terminated by a nullptr.
1006 : * \param[in] source Where the value comes from.
1007 : * \param[in] only_environment_variable Accept command line arguments (false)
1008 : * or environment variable arguments (true).
1009 : */
1010 334 : void getopt::parse_arguments(
1011 : int argc
1012 : , char * argv[]
1013 : , option_source_t source
1014 : , bool only_environment_variable)
1015 : {
1016 794 : for(int i(1); i < argc; ++i)
1017 : {
1018 475 : if(argv[i][0] == '-')
1019 : {
1020 409 : if(argv[i][1] == '-')
1021 : {
1022 354 : if(argv[i][2] == '\0')
1023 : {
1024 : // end of options, skip the '--' and then anything else
1025 : // is taken as "filenames" (or whatever the tool expects)
1026 : //
1027 12 : if(f_default_option == nullptr)
1028 : {
1029 2 : cppthread::log << cppthread::log_level_t::error
1030 1 : << "no default options defined; thus \"--\" is not accepted by this program."
1031 2 : << cppthread::end;
1032 1 : break;
1033 : }
1034 :
1035 11 : if(only_environment_variable)
1036 : {
1037 6 : if(!f_default_option->has_flag(GETOPT_FLAG_ENVIRONMENT_VARIABLE))
1038 : {
1039 2 : cppthread::log << cppthread::log_level_t::error
1040 1 : << "option \"--\" is not supported in the environment variable."
1041 2 : << cppthread::end;
1042 1 : break;
1043 : }
1044 : }
1045 : else
1046 : {
1047 5 : if(!f_default_option->has_flag(GETOPT_FLAG_COMMAND_LINE))
1048 : {
1049 2 : cppthread::log << cppthread::log_level_t::error
1050 1 : << "option \"--\" is not supported on the command line."
1051 2 : << cppthread::end;
1052 1 : break;
1053 : }
1054 : }
1055 :
1056 : // in this case we do NOT test whether an argument uses
1057 : // a dash (-) we take them all as default options
1058 : //
1059 14 : while(i + 1 < argc)
1060 : {
1061 14 : ++i;
1062 14 : f_default_option->add_value(argv[i], source);
1063 : }
1064 : }
1065 : else
1066 : {
1067 : // a long option, check that it is defined in the
1068 : // programmer defined options
1069 : //
1070 680 : std::string option_name(argv[i] + 2);
1071 680 : std::string option_value;
1072 342 : std::string::size_type const pos(option_name.find('='));
1073 342 : if(pos != std::string::npos)
1074 : {
1075 21 : if(pos == 0)
1076 : {
1077 2 : cppthread::log << cppthread::log_level_t::error
1078 1 : << "name missing in \""
1079 1 : << argv[i]
1080 1 : << "\"."
1081 2 : << cppthread::end;
1082 1 : break;
1083 : }
1084 :
1085 20 : option_value = option_name.substr(pos + 1);
1086 20 : option_name.resize(pos);
1087 : }
1088 678 : option_info::pointer_t opt(get_option(option_name));
1089 340 : if(opt == nullptr)
1090 : {
1091 2 : cppthread::log << cppthread::log_level_t::error
1092 1 : << "option \"--"
1093 1 : << option_name
1094 1 : << "\" is not supported."
1095 2 : << cppthread::end;
1096 1 : break;
1097 : }
1098 339 : if(only_environment_variable)
1099 : {
1100 62 : if(!opt->has_flag(GETOPT_FLAG_ENVIRONMENT_VARIABLE))
1101 : {
1102 2 : cppthread::log << cppthread::log_level_t::error
1103 1 : << "option \"--"
1104 1 : << option_name
1105 1 : << "\" is not supported in the environment variable."
1106 2 : << cppthread::end;
1107 1 : break;
1108 : }
1109 : }
1110 : else
1111 : {
1112 277 : if(!opt->has_flag(GETOPT_FLAG_COMMAND_LINE))
1113 : {
1114 2 : cppthread::log << cppthread::log_level_t::error
1115 1 : << "option \"--"
1116 1 : << option_name
1117 1 : << "\" is not supported on the command line."
1118 2 : << cppthread::end;
1119 1 : break;
1120 : }
1121 : }
1122 337 : if(pos != std::string::npos)
1123 : {
1124 : // the user specified a value after an equal sign
1125 : //
1126 18 : add_option_from_string(opt, option_value, std::string(), source);
1127 : }
1128 : else
1129 : {
1130 319 : add_options(opt, i, argc, argv, source);
1131 : }
1132 : }
1133 : }
1134 : else
1135 : {
1136 55 : if(argv[i][1] == '\0')
1137 : {
1138 : // stdin/stdout (a '-' by itself)
1139 : //
1140 9 : if(f_default_option == nullptr)
1141 : {
1142 2 : cppthread::log << cppthread::log_level_t::error
1143 1 : << "no default options defined; thus \"-\" is not accepted by this program."
1144 2 : << cppthread::end;
1145 1 : break;
1146 : }
1147 8 : if(only_environment_variable)
1148 : {
1149 4 : if(!f_default_option->has_flag(GETOPT_FLAG_ENVIRONMENT_VARIABLE))
1150 : {
1151 2 : cppthread::log << cppthread::log_level_t::error
1152 1 : << "option \"-\" is not supported in the environment variable."
1153 2 : << cppthread::end;
1154 1 : break;
1155 : }
1156 : }
1157 : else
1158 : {
1159 4 : if(!f_default_option->has_flag(GETOPT_FLAG_COMMAND_LINE))
1160 : {
1161 2 : cppthread::log << cppthread::log_level_t::error
1162 1 : << "option \"-\" is not supported on the command line."
1163 2 : << cppthread::end;
1164 1 : break;
1165 : }
1166 : }
1167 :
1168 : // this is similar to a default option by itself
1169 : //
1170 6 : f_default_option->add_value(argv[i], source);
1171 : }
1172 : else
1173 : {
1174 : // short option(s)
1175 : //
1176 : // i gets incremented by add_options() so we have to
1177 : // keep a copy in `k`
1178 : //
1179 92 : std::string const short_args_string(argv[i] + 1);
1180 91 : for(libutf8::utf8_iterator short_args(short_args_string)
1181 91 : ; short_args != short_args_string.end()
1182 : ; ++short_args)
1183 : {
1184 93 : option_info::pointer_t opt(get_option(*short_args));
1185 48 : if(opt == nullptr)
1186 : {
1187 2 : cppthread::log << cppthread::log_level_t::error
1188 1 : << "option \"-"
1189 2 : << short_name_to_string(*short_args)
1190 1 : << "\" is not supported."
1191 3 : << cppthread::end;
1192 1 : break;
1193 : }
1194 47 : if(only_environment_variable)
1195 : {
1196 19 : if(!opt->has_flag(GETOPT_FLAG_ENVIRONMENT_VARIABLE))
1197 : {
1198 2 : cppthread::log << cppthread::log_level_t::error
1199 1 : << "option \"-"
1200 2 : << short_name_to_string(*short_args)
1201 1 : << "\" is not supported in the environment variable."
1202 3 : << cppthread::end;
1203 1 : break;
1204 : }
1205 : }
1206 : else
1207 : {
1208 28 : if(!opt->has_flag(GETOPT_FLAG_COMMAND_LINE))
1209 : {
1210 2 : cppthread::log << cppthread::log_level_t::error
1211 1 : << "option \"-"
1212 2 : << short_name_to_string(*short_args)
1213 1 : << "\" is not supported on the command line."
1214 3 : << cppthread::end;
1215 1 : break;
1216 : }
1217 : }
1218 45 : add_options(opt, i, argc, argv, source);
1219 : }
1220 : }
1221 : }
1222 : }
1223 : else
1224 : {
1225 : // direct entry (filename or whatever the tool expects as a default)
1226 : //
1227 66 : if(f_default_option == nullptr)
1228 : {
1229 4 : cppthread::log << cppthread::log_level_t::error
1230 2 : << "no default options defined; we do not know what to do of \""
1231 2 : << argv[i]
1232 2 : << "\"; standalone parameters are not accepted by this program."
1233 4 : << cppthread::end;
1234 2 : break;
1235 : }
1236 64 : if(only_environment_variable)
1237 : {
1238 27 : if(!f_default_option->has_flag(GETOPT_FLAG_ENVIRONMENT_VARIABLE))
1239 : {
1240 2 : cppthread::log << cppthread::log_level_t::error
1241 1 : << "default options are not supported in the environment variable."
1242 2 : << cppthread::end;
1243 1 : break;
1244 : }
1245 : }
1246 : else
1247 : {
1248 37 : if(!f_default_option->has_flag(GETOPT_FLAG_COMMAND_LINE))
1249 : {
1250 2 : cppthread::log << cppthread::log_level_t::error
1251 1 : << "default options are not supported on the command line."
1252 2 : << cppthread::end;
1253 1 : break;
1254 : }
1255 : }
1256 62 : f_default_option->add_value(argv[i], source);
1257 : }
1258 : }
1259 :
1260 333 : f_parsed = true;
1261 333 : }
1262 :
1263 :
1264 : /** \brief Return the alias if there is one.
1265 : *
1266 : * This function returns the input \p opt parameter unless it is an
1267 : * alias in which case the destination alias option is returned instead.
1268 : *
1269 : * \param[in] opt The option for which an alias is desired.
1270 : *
1271 : * \return \p opt unless it is an alias in which case
1272 : * opt->get_alias_destination() is returned.
1273 : *
1274 : * \sa option_info::get_alias()
1275 : */
1276 5338 : option_info::pointer_t getopt::get_alias_destination(option_info::pointer_t opt) const
1277 : {
1278 10676 : if(opt != nullptr
1279 5338 : && opt->has_flag(GETOPT_FLAG_ALIAS))
1280 : {
1281 95 : opt = opt->get_alias_destination();
1282 95 : if(opt == nullptr)
1283 : {
1284 1 : throw getopt_undefined("getopt::get_alias_destination(): alias is missing. Did you call link_aliases()?");
1285 : }
1286 : }
1287 :
1288 5337 : return opt;
1289 : }
1290 :
1291 :
1292 : /** \brief Retrieve the complete list of options.
1293 : *
1294 : * Applications that let their users enter dynamically options need to
1295 : * have access to the resulting list of options which may not otherwise
1296 : * be known.
1297 : *
1298 : * \return The map of options indexed by name.
1299 : *
1300 : * \sa parse_options_from_file()
1301 : */
1302 5 : option_info::map_by_name_t const & getopt::get_options() const
1303 : {
1304 5 : return f_options_by_name;
1305 : }
1306 :
1307 :
1308 : /** \brief Retrieve an option by name.
1309 : *
1310 : * This function retrieves an option by name. The function handles the
1311 : * special case of the default option. This means "--" can always be
1312 : * used to access the default option, whatever the name given to that
1313 : * option in the declaration of your options.
1314 : *
1315 : * Of course, if no default is defined, then "--" returns a nullptr.
1316 : *
1317 : * By default the function returns the final option. That is, if the
1318 : * named option is an alias, the destination option is returned, not
1319 : * the alias. This way the rest of the code is much simpler. You may
1320 : * get the exact option, even if it is aliased, by setting the
1321 : * \p exact_option parameter to true. It is really rare that you
1322 : * would need to do so.
1323 : *
1324 : * \note
1325 : * The \p name parameter could be an empty string to represent the default
1326 : * value (I think that's what that was for, now you use "--"). I've added
1327 : * the throw in this function to catch that invalid use, which either means
1328 : * you tried to check something with an invalid name or are expected to use
1329 : * the "--".
1330 : *
1331 : * \param[in] name The name of the option to retrieve.
1332 : * \param[in] exact_option Return the exact option, not its alias.
1333 : *
1334 : * \return The pointer to the named option or nullptr if not found.
1335 : */
1336 6773 : option_info::pointer_t getopt::get_option(std::string const & name, bool exact_option) const
1337 : {
1338 13546 : option_info::pointer_t opt;
1339 :
1340 6773 : if(name.empty())
1341 : {
1342 : // see \note section in doxy above about this
1343 : //
1344 4 : throw getopt_invalid_parameter("get_option() `name` argument cannot be empty.");
1345 : }
1346 :
1347 13538 : std::string const n(boost::replace_all_copy(name, "_", "-"));
1348 :
1349 : // we need this special case when looking for the default option
1350 : // because the name may not be "--" in the option table
1351 : // (i.e. you could call your default option "filenames" for example.)
1352 : //
1353 13538 : if(n.length() == 2
1354 504 : && n[0] == '-'
1355 7268 : && n[1] == '-')
1356 : {
1357 499 : opt = f_default_option;
1358 : }
1359 : else
1360 : {
1361 6270 : short_name_t short_name(string_to_short_name(n));
1362 6270 : if(short_name != NO_SHORT_NAME)
1363 : {
1364 6 : auto it(f_options_by_short_name.find(short_name));
1365 6 : if(it != f_options_by_short_name.end())
1366 : {
1367 2 : opt = it->second;
1368 : }
1369 : }
1370 : else
1371 : {
1372 6264 : auto it(f_options_by_name.find(n));
1373 6264 : if(it != f_options_by_name.end())
1374 : {
1375 3714 : opt = it->second;
1376 : }
1377 : }
1378 : }
1379 :
1380 : return exact_option
1381 : ? opt
1382 13538 : : get_alias_destination(opt);
1383 : }
1384 :
1385 :
1386 : /** \brief Get an option using its short name.
1387 : *
1388 : * This function searches for an option given its short name.
1389 : *
1390 : * By default the function returns the final option. That is, if the
1391 : * named option is an alias, the destination option is returned, not
1392 : * the alias. This way the rest of the code is much simpler. You may
1393 : * get the exact option, even if it is aliased, by setting the
1394 : * \p exact_option parameter to true. It is really rare that you
1395 : * would need to do so, though.
1396 : *
1397 : * \param[in] short_name The short name of the option to look for.
1398 : * \param[in] exact_option Return the exact option, not its alias.
1399 : *
1400 : * \return The pointer to the option or nullptr if not found.
1401 : */
1402 2136 : option_info::pointer_t getopt::get_option(short_name_t short_name, bool exact_option) const
1403 : {
1404 2136 : auto it(f_options_by_short_name.find(short_name));
1405 2136 : if(it == f_options_by_short_name.end())
1406 : {
1407 1857 : return option_info::pointer_t();
1408 : }
1409 :
1410 : return exact_option
1411 8 : ? it->second
1412 287 : : get_alias_destination(it->second);
1413 : }
1414 :
1415 :
1416 : /** \brief Read parameters of the current option.
1417 : *
1418 : * This function saves the option in the list of options found in this list
1419 : * of arguments. If the option is expected to have parameters, then those
1420 : * are taken from the argv array before the function saves the option in
1421 : * the object list. The index, \p i, is increased accordingly.
1422 : *
1423 : * \warning
1424 : * This function cannot be called properly with the '-' option in case it
1425 : * is viewed as a default parameter. This is because the algorithm expects
1426 : * the index (\p i) to be pointing to the command line option and not the
1427 : * argument to that command.
1428 : *
1429 : * \param[in] opt The concerned option
1430 : * \param[in] i The current position, starting with the option position
1431 : * \param[in] argc The number of arguments in the argv array.
1432 : * \param[in] argv The list of argument strings.
1433 : * \param[in] source Where the value comes from.
1434 : */
1435 364 : void getopt::add_options(
1436 : option_info::pointer_t opt
1437 : , int & i
1438 : , int argc
1439 : , char ** argv
1440 : , option_source_t source)
1441 : {
1442 364 : if(opt->has_flag(GETOPT_FLAG_FLAG))
1443 : {
1444 154 : opt->add_value(opt->get_default(), source);
1445 : }
1446 : else
1447 : {
1448 210 : if(i + 1 < argc && !is_arg(argv[i + 1]))
1449 : {
1450 187 : if(opt->has_flag(GETOPT_FLAG_MULTIPLE))
1451 : {
1452 43 : do
1453 : {
1454 78 : ++i;
1455 78 : opt->add_value(argv[i], source);
1456 : }
1457 78 : while(i + 1 < argc && !is_arg(argv[i + 1]));
1458 : }
1459 : else
1460 : {
1461 152 : ++i;
1462 152 : opt->add_value(argv[i], source);
1463 : }
1464 : }
1465 : else
1466 : {
1467 23 : if(opt->has_flag(GETOPT_FLAG_REQUIRED))
1468 : {
1469 6 : cppthread::log << cppthread::log_level_t::error
1470 3 : << "option --"
1471 3 : << opt->get_name()
1472 3 : << " expects an argument."
1473 6 : << cppthread::end;
1474 : }
1475 : else
1476 : {
1477 : // We need to set something because the value is being
1478 : // set although no argument was specified (but that's
1479 : // legal by this argument's definition)
1480 : //
1481 20 : opt->add_value(std::string(), source);
1482 : }
1483 : }
1484 : }
1485 364 : }
1486 :
1487 :
1488 : /** \brief Add an option with a value string.
1489 : *
1490 : * This function accepts a string as the value. If the option accepts
1491 : * multiple values, then the function makes use of the set_multiple_value()
1492 : * function of the option_info class. This will break the option up in
1493 : * multiple value if possible.
1494 : *
1495 : * \param[in] opt The option receiving a value.
1496 : * \param[in] value The value to assign this option.
1497 : * \param[in] filename The name of a configuration file if the option was
1498 : * read from such.
1499 : * \param[in] source Where the value comes from.
1500 : */
1501 118 : void getopt::add_option_from_string(
1502 : option_info::pointer_t opt
1503 : , std::string const & value
1504 : , std::string const & filename
1505 : , option_source_t source)
1506 : {
1507 : // is the value defined?
1508 : //
1509 118 : if(!value.empty())
1510 : {
1511 114 : if(!opt->has_flag(GETOPT_FLAG_FLAG))
1512 : {
1513 : // does the option support multiple entries?
1514 : //
1515 110 : if(opt->has_flag(GETOPT_FLAG_MULTIPLE))
1516 : {
1517 23 : opt->set_multiple_values(value, source);
1518 : }
1519 : else
1520 : {
1521 87 : opt->set_value(0, value, source);
1522 : }
1523 110 : return;
1524 : }
1525 :
1526 : // for flags, allow "true" or "false" that way we can reset those
1527 : // flags and especially, it's possible to use them in configuration
1528 : // files that way
1529 : //
1530 4 : if(is_false(value))
1531 : {
1532 2 : opt->reset();
1533 2 : return;
1534 : }
1535 :
1536 2 : if(is_true(value))
1537 : {
1538 : // for this, pass an empty string to the next layer
1539 : //
1540 1 : opt->set_value(0, std::string(), source);
1541 1 : return;
1542 : }
1543 :
1544 2 : cppthread::log << cppthread::log_level_t::error
1545 1 : << "option "
1546 1 : << (filename.empty()
1547 3 : ? "--" + opt->get_name()
1548 3 : : "\"" + boost::replace_all_copy(opt->get_name(), "-", "_") + "\"")
1549 1 : << " cannot be given value \""
1550 1 : << value
1551 1 : << "\""
1552 1 : << (filename.empty()
1553 3 : ? std::string()
1554 : : " in configuration file \""
1555 2 : + filename
1556 1 : + "\"")
1557 1 : << ". It only accepts \"true\" or \"false\"."
1558 4 : << cppthread::end;
1559 1 : return;
1560 : }
1561 :
1562 : // does the option require a value when used?
1563 : //
1564 4 : if(opt->has_flag(GETOPT_FLAG_REQUIRED))
1565 : {
1566 2 : cppthread::log << cppthread::log_level_t::error
1567 1 : << "option "
1568 1 : << (filename.empty()
1569 2 : ? "--" + opt->get_name()
1570 2 : : "\"" + boost::replace_all_copy(opt->get_name(), "-", "_") + "\"")
1571 1 : << " must be given a value"
1572 1 : << (filename.empty()
1573 2 : ? std::string()
1574 : : " in configuration file \""
1575 1 : + filename
1576 1 : + "\"")
1577 1 : << "."
1578 4 : << cppthread::end;
1579 1 : return;
1580 : }
1581 :
1582 : // accept an empty value otherwise
1583 : //
1584 3 : opt->set_value(0, value, source);
1585 : }
1586 :
1587 :
1588 : /** \brief Retrieve a pointer to the variables defined in the getopt object.
1589 : *
1590 : * This function retrieves the variables defined in the getopt object.
1591 : * This is useful if you want to support those variables within
1592 : * configuration files that you read later on.
1593 : *
1594 : * \note
1595 : * This pointer is never a nullptr.
1596 : *
1597 : * \return A pointer to the getopt variables.
1598 : */
1599 1 : variables::pointer_t getopt::get_variables() const
1600 : {
1601 1 : return f_variables;
1602 : }
1603 :
1604 :
1605 :
1606 6 : } // namespace advgetopt
1607 : // vim: ts=4 sw=4 et
|