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