Quick Links:

bal | bbl | bdl | bsl

Namespaces

Component balcl_commandline
[Package balcl]

Provide command line parsing, validation, and access. More...

Namespaces

namespace  balcl

Detailed Description

Outline
Purpose:
Provide command line parsing, validation, and access.
Classes:
balcl::CommandLine value-semantic command-line arguments
balcl::CommandLineOptionsHandle references to parsed options
See also:
Component balcl_optionvalue, Component balcl_optiontype
Description:
This component provides a value-semantic class, balcl::CommandLine, used to represent the command-line arguments passed to a process. Also provided is balcl::CommandLineOptionsHandle, a class that provides access to the options (and associative values, if any) found in a balcl::CommandLine object in a "parsed" state.
The constructor of balcl::CommandLine takes a specification describing the command-line arguments. Once created, printUsage can be invoked to print the usage syntax. The parse method takes command-line arguments and validates them against the specification supplied at construction, printing suitable messages on an optionally-specified stream in case of a parsing error. Once parsed, options and values can be accessed using various access methods. The class provides a set of theType access methods (for example, theString, theInt) that return the value of the specified option name. It is also possible to link a variable with an option in the specification; doing so will cause the variable to be loaded with the option value once parse has been invoked and was successful. The options method returns a balcl::CommandLineOptionsHandle containing option names and their values.
Component Features Summary:
This component offers the following features:
  1. Validation of command-line arguments against the provided specification.
  2. The ability to specify sophisticated constraints easily. Users can also build their own constraints and use them in the specification.
  3. The ability to automatically generate usage syntax.
  4. The ability to directly link a variable to an option. Parsing a command line loads such variables with the option value as specified on the command line (or a default value if one is configured). Linked variables provide a sometimes convenient alternative to using the accessor methods. See Type-and-Constraint Field. Linked variables can be bsl::optional objects for each of the scalar option types except bool.
  5. The ability to access options and their corresponding values through various accessor methods.
  6. The ability to parse Unix-style command lines (for example, grouping of flags, allowing any ordering of options, or a mix between options and non-option arguments, short tag and long tag forms, etc.).
  7. The ability to have multiple non-option arguments of possibly different types. Note that only the last non-option argument may be multi-valued, and that if a non-option has a default value, then all subsequent non-options must also have a default value.
A lower bound can be placed on the number of multi-valued non-option arguments (e.g., two or more values) can be achieved by explicitly specifying the required number of single-valued non-option arguments of the same type before the unrestricted multi-value non-option of that same type.
Background for Unix-Style Command-Line Arguments and Definitions:
This section provides background on Unix-style command-line arguments, as well as definitions of terms used frequently in this documentation (such as "option", "flag", "non-option", "tag", "short tag", "long tag"). Readers familiar with Unix command lines can skim this section or omit entirely.
Command-line arguments can be classified as:
  • command name (there is only one, and it is always the first argument)
  • options (tags and associated values)
  • flags (boolean options)
  • non-option arguments
For example, in the following command line:
  $ mybuildcommand -e -c CC64 myproject
the command name is mybuildcommand. There is one option, described by -c CC64: c is the tag name, and CC64 is the option value. There is also one boolean option (flag): -e is a flag, e is the flag name. The last parameter, myproject, is a non-option argument.
Sometimes option is also used where "flag" or "non-option" would be more accurate. What is actually intended should be clear from context.
A user specifies an option on a command line by entering one of the tag values configured for that option. Each option has a mandatory long tag and an optional short tag. The short tag, if specified, must be a single alphabet symbol; the long tag generally must follow the same rules applicable to C/C++ identifiers, except that - is allowed (but not as the leading character). When a short tag is used on a command line, it must be preceded by -, and when a long tag is used it must be preceded by --. Flags have no corresponding values; they are either present or absent. Option tags must be followed by a corresponding option value. An option can have multiple values (such options are called multi-valued options). When multiple values are provided for an option, the tag must appear with each value (see the section Multi-Valued Options and How to Specify Them). Arguments that are not the command name, options, or flags are called "non-option" arguments and can be either single-valued or multi-valued. They do not have any tag associated with them.
Consider the syntax of a typical Unix-style command whose options are described by the usage string:
  usage: mysort [-r|reverse] [-o|outputfile <outfile>] files...
