LCOV - code coverage report
Current view: top level - advgetopt - advgetopt.cpp (source / functions) Hit Total Coverage
Test: coverage.info Lines: 295 295 100.0 %
Date: 2020-11-13 17:54:34 Functions: 18 18 100.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13