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 data access implementation.
22 : *
23 : * The advgetopt class has many function used to access the data in the
24 : * class. These functions are gathered here.
25 : */
26 :
27 : // self
28 : //
29 : #include "advgetopt/advgetopt.h"
30 :
31 : #include "advgetopt/conf_file.h"
32 : #include "advgetopt/exception.h"
33 : #include "advgetopt/validator_double.h"
34 : #include "advgetopt/validator_integer.h"
35 : #include "advgetopt/version.h"
36 :
37 :
38 : // cppthread lib
39 : //
40 : #include <cppthread/log.h>
41 :
42 :
43 : // C lib
44 : //
45 : #include <string.h>
46 :
47 :
48 : // last include
49 : //
50 : #include <snapdev/poison.h>
51 :
52 :
53 :
54 :
55 : namespace advgetopt
56 : {
57 :
58 :
59 :
60 :
61 :
62 : /** \brief Check whether a parameter is defined.
63 : *
64 : * This function returns true if the specified parameter is found as part of
65 : * the command line options.
66 : *
67 : * You must specify the long name of the option. So a `--verbose` option can
68 : * be checked with:
69 : *
70 : * \code
71 : * if(is_defined("verbose")) ...
72 : * \endcode
73 : *
74 : * For options that come with a short name, you may also specify the short
75 : * name. This is done with a string in this case. It can be a UTF-8
76 : * character. The short name is used if the string represents exactly one
77 : * Unicode character. So the following is equivalent to the previous
78 : * example, assuming your verbose definition has `v` as the short name:
79 : *
80 : * \code
81 : * if(is_defined("v")) ...
82 : * \endcode
83 : *
84 : * \note
85 : * This function returns true when the option was found on the command line,
86 : * the environment variable, or a configuration file. It returns false if
87 : * the option is defined, but was not specified anywhere by the client using
88 : * your program. Also, specifying the option in one of those three locations
89 : * when not allowed at that location will not result in this flag being raised.
90 : *
91 : * \param[in] name The long name or short name of the option to check.
92 : *
93 : * \return true if the option was defined in a configuration file, the
94 : * environment variable, or the command line.
95 : */
96 1368 : bool getopt::is_defined(std::string const & name) const
97 : {
98 1368 : is_parsed();
99 :
100 2728 : option_info::pointer_t opt(get_option(name));
101 1364 : if(opt != nullptr)
102 : {
103 1038 : return opt->is_defined();
104 : }
105 :
106 326 : return false;
107 : }
108 :
109 :
110 : /** \brief Retrieve the number of arguments.
111 : *
112 : * This function returns the number of arguments that were specified after
113 : * the named option.
114 : *
115 : * The function returns zero if the argument was never specified on the
116 : * command line. If the option accepts exactly one parameter (i.e. not
117 : * marked as a multiple arguments option: GETOPT_FLAG_MULTIPLE) then
118 : * the function returns either zero (not specified) or one (specified
119 : * at least once.)
120 : *
121 : * \param[in] name The name of the option to check.
122 : *
123 : * \return The number of arguments specified on the command line or zero.
124 : */
125 615 : size_t getopt::size(std::string const & name) const
126 : {
127 615 : is_parsed();
128 :
129 1224 : option_info::pointer_t opt(get_option(name));
130 612 : if(opt != nullptr)
131 : {
132 400 : return opt->size();
133 : }
134 212 : return 0;
135 : }
136 :
137 :
138 : /** \brief Check whether an option has a default value.
139 : *
140 : * Some parameters may be given a default. This function is used to
141 : * detect whether such a default value is defined.
142 : *
143 : * \note
144 : * This function is particularly useful in the event the default value
145 : * may be an empty string.
146 : *
147 : * \exception getopt_exception_undefined
148 : * The getopt_exception_undefined exception is raised if this function is
149 : * called with an empty \p name.
150 : *
151 : * \param[in] name The name of the parameter of which you want to know
152 : * whether it has a default value or not.
153 : *
154 : * \return true if the default value was defined (even if an empty string.)
155 : */
156 79 : bool getopt::has_default(std::string const & name) const
157 : {
158 156 : option_info::pointer_t opt(get_option(name));
159 77 : if(opt != nullptr)
160 : {
161 72 : return opt->has_default();
162 : }
163 :
164 5 : return false;
165 : }
166 :
167 :
168 : /** \brief Get the default value for this option.
169 : *
170 : * When an option is not defined, you may use this function to retrieve its
171 : * default instead. This is actually done automatically when you call the
172 : * get_string() or get_long() functions.
173 : *
174 : * An option without a default has this function returning nullptr.
175 : *
176 : * \note
177 : * Whether an option has a default value should be checked with the
178 : * has_default() function which returns true when the default value
179 : * was defined. An option with an empty string as the default is
180 : * a valid case which cannot be detected otherwise.
181 : *
182 : * \exception getopt_exception_undefined
183 : * The getopt_exception_undefined exception is raised if this function is
184 : * called with an empty \p name.
185 : *
186 : * \param[in] name The name of the parameter of which you want to retrieve
187 : * the default value.
188 : *
189 : * \return The default value or an empty string if no value is defined.
190 : */
191 553 : std::string getopt::get_default(std::string const & name) const
192 : {
193 1104 : option_info::pointer_t opt(get_option(name));
194 551 : if(opt != nullptr)
195 : {
196 318 : return opt->get_default();
197 : }
198 :
199 233 : return std::string();
200 : }
201 :
202 :
203 : /** \brief This function retrieves an argument as a long value.
204 : *
205 : * This function reads the specified argument from the named option and
206 : * transforms it to a long value. It then checks the result against the
207 : * specified minimum and maximum range.
208 : *
209 : * The function name represents an argument that needs to be defined. You
210 : * can test whether it was defined on the command line with the is_defined()
211 : * function. The index must be between 0 and 'size() - 1' inclusive. If
212 : * the item was not defined, then size() returns zero and you cannot call
213 : * this function.
214 : *
215 : * The function does not check the validity of the minimum and maximum
216 : * parameters. If \p min \> \p max is true then the function will always
217 : * fail with a call to usage() as no value can be defined between \p min
218 : * and \p max in that case. The minimum and maximum values are inclusive,
219 : * so a range of 1 to 9 is defined with exactly 1 and 9 in min and max.
220 : * For example, the z library compression could be retrieved with:
221 : *
222 : * \code
223 : * int level(6); // default to 6
224 : * if(opt.is_defined("zlevel"))
225 : * {
226 : * zlevel = opt.get_long("zlevel", 0, 1, 9);
227 : * }
228 : * \endcode
229 : *
230 : * Note that the function can be used to read unsigned numbers, however
231 : * at this point getopt does not really support negative numbers (i.e. because
232 : * -\<number> is viewed as an option.)
233 : *
234 : * \exception getopt_exception_undefined
235 : * The getopt_exception_undefined exception is raised if \p name was not
236 : * found on the command line and it has no default, or if \p idx is
237 : * out of bounds.
238 : *
239 : * \param[in] name The name of the option to retrieve.
240 : * \param[in] idx The index of the argument to retrieve.
241 : * \param[in] min The minimum value that will be returned (inclusive).
242 : * \param[in] max The maximum value that will be returned (inclusive).
243 : *
244 : * \return The argument as a long.
245 : */
246 130 : long getopt::get_long(std::string const & name, int idx, long min, long max) const
247 : {
248 130 : is_parsed();
249 :
250 260 : option_info::pointer_t opt(get_option(name));
251 130 : if(opt == nullptr)
252 : {
253 : throw getopt_logic_error(
254 : "there is no --"
255 6 : + name
256 9 : + " option defined.");
257 : }
258 :
259 127 : long result(0.0);
260 127 : if(!opt->is_defined())
261 : {
262 96 : std::string const d(opt->get_default());
263 48 : if(d.empty())
264 : {
265 : throw getopt_logic_error(
266 : "the --"
267 12 : + name
268 18 : + " option was not defined on the command line and it has no or an empty default.");
269 : }
270 42 : if(!validator_integer::convert_string(d, result))
271 : {
272 : // here we throw because this default value is defined in the
273 : // options of the tool and not by the user
274 : //
275 : throw getopt_logic_error(
276 : "invalid default number \""
277 6 : + d
278 9 : + "\" for option --"
279 9 : + name);
280 : }
281 : }
282 : else
283 : {
284 79 : result = opt->get_long(idx);
285 : }
286 :
287 : // TODO: replace with validators
288 : //
289 118 : if(result < min || result > max)
290 : {
291 4 : cppthread::log << cppthread::log_level_t::error
292 2 : << result
293 2 : << " is out of bounds ("
294 2 : << min
295 2 : << ".."
296 2 : << max
297 2 : << " inclusive) in parameter --"
298 2 : << name
299 2 : << "."
300 4 : << cppthread::end;
301 2 : result = -1;
302 : }
303 :
304 236 : return result;
305 : }
306 :
307 :
308 : /** \brief This function retrieves an argument as a double value.
309 : *
310 : * This function reads the specified argument from the named option and
311 : * transforms it to a double value. It then checks the result against the
312 : * specified minimum and maximum range.
313 : *
314 : * The function name represents an argument that needs to be defined. You
315 : * can test whether it was defined on the command line with the is_defined()
316 : * function. The index must be between 0 and 'size() - 1' inclusive. If
317 : * the item was not defined, then size() returns zero and you cannot call
318 : * this function.
319 : *
320 : * The function does not check the validity of the minimum and maximum
321 : * parameters. If \p min \> \p max is true then the function will always
322 : * fail with a call to usage() as no value can be defined between \p min
323 : * and \p max in that case. The minimum and maximum values are inclusive,
324 : * so a range of 1 to 9 is defined with exactly 1 and 9 in min and max.
325 : * For example, the z library compression could be retrieved with:
326 : *
327 : * \code
328 : * int level(6); // default to 6
329 : * if(opt.is_defined("zlevel"))
330 : * {
331 : * zlevel = opt.get_double("zlevel", 0, 1, 9);
332 : * }
333 : * \endcode
334 : *
335 : * Note that the function can be used to read unsigned numbers, however
336 : * at this point getopt does not really support negative numbers (i.e. because
337 : * -\<number> is viewed as an option.)
338 : *
339 : * \todo
340 : * Fix example with a parameter which makes sense (i.e. accepts doubles).
341 : *
342 : * \exception getopt_exception_undefined
343 : * The getopt_exception_undefined exception is raised if \p name was not
344 : * found on the command line and it has no default, or if \p idx is
345 : * out of bounds.
346 : *
347 : * \param[in] name The name of the option to retrieve.
348 : * \param[in] idx The index of the argument to retrieve.
349 : * \param[in] min The minimum value that will be returned (inclusive).
350 : * \param[in] max The maximum value that will be returned (inclusive).
351 : *
352 : * \return The argument as a long.
353 : */
354 0 : double getopt::get_double(std::string const & name, int idx, double min, double max) const
355 : {
356 0 : is_parsed();
357 :
358 0 : option_info::pointer_t opt(get_option(name));
359 0 : if(opt == nullptr)
360 : {
361 : throw getopt_logic_error(
362 : "there is no --"
363 0 : + name
364 0 : + " option defined.");
365 : }
366 :
367 0 : double result(0);
368 0 : if(!opt->is_defined())
369 : {
370 0 : std::string const d(opt->get_default());
371 0 : if(d.empty())
372 : {
373 : throw getopt_logic_error(
374 : "the --"
375 0 : + name
376 0 : + " option was not defined on the command line and it has no or an empty default.");
377 : }
378 0 : if(!validator_double::convert_string(d, result))
379 : {
380 : // here we throw because this default value is defined in the
381 : // options of the tool and not by the user
382 : //
383 : throw getopt_logic_error(
384 : "invalid default number \""
385 0 : + d
386 0 : + "\" for option --"
387 0 : + name);
388 : }
389 : }
390 : else
391 : {
392 0 : result = opt->get_double(idx);
393 : }
394 :
395 : // TODO: replace with validators
396 : //
397 0 : if(result < min || result > max)
398 : {
399 0 : cppthread::log << cppthread::log_level_t::error
400 0 : << result
401 0 : << " is out of bounds ("
402 0 : << min
403 0 : << ".."
404 0 : << max
405 0 : << " inclusive) in parameter --"
406 0 : << name
407 0 : << "."
408 0 : << cppthread::end;
409 0 : result = -1.0;
410 : }
411 :
412 0 : return result;
413 : }
414 :
415 :
416 : /** \brief Get the content of an option as a string.
417 : *
418 : * Get the content of the named parameter as a string. Command line options
419 : * that accept multiple arguments accept the \p idx parameter to
420 : * specify which item you are interested in.
421 : *
422 : * Note that the option must have been specified on the command line or have
423 : * a default value. For options that do not have a default value, you want
424 : * to call the is_defined() function first.
425 : *
426 : * \note
427 : * If the function returns the default value, it gets returned as is. i.e.
428 : * it won't be passed through the variable processing function.
429 : *
430 : * \exception getopt_exception_undefined
431 : * The getopt_exception_undefined exception is raised if \p name was not
432 : * found on the command line and it has no default, or if \p idx is
433 : * out of bounds.
434 : *
435 : * \param[in] name The name of the option to read.
436 : * \param[in] idx The zero based index of a multi-argument command line option.
437 : * \param[in] raw Whether to return the value without replacing the variables.
438 : *
439 : * \return The option argument as a string.
440 : */
441 562 : std::string getopt::get_string(
442 : std::string const & name
443 : , int idx
444 : , bool raw) const
445 : {
446 562 : is_parsed();
447 :
448 1124 : option_info::pointer_t opt(get_option(name));
449 562 : if(opt == nullptr)
450 : {
451 : throw getopt_logic_error(
452 : "there is no --"
453 6 : + name
454 9 : + " option defined.");
455 : }
456 :
457 559 : if(!opt->is_defined())
458 : {
459 45 : if(opt->has_default())
460 : {
461 40 : return opt->get_default();
462 : }
463 : throw getopt_logic_error(
464 : "the --"
465 10 : + name
466 15 : + " option was not defined on the command line and it has no default.");
467 : }
468 :
469 : // it was defined, but if REQUIRED is not set and the value is empty
470 : // then we want to return the default if it has such defined
471 : //
472 1027 : std::string const value(opt->get_value(idx, raw));
473 1026 : if(value.empty()
474 67 : && opt->has_default()
475 521 : && !opt->has_flag(GETOPT_FLAG_REQUIRED))
476 : {
477 8 : return opt->get_default();
478 : }
479 :
480 505 : return value;
481 : }
482 :
483 :
484 : /** \brief Retrieve the value of an argument.
485 : *
486 : * This operator returns the value of an argument just like the get_string()
487 : * does when the argument is defined. When the argument is not defined and it
488 : * has no default, it returns an empty string instead of throwing.
489 : *
490 : * The function is only capable of returning the very first value. If this
491 : * argument has the GETOPT_FLAG_MULTIPLE flag set, you probably want to use
492 : * the get_string() instead.
493 : *
494 : * \param[in] name The name of the option to retrieve.
495 : *
496 : * \return The value of that option or an empty string if not defined.
497 : */
498 193 : std::string getopt::operator [] (std::string const & name) const
499 : {
500 193 : is_parsed();
501 :
502 193 : if(name.empty())
503 : {
504 2 : throw getopt_logic_error("argument name cannot be empty.");
505 : }
506 :
507 382 : option_info::pointer_t opt(get_option(name));
508 191 : if(opt == nullptr)
509 : {
510 1 : return std::string();
511 : }
512 :
513 190 : if(!opt->is_defined())
514 : {
515 6 : if(opt->has_default())
516 : {
517 5 : return opt->get_default();
518 : }
519 1 : return std::string();
520 : }
521 :
522 184 : return opt->get_value(0);
523 : }
524 :
525 :
526 : /** \brief Access a parameter in read and write mode.
527 : *
528 : * This function allows you to access an argument which may or may not
529 : * yet exist.
530 : *
531 : * The return value is a reference to that parameter. You can read
532 : * and write to the reference.
533 : *
534 : * A non-existant argument is created only if necessary. That is,
535 : * only if you actually use an assignment operator as follow:
536 : *
537 : * \code
538 : * // straight assignment:
539 : * opt["my-var"] = "123";
540 : *
541 : * // or concatenation:
542 : * opt["my-var"] += "append";
543 : * \endcode
544 : *
545 : * In read mode and unless you defined a default, a non-existant argument
546 : * is viewed as an empty string or 0 if retrieved as a long:
547 : *
548 : * \code
549 : * // if non-existant you get an empty string:
550 : * std::string value = opt["non-existant"];
551 : *
552 : * // if non-existant you get zero:
553 : * long value = opt["non-existant"].get_long();
554 : * \endcode
555 : *
556 : * The get_long() function may generate an error if the parameter is not
557 : * a valid integer. Also when a default is defined, it tries to convert
558 : * the default value to a number and if that fails an error is generated.
559 : *
560 : * \note
561 : * This operator only allows you to access the very first value of
562 : * this option. If the option is marked with GETOPT_FLAG_MULTIPLE,
563 : * you may want to use the get_option() function and then handle
564 : * the option multiple values manually with the option_info::get_value()
565 : * and option_info::set_value().
566 : *
567 : * \warning
568 : * If the option is an alias and the destination is not defined you
569 : * can still get an exception raised.
570 : *
571 : * \param[in] name The name of the option to access.
572 : *
573 : * \return A reference to this option with support for many std::string like
574 : * operators.
575 : */
576 169 : option_info_ref getopt::operator [] (std::string const & name)
577 : {
578 169 : is_parsed();
579 :
580 169 : if(name.empty())
581 : {
582 2 : throw getopt_logic_error("argument name cannot be empty.");
583 : }
584 :
585 334 : option_info::pointer_t opt(get_option(name));
586 167 : if(opt == nullptr)
587 : {
588 54 : if(name.length() == 1)
589 : {
590 2 : throw getopt_logic_error("argument name cannot be one letter if it does not exist in operator [].");
591 : }
592 :
593 : // The option doesn't exist yet, create it
594 : //
595 52 : opt = std::make_shared<option_info>(name);
596 52 : opt->set_variables(f_variables);
597 52 : opt->add_flag(GETOPT_FLAG_DYNAMIC_CONFIGURATION);
598 52 : f_options_by_name[name] = opt;
599 : }
600 :
601 330 : return option_info_ref(opt);
602 : }
603 :
604 :
605 : /** \brief Generate a string describing whether we're using the sanitizer.
606 : *
607 : * This function determines whether this library was compiled with the
608 : * sanitizer extension. If so, then it will return detail about which
609 : * feature was compiled in.
610 : *
611 : * If no sanitizer options were compiled in, then it returns a
612 : * message saying so.
613 : *
614 : * \return A string with details about the sanitizer.
615 : */
616 2 : std::string getopt::sanitizer_details()
617 : {
618 2 : std::string result;
619 : #if defined(__SANITIZE_ADDRESS__) || defined(__SANITIZE_THREAD__)
620 : #if defined(__SANITIZE_ADDRESS__)
621 2 : result += "The address sanitizer is compiled in.\n";
622 : #endif
623 : #if defined(__SANITIZE_THREAD__)
624 : result += "The thread sanitizer is compiled in.\n";
625 : #endif
626 : #else
627 : result += "The address and thread sanitizers are not compiled in.\n";
628 : #endif
629 2 : return result;
630 : }
631 :
632 :
633 : /** \brief Process the system options.
634 : *
635 : * If you have the GETOPT_ENVIRONMENT_FLAG_SYSTEM_PARAMETERS flag turned on,
636 : * then several options are automatically added to your list of supported
637 : * options, such as `--version`.
638 : *
639 : * This function processes these options if any were used by the client.
640 : *
641 : * If the function finds one or more system flags as being defined, it
642 : * returns a non-zero set of SYSTEM_OPTION_... flags. This can be useful
643 : * to decide whether to continue processing or not.
644 : *
645 : * We define a set of flags that can help you decide whether to continue
646 : * or exit. In most cases, we propose that you exit your program if any
647 : * one of the options was a command. This is done like so:
648 : *
649 : * \code
650 : * advgetopt::flag_t const r(process_system_options(stdout));
651 : * if((r & SYSTEM_OPTION_COMMANDS_MASK) != 0)
652 : * {
653 : * exit(1);
654 : * }
655 : * \endcode
656 : *
657 : * You may still want to continue, though, if other flags where set,
658 : * even if some commands were used. For example, some tools will print
659 : * their version and move forward with there work (i.e. compilers often do
660 : * that to help with logging all the information about a build process,
661 : * including the version of the compiler.)
662 : *
663 : * \param[in] out The stream where output is sent if required.
664 : *
665 : * \return non-zero set of flags if any of the system parameters were processed.
666 : */
667 42 : flag_t getopt::process_system_options(std::basic_ostream<char> & out)
668 : {
669 42 : flag_t result(SYSTEM_OPTION_NONE);
670 :
671 : // --version
672 42 : if(is_defined("version"))
673 : {
674 4 : if(f_options_environment.f_version == nullptr)
675 : {
676 1 : out << "warning: no version found." << std::endl;
677 : }
678 : else
679 : {
680 3 : out << f_options_environment.f_version << std::endl;
681 : }
682 4 : result |= SYSTEM_OPTION_VERSION;
683 : }
684 :
685 : // --has-sanitizer
686 42 : if(is_defined("has-sanitizer"))
687 : {
688 1 : out << sanitizer_details() << std::flush;
689 1 : result |= SYSTEM_OPTION_HELP;
690 : }
691 :
692 : // --compiler-version
693 42 : if(is_defined("compiler-version"))
694 : {
695 1 : out << LIBADVGETOPT_COMPILER_VERSION << std::endl;
696 1 : result |= SYSTEM_OPTION_HELP;
697 : }
698 :
699 : // --help
700 42 : if(is_defined("help"))
701 : {
702 1 : out << usage() << std::endl;
703 1 : result |= SYSTEM_OPTION_HELP;
704 : }
705 :
706 : // --long-help
707 42 : if(is_defined("long-help"))
708 : {
709 1 : out << usage(GETOPT_FLAG_SHOW_ALL) << std::endl;
710 1 : result |= SYSTEM_OPTION_HELP;
711 : }
712 :
713 : // --<group-name>-help
714 : //
715 42 : if(f_options_environment.f_groups != nullptr)
716 : {
717 6 : for(group_description const * grp = f_options_environment.f_groups
718 6 : ; grp->f_group != GETOPT_FLAG_GROUP_NONE
719 : ; ++grp)
720 : {
721 : // the name is not mandatory, without it you do not get the command
722 : // line option but still get the group description
723 : //
724 4 : if(grp->f_name != nullptr
725 4 : && *grp->f_name != '\0')
726 : {
727 8 : std::string const name(grp->f_name);
728 8 : std::string const option_name(name + "-help");
729 4 : if(is_defined(option_name))
730 : {
731 2 : out << usage(grp->f_group) << std::endl;
732 2 : result |= SYSTEM_OPTION_HELP;
733 : }
734 : }
735 : }
736 : }
737 :
738 : // --copyright
739 42 : if(is_defined("copyright"))
740 : {
741 3 : if(f_options_environment.f_copyright == nullptr)
742 : {
743 1 : out << "warning: no copyright notice found." << std::endl;
744 : }
745 : else
746 : {
747 2 : out << f_options_environment.f_copyright << std::endl;
748 : }
749 3 : result |= SYSTEM_OPTION_COPYRIGHT;
750 : }
751 :
752 : // --license
753 42 : if(is_defined("license"))
754 : {
755 4 : if(f_options_environment.f_license == nullptr)
756 : {
757 1 : out << "warning: no license found." << std::endl;
758 : }
759 : else
760 : {
761 3 : out << f_options_environment.f_license << std::endl;
762 : }
763 4 : result |= SYSTEM_OPTION_LICENSE;
764 : }
765 :
766 : // --build-date
767 42 : if(is_defined("build-date"))
768 : {
769 : out << "Built on "
770 2 : << (f_options_environment.f_build_date == nullptr
771 : ? "<no-build-date>"
772 : : f_options_environment.f_build_date)
773 : << " at "
774 2 : << (f_options_environment.f_build_time == nullptr
775 : ? "<no-build-time>"
776 6 : : f_options_environment.f_build_time)
777 2 : << std::endl;
778 2 : result |= SYSTEM_OPTION_BUILD_DATE;
779 : }
780 :
781 : // --environment-variable-name
782 42 : if(is_defined("environment-variable-name"))
783 : {
784 3 : if(f_options_environment.f_environment_variable_name == nullptr
785 2 : || *f_options_environment.f_environment_variable_name == '\0')
786 : {
787 : out << f_options_environment.f_project_name
788 2 : << " does not support an environment variable."
789 2 : << std::endl;
790 : }
791 : else
792 : {
793 1 : out << f_options_environment.f_environment_variable_name << std::endl;
794 : }
795 3 : result |= SYSTEM_OPTION_ENVIRONMENT_VARIABLE_NAME;
796 : }
797 :
798 : // --configuration-filenames
799 42 : if(is_defined("configuration-filenames"))
800 : {
801 6 : string_list_t list(get_configuration_filenames(false, false));
802 3 : if(list.empty())
803 : {
804 : out << f_options_environment.f_project_name
805 1 : << " does not support configuration files."
806 1 : << std::endl;
807 : }
808 : else
809 : {
810 2 : out << "Configuration filenames:" << std::endl;
811 26 : for(auto n : list)
812 : {
813 24 : out << " . " << n << std::endl;
814 : }
815 : }
816 3 : result |= SYSTEM_OPTION_CONFIGURATION_FILENAMES;
817 : }
818 :
819 : // --path-to-option-definitions
820 42 : if(is_defined("path-to-option-definitions"))
821 : {
822 2 : if(f_options_environment.f_options_files_directory == nullptr
823 1 : || *f_options_environment.f_options_files_directory == '\0')
824 : {
825 1 : out << "/usr/share/advgetopt/options/" << std::endl;
826 : }
827 : else
828 : {
829 1 : out << f_options_environment.f_options_files_directory;
830 1 : if(f_options_environment.f_options_files_directory[strlen(f_options_environment.f_options_files_directory) - 1] != '/')
831 : {
832 1 : out << '/';
833 : }
834 1 : out << std::endl;
835 : }
836 2 : result |= SYSTEM_OPTION_PATH_TO_OPTION_DEFINITIONS;
837 : }
838 :
839 : // --config-dir
840 42 : if(is_defined("config-dir"))
841 : {
842 : // these are automatically used in the get_configuration_filenames()
843 : // function, there is nothing for us to do here
844 : //
845 3 : result |= SYSTEM_OPTION_CONFIG_DIR;
846 : }
847 :
848 : // --show-option-sources
849 42 : if(is_defined("show-option-sources"))
850 : {
851 3 : show_option_sources(out);
852 3 : result |= SYSTEM_OPTION_SHOW_OPTION_SOURCES;
853 : }
854 :
855 : // --print-option
856 42 : if(is_defined("print-option"))
857 : {
858 0 : std::string const name(get_string("print-option"));
859 0 : if(is_defined(name))
860 : {
861 0 : out << get_string(name) << std::endl;
862 : }
863 0 : else if(has_default(name))
864 : {
865 0 : out << get_default(name) << std::endl;
866 : }
867 0 : result |= SYSTEM_OPTION_SHOW_OPTION_VALUE;
868 : }
869 :
870 42 : return result;
871 : }
872 :
873 :
874 :
875 :
876 :
877 6 : } // namespace advgetopt
878 : // vim: ts=4 sw=4 et
|