Here:
  '-r|reverse' is a flag: 'r' is the short tag, 'reverse' is the long tag.

  '-o|outputfile' is an option: 'o' is the short tag, 'outputfile' is the
                  long tag.  The value is parsed from the string 'outfile'.

  'files...' describes the multi-valued non-option argument.
The command can be invoked as follows:
  $ mysort -r -o myoutfile file1 file2 file3
and an equivalent command line is:
  $ mysort --reverse --outputfile myoutfile file1 file2 file3
Note that short tags must be prepended with - and long tags with --. To specify a non-option argument beginning with -, use a single -- separator (not followed by a long tag).
Specifying Option Values:
This component supports a variety of forms for specifying option values. They are best described by example. Consider the command-line specification described by the following usage string:
  usage: myserver [-p|port <portNumber>]
The following (valid) forms can be used with equivalent meaning:
  $ myserver -p 13
  $ myserver -p=13  # option value is '13' and *not* '=13'
  $ myserver -p13
  $ myserver --port 13
  $ myserver --port=13
Note that if =13 is desired as an option value, then whitespace must be used as in:
  $ myserver -p =13  # option value *is* '=13'
All of the following are invalid:
  $ myserver -port13
  $ myserver --p 13
  $ myserver -port 13
Flag Grouping:
Flags can be grouped (i.e., expressed more succinctly like -ctv instead of -c -t -v). While grouping flags, short tags must be used. For example, given the command-line specification described by the following usage string:
  usage: mysort [-r|reverse] [-i|insensitiveToCase] [-u|uniq]
the following command lines are valid and equivalent:
  $ mysort -r -i -u
  $ cmd -riu
  $ cmd -uir
  $ cmd -i -ru
Note that the last character in a group need not be a flag; it could be an option. Any character that is the short tag of an option signals the end of the flag group, and it must be followed by the value of the option. For example, given the command-line specification described by the following usage string:
  usage: mysort [-r|reverse] [-i|insensitiveToCase] [-u|uniq]
                [-o|outfile <outputfile>]
the following command lines are valid and equivalent:
  $ mysort -riu -o myoutfile
  $ mysort -riuo myoutfile
  $ mysort -riuomyoutfile
  $ mysort -riuo=myoutfile
Multi-Valued Options and How to Specify Them:
Options can have several values. For example, in the command-line specification described by the following usage string, * denotes a multi-valued option, and + denotes a multivalued option that must occur at least once.
  usage: mycompiler [-l|library <libName>]* [-o|out outFile] [<object>]+
multiple values can be given as follows:
  $ mycompiler -l lib1 -l lib2 -l lib3 -o main a.o b.o
They need not be supplied contiguously. For example, the following command line is valid and equivalent to the above:
  $ mycompiler -l lib1 -o main -l lib2 -l lib3 a.o b.o
Note that the tag needs to be repeated for every option value. For example, the following command line is invalid (because -l must be repeated before both lib2 and lib3):
  $ mycompiler -l lib1 lib2 lib3 -o main a.o b.o
Short and long forms can be used in mixed fashion, however:
  $ mycompiler -l lib1 -o main --library lib2 -l lib3 a.o b.o
Order of Arguments:
Command-line arguments can appear in any order. For example, given the command-line specification described by the following usage string:
  usage: mysort [-r|reverse] [-o|outputfile <outfile>] [<file>]+
all the following command lines are valid (and equivalent):
  $ mysort -r -o myoutfile file1 file2 file3
  $ mysort file1 file2 file3 -r -o myoutfile
  $ mysort file1 -o myoutfile file2 -r file3
  $ mysort file1 -o=myoutfile file2 -r file3
There are three exceptions to the above rule on argument order:
  1. An option tag must be followed by that option's value, if any (either in the next argument, or in the same argument using "=value").
  2. When a non-option argument starts with a - then it must not appear before any option or flag and a -- must be put on the command line to indicate the end of all options and flags.
  3. Non-option arguments are parsed and assigned in the order they appear on the command line.
For example, the following is invalid because of rule (1) above (because -o should be followed by myoutfile):
  $ mysort -o -r myoutfile file1 file2 file3
