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