From: Misha Brukman Date: Fri, 24 Oct 2003 19:59:21 +0000 (+0000) Subject: * Use stylesheets and
s for layout instead of +
  • Top-Level Classes and Functions +
  • The + cl::ParseCommandLineOptions function
  • +
  • The + cl::ParseEnvironmentOptions function
  • +
  • The cl::opt class
  • +
  • The cl::list class
  • +
  • The cl::alias class
  • + +
  • Builtin parsers - + parser<float> specializations
  • + +
  • Extension Guide
      -
    1. Writing a custom parser -
    2. Exploiting external storage -
    3. Dynamically adding command line options -
    - -

    Written by Chris Lattner

    -

    +

  • Writing a custom parser
  • +
  • Exploiting external storage
  • +
  • Dynamically adding command line + options
  • + + +
    +

    Written by Chris Lattner

    +
    - -
    -Introduction -
    -Quick Start Guide -
       -Boolean Arguments -
       -Argument Aliases -
       -Selecting an alternative from a set of possibilities -
       -Named Alternatives -
       -Parsing a list of options -
       -Adding freeform text to help output -
    -Reference Guide -
       -Positional Arguments -


    Specifying positional options with hyphens

      + -Sometimes you may want to specify a value to your positional argument that +
      + +

      Sometimes you may want to specify a value to your positional argument that starts with a hyphen (for example, searching for '-foo' in a file). At first, you will have trouble doing this, because it will try to find an argument named '-foo', and will fail (and single quotes will not save you). -Note that the system grep has the same problem:

      +Note that the system grep has the same problem:

         $ spiffygrep '-foo' test.txt
      @@ -762,45 +808,49 @@ Note that the system grep has the same problem:

      grep: illegal option -- o grep: illegal option -- o Usage: grep -hblcnsviw pattern file . . . -

      + -The solution for this problem is the same for both your tool and the system +

      The solution for this problem is the same for both your tool and the system version: use the '--' marker. When the user specifies '--' on the command line, it is telling the program that all options after the '--' should be treated as positional arguments, not options. Thus, we -can use it like this:

      +can use it like this:

         $ spiffygrep -- -foo test.txt
           ...output...
      -

      - + +

      -


    The cl::ConsumeAfter modifier

      + + +
      -The cl::ConsumeAfter formatting option is +

      The cl::ConsumeAfter formatting option is used to construct programs that use "interpreter style" option processing. With this style of option processing, all arguments specified after the last positional argument are treated as special interpreter arguments that are not -interpreted by the command line argument.

      +interpreted by the command line argument.

      -As a concrete example, lets say we are developing a replacement for the standard -Unix Bourne shell (/bin/sh). To run /bin/sh, first you -specify options to the shell itself (like -x which turns on trace +

      As a concrete example, lets say we are developing a replacement for the +standard Unix Bourne shell (/bin/sh). To run /bin/sh, first +you specify options to the shell itself (like -x which turns on trace output), then you specify the name of the script to run, then you specify arguments to the script. These arguments to the script are parsed by the bourne shell command line option processor, but are not interpreted as options to the -shell itself. Using the CommandLine library, we would specify this as:

      +shell itself. Using the CommandLine library, we would specify this as:

       cl::opt<string> Script(cl::Positional, cl::desc("<input script>"), cl::init("-"));
       cl::list<string>  Argv(cl::ConsumeAfter, cl::desc("<program arguments>..."));
       cl::opt<bool>    Trace("x", cl::desc("Enable trace output"));
      -

      + -which automatically provides the help output:

      +

      which automatically provides the help output:

       USAGE: spiffysh [options] <input script> <program arguments>...
      @@ -808,43 +858,45 @@ USAGE: spiffysh [options] <input script> <program arguments>...-x    - Enable trace output
      -

      + -At runtime, if we run our new shell replacement as 'spiffysh -x test.sh -a --x -y bar', the Trace variable will be set to true, the +

      At runtime, if we run our new shell replacement as 'spiffysh -x test.sh +-a -x -y bar', the Trace variable will be set to true, the Script variable will be set to "test.sh", and the -Argv list will contain ["-a", "-x", "-y", "bar"], because -they were specified after the last positional argument (which is the script -name).

      +Argv list will contain ["-a", "-x", "-y", "bar"], because they +were specified after the last positional argument (which is the script +name).

      -There are several limitations to when cl::ConsumeAfter options can be -specified. For example, only one cl::ConsumeAfter can be specified per -program, there must be at least one positional +

      There are several limitations to when cl::ConsumeAfter options can +be specified. For example, only one cl::ConsumeAfter can be specified +per program, there must be at least one positional argument specified, and the cl::ConsumeAfter option should be a cl::list option.

      - +href="#cl::list">cl::list option.

      +
      -
       -Internal vs External Storage -
      + + +
      -By default, all command line options automatically hold the value that they +

      By default, all command line options automatically hold the value that they parse from the command line. This is very convenient in the common case, especially when combined with the ability to define command line options in the -files that use them. This is called the internal storage model.

      +files that use them. This is called the internal storage model.

      -Sometimes, however, it is nice to separate the command line option processing +

      Sometimes, however, it is nice to separate the command line option processing code from the storage of the value parsed. For example, lets say that we have a '-debug' option that we would like to use to enable debug information across the entire body of our program. In this case, the boolean value controlling the debug code should be globally accessable (in a header file, for example) yet the command line option processing code should not be exposed to all of these clients (requiring lots of .cpp files to #include -CommandLine.h).

      +CommandLine.h).

      -To do this, set up your .h file with your option, like this for example:

      +

      To do this, set up your .h file with your option, like this for example:

       // DebugFlag.h - Get access to the '-debug' command line option
      @@ -863,19 +915,20 @@ extern bool DebugFlag;
       //
       // DEBUG(cerr << "Bitset contains: " << Bitset << "\n");
       //
      -#ifdef NDEBUG
      +#ifdef NDEBUG
       #define DEBUG(X)
       #else
      -#define DEBUG(X) \
      +#define DEBUG(X) \
         do { if (DebugFlag) { X; } } while (0)
      -#endif
      +#endif
       
      -This allows clients to blissfully use the DEBUG() macro, or the +

      This allows clients to blissfully use the DEBUG() macro, or the DebugFlag explicitly if they want to. Now we just need to be able to set the DebugFlag boolean when the option is set. To do this, we pass an additial argument to our command line argument processor, and we specify -where to fill in with the cl::location attribute:

      +where to fill in with the cl::location +attribute:

       bool DebugFlag;      // the actual value
      @@ -884,41 +937,46 @@ Debug("debug", cl::desc("Enable debug outputcl::location(DebugFlag));
       
      -In the above example, we specify "true" as the second argument to the -cl::opt template, indicating that the template should not -maintain a copy of the value itself. In addition to this, we specify the In the above example, we specify "true" as the second argument to +the cl::opt template, indicating that the template should +not maintain a copy of the value itself. In addition to this, we specify the cl::location attribute, so that DebugFlag is -automatically set.

      - +automatically set.

      +
      -
       -Option Attributes -
       -Option Modifiers -


    Hiding an option from --help output


    Controlling the number of occurances required and allowed


    Controlling whether or not a value must be specified

      + + +
      -This group of options is used to control whether or not the option allows a +

      This group of options is used to control whether or not the option allows a value to be present. In the case of the CommandLine library, a value is either specified with an equal sign (e.g. '-index-depth=17') or as a trailing -string (e.g. '-o a.out').

      +string (e.g. '-o a.out').

      -The allowed values for this option group are:

      +

      The allowed values for this option group are:

      -In general, the default values for this option group work just like you would +

      In general, the default values for this option group work just like you would want them to. As mentioned above, you can specify the cl::ValueDisallowed modifier to a boolean argument to restrict your command line parser. These options are mostly useful -when extending the library.

      - +when extending the library.

      +
      -


    Controlling other formatting options


    Miscellaneous option modifiers

      + + +
      -The miscellaneous option modifiers are the only flags where you can specify more -than one flag from the set: they are not mutually exclusive. These flags -specify boolean properties that modify the option.

      +

      The miscellaneous option modifiers are the only flags where you can specify +more than one flag from the set: they are not mutually exclusive. These flags +specify boolean properties that modify the option.

        -The cl::CommaSeparated modifier +
      • The cl::CommaSeparated modifier indicates that any commas specified for an option's value should be used to split the value up into multiple values for the option. For example, these two options are equivalent when cl::CommaSeparated is specified: "-foo=a -foo=b -foo=c" and "-foo=a,b,c". This option only makes sense to be used in a case where the option is allowed to accept one or -more values (i.e. it is a cl::list option).

        +more values (i.e. it is a cl::list option).

      • +
      -So far, the only miscellaneous option modifier is the -cl::CommaSeparated modifier.

      +

      So far, the only miscellaneous option modifier is the +cl::CommaSeparated modifier.

      +
      -
       -Top-Level Classes and Functions -


    The -cl::ParseCommandLineOptions function

      + + +
      -The cl::ParseCommandLineOptions function is designed to be called +

      The cl::ParseCommandLineOptions function is designed to be called directly from main, and is used to fill in the values of all of the command line option variables once argc and argv are -available.

      +available.

      -The cl::ParseCommandLineOptions function requires two parameters +

      The cl::ParseCommandLineOptions function requires two parameters (argc and argv), but may also take an optional third parameter which holds additional extra text to emit when the ---help option is invoked.

      +--help option is invoked.

      +
      -


    The -cl::ParseEnvironmentOptions function

      - -The cl::ParseEnvironmentOptions -function has mostly the same effects as -cl::ParseCommandLineOptions, -except that it is designed to take values for options from an -environment variable, for those cases in which reading the -command line is not convenient or not desired. It fills in -the values of all the command line option variables just like -cl::ParseCommandLineOptions -does.

      - -It takes three parameters: first, the name of the program (since argv -may not be available, it can't just look in argv[0]), second, -the name of the environment variable to examine, and third, the optional +

      + +
      + +

      The cl::ParseEnvironmentOptions function has mostly the same effects +as cl::ParseCommandLineOptions, +except that it is designed to take values for options from an environment +variable, for those cases in which reading the command line is not convenient or +not desired. It fills in the values of all the command line option variables +just like cl::ParseCommandLineOptions +does.

      + +

      It takes three parameters: first, the name of the program (since +argv may not be available, it can't just look in argv[0]), +second, the name of the environment variable to examine, and third, the optional additional extra text to emit when the ---help option is invoked.

      +--help option is invoked.

      -cl::ParseEnvironmentOptions will break the environment +

      cl::ParseEnvironmentOptions will break the environment variable's value up into words and then process them using cl::ParseCommandLineOptions. Note: Currently cl::ParseEnvironmentOptions does not support quoting, so an environment variable containing -option "foo bar" will be parsed as three words, -option, "foo, and bar", which is different from what you would get from the shell with the same -input.

      +input.

      + +
      -


    The cl::opt class

      + -The cl::opt class is the class used to represent scalar command line +
      + +

      The cl::opt class is the class used to represent scalar command line options, and is the one used most of the time. It is a templated class which can take up to three arguments (all except for the first have default values -though):

      +though):

       namespace cl {
      @@ -1258,28 +1380,33 @@ though):

      class ParserClass = parser<DataType> > class opt; } -

      + -The first template argument specifies what underlying data type the command line -argument is, and is used to select a default parser implementation. The second -template argument is used to specify whether the option should contain the -storage for the option (the default) or whether external storage should be used -to contain the value parsed for the option (see Internal vs -External Storage for more information).

      +

      The first template argument specifies what underlying data type the command +line argument is, and is used to select a default parser implementation. The +second template argument is used to specify whether the option should contain +the storage for the option (the default) or whether external storage should be +used to contain the value parsed for the option (see Internal +vs External Storage for more information).

      -The third template argument specifies which parser to use. The default value +

      The third template argument specifies which parser to use. The default value selects an instantiation of the parser class based on the underlying data type of the option. In general, this default works well for most applications, so this option is only used when using a custom parser.

      +href="#customparser">custom parser.

      +
      -


    The cl::list class

      + -The cl::list class is the class used to represent a list of command +
      + +

      The cl::list class is the class used to represent a list of command line options. It too is a templated class which can take up to three -arguments:

      +arguments:

       namespace cl {
      @@ -1287,135 +1414,162 @@ arguments:

      class ParserClass = parser<DataType> > class list; } -

      + -This class works the exact same as the cl::opt -class, except that the second argument is the type of the external -storage, not a boolean value. For this class, the marker type 'bool' -is used to indicate that internal storage should be used.

      +

      This class works the exact same as the cl::opt class, except that the second argument is +the type of the external storage, not a boolean value. For this class, +the marker type 'bool' is used to indicate that internal storage should +be used.

      +
      -


    The cl::alias class

      + -The cl::alias class is a nontemplated class that is used to form -aliases for other arguments.

      +

      + +

      The cl::alias class is a nontemplated class that is used to form +aliases for other arguments.

       namespace cl {
         class alias;
       }
      -

      + -The cl::aliasopt attribute should be used -to specify which option this is an alias for. Alias arguments default to being -Hidden, and use the aliased options parser to do the -conversion from string to data.

      +

      The cl::aliasopt attribute should be +used to specify which option this is an alias for. Alias arguments default to +being Hidden, and use the aliased options parser to do +the conversion from string to data.

      +
      -
       -Builtin parsers -
      + + +
      -Parsers control how the string value taken from the command line is translated -into a typed value, suitable for use in a C++ program. By default, the -CommandLine library uses an instance of parser<type> if the +

      Parsers control how the string value taken from the command line is +translated into a typed value, suitable for use in a C++ program. By default, +the CommandLine library uses an instance of parser<type> if the command line option specifies that it uses values of type 'type'. Because of this, custom option processing is specified with specializations of -the 'parser' class.

      +the 'parser' class.

      -The CommandLine library provides the following builtin parser specializations, -which are sufficient for most applications. It can, however, also be extended to -work with new data types and new ways of interpreting the same data. See the Writing a Custom Parser for more details on this type -of library extension.

      +

      The CommandLine library provides the following builtin parser +specializations, which are sufficient for most applications. It can, however, +also be extended to work with new data types and new ways of interpreting the +same data. See the Writing a Custom Parser for more +details on this type of library extension.

      -
    • The generic parser<t> parser + +
    • -
    -Extension Guide -
      + -Although the CommandLine library has a lot of functionality built into it +
      + +

      Although the CommandLine library has a lot of functionality built into it already (as discussed previously), one of its true strengths lie in its extensibility. This section discusses how the CommandLine library works under -the covers and illustrates how to do some simple, common, extensions.

      +the covers and illustrates how to do some simple, common, extensions.

      +
      -
    -
       Writing a custom parser -
      + -One of the simplest and most common extensions is the use of a custom parser. +
      + +

      One of the simplest and most common extensions is the use of a custom parser. As discussed previously, parsers are the portion of the CommandLine library that turns string input from the user into a -particular parsed data type, validating the input in the process.

      +particular parsed data type, validating the input in the process.

      -There are two ways to use a new parser:

      +

      There are two ways to use a new parser:

        -
      1. Specialize the cl::parser template for - your custom data type.

        - This approach has the advantage that users of your custom data type will - automatically use your custom parser whenever they define an option with a - value type of your data type. The disadvantage of this approach is that it - doesn't work if your fundemental data type is something that is already - supported.

        +

      2. + +

        Specialize the cl::parser template for +your custom data type.

        + +

        This approach has the advantage that users of your custom data type will +automatically use your custom parser whenever they define an option with a value +type of your data type. The disadvantage of this approach is that it doesn't +work if your fundemental data type is something that is already supported.

        -
      3. Write an independent class, using it explicitly from options that need - it.

        +

      4. - This approach works well in situations where you would line to parse an - option using special syntax for a not-very-special data-type. The drawback - of this approach is that users of your parser have to be aware that they are - using your parser, instead of the builtin ones.

        +

      5. -

      +

      Write an independent class, using it explicitly from options that need +it.

      -To guide the discussion, we will discuss a custom parser that accepts file +

      This approach works well in situations where you would line to parse an +option using special syntax for a not-very-special data-type. The drawback of +this approach is that users of your parser have to be aware that they are using +your parser, instead of the builtin ones.

      + + + + + +

      To guide the discussion, we will discuss a custom parser that accepts file sizes, specified with an optional unit after the numeric size. For example, we would like to parse "102kb", "41M", "1G" into the appropriate integer value. In this case, the underlying data type we want to parse into is 'unsigned'. We choose approach #2 above because we don't want to make -this the default for all unsigned options.

      +this the default for all unsigned options.

      -To start out, we declare our new FileSizeParser class:

      +

      To start out, we declare our new FileSizeParser class:

       struct FileSizeParser : public cl::basic_parser<unsigned> {
      @@ -1423,18 +1577,21 @@ To start out, we declare our new FileSizeParser class:

      bool parse(cl::Option &O, const char *ArgName, const std::string &ArgValue, unsigned &Val); }; -

      + -Our new class inherits from the cl::basic_parser template class to fill -in the default, boiler plate, code for us. We give it the data type that we -parse into (the last argument to the parse method so that clients of +

      Our new class inherits from the cl::basic_parser template class to +fill in the default, boiler plate, code for us. We give it the data type that +we parse into (the last argument to the parse method so that clients of our custom parser know what object type to pass in to the parse method (here we -declare that we parse into 'unsigned' variables.

      +declare that we parse into 'unsigned' variables.

      -For most purposes, the only method that must be implemented in a custom parser -is the parse method. The parse method is called whenever the -option is invoked, passing in the option itself, the option name, the string to -parse, and a reference to a return value. If the string to parse is not well formed, the parser should output an error message and return true. Otherwise it should return false and set 'Val' to the parsed value. In our example, we implement parse as:

      +

      For most purposes, the only method that must be implemented in a custom +parser is the parse method. The parse method is called +whenever the option is invoked, passing in the option itself, the option name, +the string to parse, and a reference to a return value. If the string to parse +is not well formed, the parser should output an error message and return true. +Otherwise it should return false and set 'Val' to the parsed value. In +our example, we implement parse as:

       bool FileSizeParser::parse(cl::Option &O, const char *ArgName,
      @@ -1462,32 +1619,32 @@ parse, and a reference to a return value.  If the string to parse is not well fo
           }
         }
       }
      -

      + -This function implements a very simple parser for the kinds of strings we are +

      This function implements a very simple parser for the kinds of strings we are interested in. Although it has some holes (it allows "123KKK" for example), it is good enough for this example. Note that we use the option itself to print out the error message (the error method always returns true) in order to get a nice error message (shown below). Now that we have our -parser class, we can use it like this:

      +parser class, we can use it like this:

       static cl::opt<unsigned, false, FileSizeParser>
       MFS("max-file-size", cl::desc("Maximum file size to accept"),
           cl::value_desc("size"));
      -

      + -Which adds this to the output of our program:

      +

      Which adds this to the output of our program:

       OPTIONS:
         -help                 - display available options (--help-hidden for more)
         ...
         -max-file-size=<size> - Maximum file size to accept
      -

      + -And we can test that our parse works correctly now (the test program just prints -out the max-file-size argument value):

      +

      And we can test that our parse works correctly now (the test program just +prints out the max-file-size argument value):

       $ ./test
      @@ -1498,41 +1655,43 @@ $ ./test -max-file-size=3G
       MFS: 3221225472
       $ ./test -max-file-size=dog
       -max-file-size option: 'dog' value invalid for file size argument!
      -

      + -It looks like it works. The error message that we get is nice and helpful, and -we seem to accept reasonable file sizes. This wraps up the "custom parser" -tutorial.

      +

      It looks like it works. The error message that we get is nice and helpful, +and we seem to accept reasonable file sizes. This wraps up the "custom parser" +tutorial.

      +
      -
    -
       Exploiting external -storage
    -
       Dynamically adding command -line options
      +
    + + +
    +

    TODO: fill in this section

    +
    - -
    - + + + +