and the following is incorrect because of rule (2) (because -weirdfilename, which starts with -, must appear after --):
  $ mysort -weirdfilename file2 file3 -r -o myoutfile
The previous examples can be corrected in either of the following ways:
  $ mysort -r -o myoutfile -- -weirdfilename file2 file3
  $ mysort file2 file3 -r -o myoutfile -- -weirdfilename
Note that the order of values within the sequence of multi-valued non-option arguments differs in both examples, as per rule (3). In the first example, the non-option arguments have for a value the (ordered) sequence:
  -weirdfilename file2 file3
while in the second example, the non-option argument value is the sequence:
  file2 file3 -weirdfilename
This order may or may not matter to the application.
Specifying Command-Line Arguments:
A command line is described by an option table (supplied as an array of balcl::OptionInfo). Each entry (row) of the table describes an option (i.e., an option, flag, or non-option argument). Each entry has several fields, specified in the following order:
  Field name                     Main purpose (see below for more details)
  ============================   ===========================================
  tag field                      Specify tags (short and long) for options
                                 and flags.  A non-option argument is
                                 indicated by an empty string.

  name field                     Specify the name through which the option
                                 value can be accessed.

  description field              Used in printing usage.

  type-and-constraint field      (1) Specify the type of the option value(s).
                                 (2) Specify a variable to be linked to the
                                     option.
                                 (3) Specify other constraints on individual
                                     value(s).

  occurrence information field   (1) Specify a default value for an option.
                                 (2) Specify whether an option is required on
                                     the command line or is optional (by
                                     default, an option is optional).
The first three fields must be specified. The type-and-constraint field can be omitted (meaning no constraint), and the occurrence information field likewise can be omitted (meaning that the option is not required on the command line).
The following sections provide a more detailed description of each field, including example values for each field.
balcl::OptionInfo versus balcl::Option:
In some applications, command-line specifications must be defined using a statically-initialized array. For that reason, there are two classes that serve the same purpose: balcl::OptionInfo is a statically-initializable class but it does not conform to the bslma allocator protocol, while balcl::Option is convertible from balcl::OptionInfo, takes allocators, and is suitable for storing into containers.
Tag Field:
The tag field specifies the (optional) short tag and long tag for the corresponding option or flag, except that non-option arguments are indicated by an empty string for a tag field. There can only be one multi-valued entry for non-option arguments, and it must be listed last among the non-options.
The general format is either:
  1. "" (empty string) for non-option arguments;
  2. "<s>|<long>" for options and flags, where <s> is the short tag, and <long> is the long tag; or
  3. "<long>" for options and flags where a short tag is not specified.
Note that for short tags (<s>), s must be a single character (different from - and |); for long tags ("<long>"), long must have 2 or more characters (which may contain -, except as the first character, but cannot contain |). Also note that either no tag (empty string), both short and long tags, or only a long tag, may be specified.
The tag field cannot be omitted, but it can be the empty string.
Name Field:
The name field specifies the name through which the option value can be accessed either through one of the theType methods or through the handle returned by the options method.
The general format is any non-empty string. In most cases, the name will be used as-is. Note that any suffix starting at the first occurrence of =, if any, is removed from the name before storing in the balcl::OptionInfo. Thus, if a name having such a suffix is specified in a balcl::OptionInfo (e.g., "nameOption=someAttribute"), the correct name to use for querying this option by name (e.g., through the options handle) does not include the suffix (e.g., cmdLine.numSpecified("nameOption=someAttribute") will always return 0, but cmdLine.numSpecified("nameOption") will return the appropriate value).
This field cannot be omitted, and it cannot be an empty string.
Description Field:
The description field is used when printing the usage string.
The general format is any non-empty string.
This field cannot be omitted, and it cannot be an empty string.
Type-and-Constraint Field:
The type-and-constraint field specifies the type and constraints for the option values. Flags are identified by having the boolean type; note that flags cannot have constraints. Multiple values (for multi-valued options and multi-valued non-option arguments) can be specified by using array types. The list of the supported types is provided in the section Supported Types below.
Other constraints can be placed on individual value(s). When the type is an array type, then those constraints are placed on the individual value(s) held in the array and not on the entire array. A list of useful constraints is provided in the section Supported Constraint Values. Also see the section Building New Constraints to see how new constraints can be built so that they can be used in the same manner as the available constraints.
Additionally, this field allows a specified variable to be linked to the option. In that case, after parsing, the variable is loaded with the option value specified on the command line (or its default value, if any, if the option is absent from the command line). Occurrence Information Field describes how to configure a default value.
The general format can be one of either:
  balcl::TypeInfo(&variable)
  balcl::TypeInfo(&variable, constraint)
      // Link the option with the specified 'variable'.  Note that the option
      // type is inferred from the type of 'variable'.  Optionally place the
      // user-specified 'constraint', of a type defined in
      // 'balcl::Constraint', on the value.

  balcl::TypeInfo(type)
  balcl::TypeInfo(type, constraint)
      // Specify the type of this option to be of the specified 'type'.
      // Optionally place the user-specified 'constraint', of a type defined
      // in 'balcl::Constraint', on the value.  Don't link this
      // option with any variable.  'type' must be one of the static
      // variables (null pointers) listed in
      // {'balcl_optiontype'|Enumerators}.
This field can be omitted. If so, the type is assumed to be of string type with no constraints and no variable is linked to the option. No occurrence information field can then be specified; if such a field is desired, then the type-and-constraint field needs to be set explicitly.
Linked Variables:
Linked variables are updated by the parse method of balcl::CommandLine should that method determine a value for an option; otherwise, the linked variable is left unchanged. The value for an option is determined either from the command-line arguments passed to parse or obtained from a pre-configured default value, if any (see Occurrence Information Field).
Linked variables can be bsl::optional objects that wrap any of the non-array option types except for bool (see Supported Types). Also, a link to a bsl::optional object is disallowed if the option is "required" or has a default value (see Occurrence Information Field).
Occurrence Information Field:
The occurrence information field is used to specify a default value for an option, and whether an option is required on the command line or is optional. An option may also be "hidden" (i.e., not displayed by printUsage).
The general format of this field is one of the following: If a default value is specified, the option is assumed to be optional; in addition, the default value must satisfy the type and constraint indicated by the specified type-and-constraint field.
This field can be omitted, and is always omitted if the type-and-constraint field is not specified. If omitted, the option is not required on the command line and has no default value; furthermore, if the option is not present on the command line, the linked variable, if any, is unaffected.
Example Field Values:
The following tables give examples of field values.
Example: Tag Field:
The tag field may be declared using the following forms:
     Usage                              Meaning
  ==============    =======================================================
  "o|outputfile"    The option being defined is either an option or a flag.
                    The short tag is "o" and the long tag is "outputfile".

                    Note that "o" alone is invalid since a long tag must be
                    specified.

  "outputfile"      The option being defined is either an option or a flag.
                    There is no short tag and the long tag is "outputfile".

      ""            Specifies a non-option argument.
Example: Name Field:
The name field may be declared using the following form:
      Usage                              Meaning
  ===============   =======================================================
     "xyz"          The option value can be accessed by "xyz".
Example: Type-and-Constraint Field:
Suppose, for example, that our application has the following parameters:
  int                      portNum;   // a variable to be linked to an
                                      // option

  bool                     isVerbose; // a variable to be linked to a flag

  bsl::vector<bsl::string> fileNames; // a variable to be linked to a
                                      // multi-valued option
The type and constraint fields may be declared using the following values:
     Usage                               Meaning
  ===============   =======================================================
  balcl::TypeInfo(&portNum)
                    (1) Link the variable 'portNum' with this option value.
                    That is, after successful parsing, this variable will
                    contain the option value specified on the command line.
                    (2) An integer value must be provided on the command
                    line for this option (the type 'int' is inferred
                    implicitly from the type of 'portNum').

  balcl::TypeInfo(balcl::OptionType::k_INT)
                    This option value must be an integer.

  balcl::TypeInfo(&isVerbose)
                    Load the variable 'isVerbose' with this option value.

  balcl::TypeInfo(balcl::OptionType::k_BOOL)
                    This option is a flag.

  balcl::TypeInfo(&fileNames)
                    Load the variable 'fileNames' with the values specified
                    for this multi-valued option (or multi-valued
                    non-option argument).  That is, after successful parsing,
                    this variable will contain the sequence of values
                    specified on the command line, in the same order.

  balcl::TypeInfo(balcl::OptionType::k_STRING_ARRAY)
                    This option value consists of a sequence of string
                    values specified on the command line, in the same order.
Example: Occurrence Information Field:
The following values may be used for this field:
     Usage                               Meaning
  ===============   ========================================================
  balcl::OccurrenceInfo::e_REQUIRED
                    The value(s) for this option *must* be provided on the
                    command line.  For options that are of an array type, at
                    least one value must be provided.  Omission manifests
                    as a parse error.

  balcl::OccurrenceInfo::e_OPTIONAL
                    Value(s) for this option may be omitted on the command
                    line.

  balcl::OccurrenceInfo::e_HIDDEN
                    Same as 'e_OPTIONAL'; in addition, this option will not
                    be displayed by 'printUsage'.

  13                The default value for this option is 13 and the option
                    is not required on the command line.  If no value is
                    provided, then 13 is used.  If the type described by the
                    type-and-constraint field is not integer, then it is an
                    error.
Note: If an option is optional and no value is provided on the command line, then it will be in a null state (defined type but no defined value) in the handle returned by either options or specifiedOptions. In addition, if a variable was linked to this option, it will be unmodified after parsing.
Supported Types:
The following types are supported. The type is specified by an enumeration value (see balcl_optiontype) supplied as the first argument to:
  balcl::TypeInfo(type, constraint)
which is used to create the type-and-constraint field value in the command-line specification. When the constraint need only specify the type of the option value (i.e., no linked variable or programmatic constraint), one can supply any of the public data members of balcl::OptionType shown below:
  Type                            Specifier
  -----------------------------   -------------------------
  bool                            OptionType::k_BOOL
  char                            OptionType::k_CHAR
  int                             OptionType::k_INT
  bsls::Types::Int64              OptionType::k_INT64
  double                          OptionType::k_DOUBLE
  bsl::string                     OptionType::k_STRING
  bdlt::Datetime                  OptionType::k_DATETIME
  bdlt::Date                      OptionType::k_DATE
  bdlt::Time                      OptionType::k_TIME
  bsl::vector<char>               OptionType::k_CHAR_ARRAY
  bsl::vector<int>                OptionType::k_INT_ARRAY
  bsl::vector<bsls::Types::Int64> OptionType::k_INT64_ARRAY
  bsl::vector<double>             OptionType::k_DOUBLE_ARRAY
  bsl::vector<bsl::string>        OptionType::k_STRING_ARRAY
  bsl::vector<bdlt::Datetime>     OptionType::k_DATETIME_ARRAY
  bsl::vector<bdlt::Date>         OptionType::k_DATE_ARRAY
  bsl::vector<bdlt::Time>         OptionType::k_TIME_ARRAY
The ASCII representation of these values (i.e., the actual format of the values on command lines) depends on the type:
Supported Constraint Values:
This component supports constraint values for each supported type except bool. Specifically, the utility struct balcl::Constraint defines TYPEConstraint types (for instance, StringConstraint, IntConstraint) that can be used to define a constraint suitable for the balcl::TypeInfo class.
Building New Constraints:
A constraint is simply a function object that takes as its first argument the (address of the) data to be constrained and as its second argument the stream that should be written to with an appropriate error message when the data does not follow the constraint. The functor should return a bool value indicating whether or not the data abides by the constraint (with true indicating success). A constraint for a given option whose value has the given type must be convertible to one of the TYPEConstraint types defined in the utility struct balcl::Constraint. Note that when passing a function as a constraint, the address of the function must be passed.
Valid balcl::OptionInfo Specifications:
The balcl::CommandLine class has a complex set of preconditions on the option specification table (array of balcl::OptionInfo objects) passed to each of its constructors. There are requirements on individual elements, on elements relative to each other, and on the entire set of elements. If these preconditions are not met, the behavior of the constructor is undefined.
The preconditions (some previously mentioned) are given in their entirety below. Moreover, an overloaded class method, balcl::CommandLine::isValidOptionSpecification, is provided to allow programmatic checking without risk of incurring undefined behavior.
Tag/Name/Description Fields:
The tag, name, and description fields must pass the isTagValid, isNameValid, and 'isDescriptionValid methods of balcl::Option, respectively.
  • The tag field:

    • If empty (a non-option argument), the option must not be a flag.
    • If non-empty, see Tag Field above for details.

  • The name field must be non-empty.
  • The description field must be non-empty.
Collectively, each non-empty short tag, each long tag, and each name must be unique in the specification.
Default Values:
  • Default values are disallowed for flags.
  • The type of a default value must match the type of its option.
  • The default value must satisfy the user-defined constraint on the option value, if any.
Non-Option Arguments:
  • Cannot be a flag (see Tag/Name/Description Fields).
  • Cannot be a hidden option.
  • Only the last non-option argument can be multi-valued (i.e., an array type).
  • If a non-option argument has a default value, all subsequent non-option arguments must also have default values.
Boolean Options (Flags):
Options having the bool type (also known as "flags") are distinguished from the other supported option types in several ways:
  • The command-line syntax does not allow an explicit value for flag types (e.g., -x=true and -xFlag false are disallowed). The presence or absence of the tag name (either long or short form) on the command line determines the value of the option.
  • The boolean option type has no "array" form (i.e., there is no BoolArray option type).

    • Multiple instances of the tag for a boolean option are allowed on the command line (e.g., -x -x -x). For other option types, specifying multiple tags for a non-array option is an error.
    • Multiple instances of a boolean tag idempotently set the flag to true; however, one can determine the number of appearances by using the position accessor.

  • A boolean option type cannot be configured to:

    • have a default value, or
    • have a constraint, or
    • be linked to a bsl::optional<bool> variable.

  • A boolean option type can be configured to be a required parameter; however, that combination defeats the purpose of having a flag option so the requirement that the flag appear on the command line is not enforced.
  • The theBool method returns the same value (true or false) as the isSpecified method. In contrast, the the* accessor methods for the other option types have a precondition such that either isSpecified() must be true or the option must have a default value.
Usage:
This section illustrates intended use of this component.
Example 1: Using Command Line Features In Concert:
Suppose we want to design a sorting utility named mysort that has the following syntax:
  usage: mysort  [-r|reverse] [-i|insensitivetocase] [-u|uniq]
                 [-a|algorithm sortAlgo] -o|outputfile <outputFile>
                 [-t|field-separator] <character>
                 [<file>]*
                            // Sort the specified files (in 'fileList'),
                            // using the specified sorting algorithm and
                            // write the output to the specified output file.

     option                               note
  ============  ====================================================
  -a|algorithm  (1) Value (provided on command line) of this option must
                    be one among "quickSort", "insertionSort", "shellSort".
                (2) If not provided, default value will be "quickSort".

  -o|outfile    (1) This option must not be omitted on command line.
We choose the non-option argument to be an array of bsl::string so as to accommodate multiple files.
These options might be used incorrectly, as the following examples show:
             INCORRECT USE                        REASON FOR INACCURACY
  ===========================================  ============================
  $ mysort -riu -o myofile -aDUMBSORT f1 f2    Incorrect because 'DUMBSORT'
                                               is not among valid values
                                               for the -a option.

  $ mysort -riu f1 f2                          Incorrect because no value
                                               is provided for the -o option.
In order to enforce the constraint on the sorting algorithms that are supported, our application provides the following free function:
  bool isValidAlgorithm(const bsl::string *algo, bsl::ostream& stream)
      // Return 'true' if the specified 'algo' is one among "quickSort",
      // "insertionSort", and "shellSort"; otherwise, output to the specified
      // 'stream' an appropriate error message and return 'false'.
  {
      if ("quickSort" == *algo || "insertionSort" == *algo
       || "shellSort" == *algo) {
          return true;                                              // RETURN
      }
      stream << "Error: sorting algorithm must be either "
                "'quickSort', 'insertionSort', or 'shellSort'.\n";
      return false;
  }
Using this function, we can now use a balcl::CommandLine object to parse command-line options. The proper usage is shown below. First we declare the variables to be linked to the options. If they are needed at global scope, we could declare them as global variables, but we prefer to declare them as local variables inside main:
  int main(int argc, const char *argv[]) {
Then, we define local variables that will be linked to certain command-line options. If those options are specified on the command line (or if a default is specified via balcl::OccurrenceInfo), these variables are updated; otherwise, these variables are left unchanged.
      bool isReverse         = false;  // Must be initially 'false'.
      bool isCaseInsensitive = false;  // Must be initially 'false'.
      bool isUniq            = false;  // Must be initially 'false'.

      bsl::optional<char>      fieldSeparator;
      bsl::string              outFile;
      bsl::string              sortAlgo;
      bsl::vector<bsl::string> files;
Notice that variables linked to flags (boolean options) are initialized to false; otherwise, these variables would show incorrect values (i.e., true) if their corresponding tags are absent from the command line.
Next, we build up an option specification table as follows:
      // build constraint for sortAlgo option
      balcl::Constraint::StringConstraint validAlgoConstraint(
                                                          &isValidAlgorithm);

      // option specification table
      balcl::OptionInfo specTable[] = {
        {
          "r|reverse",                                     // tag
          "isReverse",                                     // name
          "sort in reverse order",                         // description
          balcl::TypeInfo(&isReverse),                     // link
          balcl::OccurrenceInfo::e_OPTIONAL                // occurrence info
        },
        {
          "i|insensitivetocase",                           // tag
          "isCaseInsensitive",                             // name
          "be case insensitive while sorting",             // description
          balcl::TypeInfo(&isCaseInsensitive),             // link
          balcl::OccurrenceInfo::e_OPTIONAL                // occurrence info
        },
        {
          "u|uniq",                                        // tag
          "isUniq",                                        // name
          "discard duplicate lines",                       // description
          balcl::TypeInfo(&isUniq),                        // link
          balcl::OccurrenceInfo::e_OPTIONAL                // occurrence info
        },
        {
          "t|field-separator",                             // tag
          "fieldSeparator",                                // name
          "field separator character",                     // description
          balcl::TypeInfo(&fieldSeparator),                // link
          balcl::OccurrenceInfo::e_OPTIONAL                // occurrence info
        },
        {
          "a|algorithm",                                   // tag
          "sortAlgo",                                      // name
          "sorting algorithm",                             // description
          balcl::TypeInfo(&sortAlgo, validAlgoConstraint),
                                                           // link and
                                                           // constraint
          balcl::OccurrenceInfo(bsl::string("quickSort"))
                                                           // default
                                                           // algorithm
        },
        {
          "o|outputfile",                                  // tag
          "outputFile",                                    // name
          "output file",                                   // description
          balcl::TypeInfo(&outFile),                       // link
          balcl::OccurrenceInfo::e_REQUIRED                // occurrence info
        },
        {
          "",                                              // non-option
          "fileList",                                      // name
          "files to be sorted",                            // description
          balcl::TypeInfo(&files),                         // link
          balcl::OccurrenceInfo::e_OPTIONAL                // occurrence info
        }
      };
We can now create a command-line specification and parse the command-line options:
      // Create command-line specification.
      balcl::CommandLine cmdLine(specTable);

      // Parse command-line options; if failure, print usage.
      if (cmdLine.parse(argc, argv)) {
          cmdLine.printUsage();
          return -1;                                                // RETURN
      }
Upon successful parsing, the cmdLine object will acquire a value that conforms to the specified constraints. We can examine these values as follows:
      // If successful, obtain command-line option values.
      balcl::CommandLineOptionsHandle options = cmdLine.options();

      // Access through linked variable.
      bsl::cout << "outFile: " << outFile << bsl::endl;
      bsl::cout << "isUniq:  " << isUniq  << bsl::endl;
      if (fieldSeparator.has_value()) {
          bsl::cout << "fieldSeparator: "
                    <<  fieldSeparator.value() << bsl::endl;
      }

      // Access through *theType* methods.
      assert(cmdLine.theString("outputFile") == outFile);

      // Access through 'options'.
      assert(options.theString("outputFile") == outFile);

      // Check that required option has been specified once.
      assert(cmdLine.isSpecified("outputFile"));

      int count = -1;
      assert(cmdLine.isSpecified("outputFile", &count));
      assert(1 == count);

      return 0;
  }
For instance, the following command lines:
  $ mysort -omyofile f1 f2 f3
  $ mysort -ainsertionSort f1 f2 f3 -riu -o myofile outputFile
  $ mysort --algorithm insertionSort --outputfile myofile f1 f2 f3 --uniq
will all produce the same output on stdout.