diff options
Diffstat (limited to 'docs/CommandLine.rst')
-rw-r--r-- | docs/CommandLine.rst | 1615 |
1 files changed, 1615 insertions, 0 deletions
diff --git a/docs/CommandLine.rst b/docs/CommandLine.rst new file mode 100644 index 0000000000..302f5a4cf5 --- /dev/null +++ b/docs/CommandLine.rst @@ -0,0 +1,1615 @@ +.. _commandline: + +============================== +CommandLine 2.0 Library Manual +============================== + +Introduction +============ + +This document describes the CommandLine argument processing library. It will +show you how to use it, and what it can do. The CommandLine library uses a +declarative approach to specifying the command line options that your program +takes. By default, these options declarations implicitly hold the value parsed +for the option declared (of course this `can be changed`_). + +Although there are a **lot** of command line argument parsing libraries out +there in many different languages, none of them fit well with what I needed. By +looking at the features and problems of other libraries, I designed the +CommandLine library to have the following features: + +#. Speed: The CommandLine library is very quick and uses little resources. The + parsing time of the library is directly proportional to the number of + arguments parsed, not the number of options recognized. Additionally, + command line argument values are captured transparently into user defined + global variables, which can be accessed like any other variable (and with the + same performance). + +#. Type Safe: As a user of CommandLine, you don't have to worry about + remembering the type of arguments that you want (is it an int? a string? a + bool? an enum?) and keep casting it around. Not only does this help prevent + error prone constructs, it also leads to dramatically cleaner source code. + +#. No subclasses required: To use CommandLine, you instantiate variables that + correspond to the arguments that you would like to capture, you don't + subclass a parser. This means that you don't have to write **any** + boilerplate code. + +#. Globally accessible: Libraries can specify command line arguments that are + automatically enabled in any tool that links to the library. This is + possible because the application doesn't have to keep a list of arguments to + pass to the parser. This also makes supporting `dynamically loaded options`_ + trivial. + +#. Cleaner: CommandLine supports enum and other types directly, meaning that + there is less error and more security built into the library. You don't have + to worry about whether your integral command line argument accidentally got + assigned a value that is not valid for your enum type. + +#. Powerful: The CommandLine library supports many different types of arguments, + from simple `boolean flags`_ to `scalars arguments`_ (`strings`_, + `integers`_, `enums`_, `doubles`_), to `lists of arguments`_. This is + possible because CommandLine is... + +#. Extensible: It is very simple to add a new argument type to CommandLine. + Simply specify the parser that you want to use with the command line option + when you declare it. `Custom parsers`_ are no problem. + +#. Labor Saving: The CommandLine library cuts down on the amount of grunt work + that you, the user, have to do. For example, it automatically provides a + ``-help`` option that shows the available command line options for your tool. + Additionally, it does most of the basic correctness checking for you. + +#. Capable: The CommandLine library can handle lots of different forms of + options often found in real programs. For example, `positional`_ arguments, + ``ls`` style `grouping`_ options (to allow processing '``ls -lad``' + naturally), ``ld`` style `prefix`_ options (to parse '``-lmalloc + -L/usr/lib``'), and interpreter style options. + +This document will hopefully let you jump in and start using CommandLine in your +utility quickly and painlessly. Additionally it should be a simple reference +manual to figure out how stuff works. If it is failing in some area (or you +want an extension to the library), nag the author, `Chris +Lattner <mailto:sabre@nondot.org>`_. + +Quick Start Guide +================= + +This section of the manual runs through a simple CommandLine'ification of a +basic compiler tool. This is intended to show you how to jump into using the +CommandLine library in your own program, and show you some of the cool things it +can do. + +To start out, you need to include the CommandLine header file into your program: + +.. code-block:: c++ + + #include "llvm/Support/CommandLine.h" + +Additionally, you need to add this as the first line of your main program: + +.. code-block:: c++ + + int main(int argc, char **argv) { + cl::ParseCommandLineOptions(argc, argv); + ... + } + +... which actually parses the arguments and fills in the variable declarations. + +Now that you are ready to support command line arguments, we need to tell the +system which ones we want, and what type of arguments they are. The CommandLine +library uses a declarative syntax to model command line arguments with the +global variable declarations that capture the parsed values. This means that +for every command line option that you would like to support, there should be a +global variable declaration to capture the result. For example, in a compiler, +we would like to support the Unix-standard '``-o <filename>``' option to specify +where to put the output. With the CommandLine library, this is represented like +this: + +.. _scalars arguments: +.. _here: + +.. code-block:: c++ + + cl::opt<string> OutputFilename("o", cl::desc("Specify output filename"), cl::value_desc("filename")); + +This declares a global variable "``OutputFilename``" that is used to capture the +result of the "``o``" argument (first parameter). We specify that this is a +simple scalar option by using the "``cl::opt``" template (as opposed to the +"``cl::list``" template), and tell the CommandLine library that the data +type that we are parsing is a string. + +The second and third parameters (which are optional) are used to specify what to +output for the "``-help``" option. In this case, we get a line that looks like +this: + +:: + + USAGE: compiler [options] + + OPTIONS: + -help - display available options (-help-hidden for more) + -o <filename> - Specify output filename + +Because we specified that the command line option should parse using the +``string`` data type, the variable declared is automatically usable as a real +string in all contexts that a normal C++ string object may be used. For +example: + +.. code-block:: c++ + + ... + std::ofstream Output(OutputFilename.c_str()); + if (Output.good()) ... + ... + +There are many different options that you can use to customize the command line +option handling library, but the above example shows the general interface to +these options. The options can be specified in any order, and are specified +with helper functions like `cl::desc(...)`_, so there are no positional +dependencies to remember. The available options are discussed in detail in the +`Reference Guide`_. + +Continuing the example, we would like to have our compiler take an input +filename as well as an output filename, but we do not want the input filename to +be specified with a hyphen (ie, not ``-filename.c``). To support this style of +argument, the CommandLine library allows for `positional`_ arguments to be +specified for the program. These positional arguments are filled with command +line parameters that are not in option form. We use this feature like this: + +.. code-block:: c++ + + + cl::opt<string> InputFilename(cl::Positional, cl::desc("<input file>"), cl::init("-")); + +This declaration indicates that the first positional argument should be treated +as the input filename. Here we use the `cl::init`_ option to specify an initial +value for the command line option, which is used if the option is not specified +(if you do not specify a `cl::init`_ modifier for an option, then the default +constructor for the data type is used to initialize the value). Command line +options default to being optional, so if we would like to require that the user +always specify an input filename, we would add the `cl::Required`_ flag, and we +could eliminate the `cl::init`_ modifier, like this: + +.. code-block:: c++ + + cl::opt<string> InputFilename(cl::Positional, cl::desc("<input file>"), cl::Required); + +Again, the CommandLine library does not require the options to be specified in +any particular order, so the above declaration is equivalent to: + +.. code-block:: c++ + + cl::opt<string> InputFilename(cl::Positional, cl::Required, cl::desc("<input file>")); + +By simply adding the `cl::Required`_ flag, the CommandLine library will +automatically issue an error if the argument is not specified, which shifts all +of the command line option verification code out of your application into the +library. This is just one example of how using flags can alter the default +behaviour of the library, on a per-option basis. By adding one of the +declarations above, the ``-help`` option synopsis is now extended to: + +:: + + USAGE: compiler [options] <input file> + + OPTIONS: + -help - display available options (-help-hidden for more) + -o <filename> - Specify output filename + +... indicating that an input filename is expected. + +Boolean Arguments +----------------- + +In addition to input and output filenames, we would like the compiler example to +support three boolean flags: "``-f``" to force writing binary output to a +terminal, "``--quiet``" to enable quiet mode, and "``-q``" for backwards +compatibility with some of our users. We can support these by declaring options +of boolean type like this: + +.. code-block:: c++ + + cl::opt<bool> Force ("f", cl::desc("Enable binary output on terminals")); + cl::opt<bool> Quiet ("quiet", cl::desc("Don't print informational messages")); + cl::opt<bool> Quiet2("q", cl::desc("Don't print informational messages"), cl::Hidden); + +This does what you would expect: it declares three boolean variables +("``Force``", "``Quiet``", and "``Quiet2``") to recognize these options. Note +that the "``-q``" option is specified with the "`cl::Hidden`_" flag. This +modifier prevents it from being shown by the standard "``-help``" output (note +that it is still shown in the "``-help-hidden``" output). + +The CommandLine library uses a `different parser`_ for different data types. +For example, in the string case, the argument passed to the option is copied +literally into the content of the string variable... we obviously cannot do that +in the boolean case, however, so we must use a smarter parser. In the case of +the boolean parser, it allows no options (in which case it assigns the value of +true to the variable), or it allows the values "``true``" or "``false``" to be +specified, allowing any of the following inputs: + +:: + + compiler -f # No value, 'Force' == true + compiler -f=true # Value specified, 'Force' == true + compiler -f=TRUE # Value specified, 'Force' == true + compiler -f=FALSE # Value specified, 'Force' == false + +... you get the idea. The `bool parser`_ just turns the string values into +boolean values, and rejects things like '``compiler -f=foo``'. Similarly, the +`float`_, `double`_, and `int`_ parsers work like you would expect, using the +'``strtol``' and '``strtod``' C library calls to parse the string value into the +specified data type. + +With the declarations above, "``compiler -help``" emits this: + +:: + + USAGE: compiler [options] <input file> + + OPTIONS: + -f - Enable binary output on terminals + -o - Override output filename + -quiet - Don't print informational messages + -help - display available options (-help-hidden for more) + +and "``compiler -help-hidden``" prints this: + +:: + + USAGE: compiler [options] <input file> + + OPTIONS: + -f - Enable binary output on terminals + -o - Override output filename + -q - Don't print informational messages + -quiet - Don't print informational messages + -help - display available options (-help-hidden for more) + +This brief example has shown you how to use the '`cl::opt`_' class to parse +simple scalar command line arguments. In addition to simple scalar arguments, +the CommandLine library also provides primitives to support CommandLine option +`aliases`_, and `lists`_ of options. + +.. _aliases: + +Argument Aliases +---------------- + +So far, the example works well, except for the fact that we need to check the +quiet condition like this now: + +.. code-block:: c++ + + ... + if (!Quiet && !Quiet2) printInformationalMessage(...); + ... + +... which is a real pain! Instead of defining two values for the same +condition, we can use the "`cl::alias`_" class to make the "``-q``" option an +**alias** for the "``-quiet``" option, instead of providing a value itself: + +.. code-block:: c++ + + cl::opt<bool> Force ("f", cl::desc("Overwrite output files")); + cl::opt<bool> Quiet ("quiet", cl::desc("Don't print informational messages")); + cl::alias QuietA("q", cl::desc("Alias for -quiet"), cl::aliasopt(Quiet)); + +The third line (which is the only one we modified from above) defines a "``-q``" +alias that updates the "``Quiet``" variable (as specified by the `cl::aliasopt`_ +modifier) whenever it is specified. Because aliases do not hold state, the only +thing the program has to query is the ``Quiet`` variable now. Another nice +feature of aliases is that they automatically hide themselves from the ``-help`` +output (although, again, they are still visible in the ``-help-hidden output``). + +Now the application code can simply use: + +.. code-block:: c++ + + ... + if (!Quiet) printInformationalMessage(...); + ... + +... which is much nicer! The "`cl::alias`_" can be used to specify an +alternative name for any variable type, and has many uses. + +.. _unnamed alternatives using the generic parser: + +Selecting an alternative from a set of possibilities +---------------------------------------------------- + +So far we have seen how the CommandLine library handles builtin types like +``std::string``, ``bool`` and ``int``, but how does it handle things it doesn't +know about, like enums or '``int*``'s? + +The answer is that it uses a table-driven generic parser (unless you specify +your own parser, as described in the `Extension Guide`_). This parser maps +literal strings to whatever type is required, and requires you to tell it what +this mapping should be. + +Let's say that we would like to add four optimization levels to our optimizer, +using the standard flags "``-g``", "``-O0``", "``-O1``", and "``-O2``". We +could easily implement this with boolean options like above, but there are +several problems with this strategy: + +#. A user could specify more than one of the options at a time, for example, + "``compiler -O3 -O2``". The CommandLine library would not be able to catch + this erroneous input for us. + +#. We would have to test 4 different variables to see which ones are set. + +#. This doesn't map to the numeric levels that we want... so we cannot easily + see if some level >= "``-O1``" is enabled. + +To cope with these problems, we can use an enum value, and have the CommandLine +library fill it in with the appropriate level directly, which is used like this: + +.. code-block:: c++ + + enum OptLevel { + g, O1, O2, O3 + }; + + cl::opt<OptLevel> OptimizationLevel(cl::desc("Choose optimization level:"), + cl::values( + clEnumVal(g , "No optimizations, enable debugging"), + clEnumVal(O1, "Enable trivial optimizations"), + clEnumVal(O2, "Enable default optimizations"), + clEnumVal(O3, "Enable expensive optimizations"), + clEnumValEnd)); + + ... + if (OptimizationLevel >= O2) doPartialRedundancyElimination(...); + ... + +This declaration defines a variable "``OptimizationLevel``" of the +"``OptLevel``" enum type. This variable can be assigned any of the values that +are listed in the declaration (Note that the declaration list must be terminated +with the "``clEnumValEnd``" argument!). The CommandLine library enforces that +the user can only specify one of the options, and it ensure that only valid enum +values can be specified. The "``clEnumVal``" macros ensure that the command +line arguments matched the enum values. With this option added, our help output +now is: + +:: + + USAGE: compiler [options] <input file> + + OPTIONS: + Choose optimization level: + -g - No optimizations, enable debugging + -O1 - Enable trivial optimizations + -O2 - Enable default optimizations + -O3 - Enable expensive optimizations + -f - Enable binary output on terminals + -help - display available options (-help-hidden for more) + -o <filename> - Specify output filename + -quiet - Don't print informational messages + +In this case, it is sort of awkward that flag names correspond directly to enum +names, because we probably don't want a enum definition named "``g``" in our +program. Because of this, we can alternatively write this example like this: + +.. code-block:: c++ + + enum OptLevel { + Debug, O1, O2, O3 + }; + + cl::opt<OptLevel> OptimizationLevel(cl::desc("Choose optimization level:"), + cl::values( + clEnumValN(Debug, "g", "No optimizations, enable debugging"), + clEnumVal(O1 , "Enable trivial optimizations"), + clEnumVal(O2 , "Enable default optimizations"), + clEnumVal(O3 , "Enable expensive optimizations"), + clEnumValEnd)); + + ... + if (OptimizationLevel == Debug) outputDebugInfo(...); + ... + +By using the "``clEnumValN``" macro instead of "``clEnumVal``", we can directly +specify the name that the flag should get. In general a direct mapping is nice, +but sometimes you can't or don't want to preserve the mapping, which is when you +would use it. + +Named Alternatives +------------------ + +Another useful argument form is a named alternative style. We shall use this +style in our compiler to specify different debug levels that can be used. +Instead of each debug level being its own switch, we want to support the +following options, of which only one can be specified at a time: +"``--debug-level=none``", "``--debug-level=quick``", +"``--debug-level=detailed``". To do this, we use the exact same format as our +optimization level flags, but we also specify an option name. For this case, +the code looks like this: + +.. code-block:: c++ + + enum DebugLev { + nodebuginfo, quick, detailed + }; + + // Enable Debug Options to be specified on the command line + cl::opt<DebugLev> DebugLevel("debug_level", cl::desc("Set the debugging level:"), + cl::values( + clEnumValN(nodebuginfo, "none", "disable debug information"), + clEnumVal(quick, "enable quick debug information"), + clEnumVal(detailed, "enable detailed debug information"), + clEnumValEnd)); + +This definition defines an enumerated command line variable of type "``enum +DebugLev``", which works exactly the same way as before. The difference here is +just the interface exposed to the user of your program and the help output by +the "``-help``" option: + +:: + + USAGE: compiler [options] <input file> + + OPTIONS: + Choose optimization level: + -g - No optimizations, enable debugging + -O1 - Enable trivial optimizations + -O2 - Enable default optimizations + -O3 - Enable expensive optimizations + -debug_level - Set the debugging level: + =none - disable debug information + =quick - enable quick debug information + =detailed - enable detailed debug information + -f - Enable binary output on terminals + -help - display available options (-help-hidden for more) + -o <filename> - Specify output filename + -quiet - Don't print informational messages + +Again, the only structural difference between the debug level declaration and +the optimization level declaration is that the debug level declaration includes +an option name (``"debug_level"``), which automatically changes how the library +processes the argument. The CommandLine library supports both forms so that you +can choose the form most appropriate for your application. + +.. _lists: + +Parsing a list of options +------------------------- + +Now that we have the standard run-of-the-mill argument types out of the way, +lets get a little wild and crazy. Lets say that we want our optimizer to accept +a **list** of optimizations to perform, allowing duplicates. For example, we +might want to run: "``compiler -dce -constprop -inline -dce -strip``". In this +case, the order of the arguments and the number of appearances is very +important. This is what the "``cl::list``" template is for. First, start by +defining an enum of the optimizations that you would like to perform: + +.. code-block:: c++ + + enum Opts { + // 'inline' is a C++ keyword, so name it 'inlining' + dce, constprop, inlining, strip + }; + +Then define your "``cl::list``" variable: + +.. code-block:: c++ + + cl::list<Opts> OptimizationList(cl::desc("Available Optimizations:"), + cl::values( + clEnumVal(dce , "Dead Code Elimination"), + clEnumVal(constprop , "Constant Propagation"), + clEnumValN(inlining, "inline", "Procedure Integration"), + clEnumVal(strip , "Strip Symbols"), + clEnumValEnd)); + +This defines a variable that is conceptually of the type +"``std::vector<enum Opts>``". Thus, you can access it with standard vector +methods: + +.. code-block:: c++ + + for (unsigned i = 0; i != OptimizationList.size(); ++i) + switch (OptimizationList[i]) + ... + +... to iterate through the list of options specified. + +Note that the "``cl::list``" template is completely general and may be used with +any data types or other arguments that you can use with the "``cl::opt``" +template. One especially useful way to use a list is to capture all of the +positional arguments together if there may be more than one specified. In the +case of a linker, for example, the linker takes several '``.o``' files, and +needs to capture them into a list. This is naturally specified as: + +.. code-block:: c++ + + ... + cl::list<std::string> InputFilenames(cl::Positional, cl::desc("<Input files>"), cl::OneOrMore); + ... + +This variable works just like a "``vector<string>``" object. As such, accessing +the list is simple, just like above. In this example, we used the +`cl::OneOrMore`_ modifier to inform the CommandLine library that it is an error +if the user does not specify any ``.o`` files on our command line. Again, this +just reduces the amount of checking we have to do. + +Collecting options as a set of flags +------------------------------------ + +Instead of collecting sets of options in a list, it is also possible to gather +information for enum values in a **bit vector**. The representation used by the +`cl::bits`_ class is an ``unsigned`` integer. An enum value is represented by a +0/1 in the enum's ordinal value bit position. 1 indicating that the enum was +specified, 0 otherwise. As each specified value is parsed, the resulting enum's +bit is set in the option's bit vector: + +.. code-block:: c++ + + bits |= 1 << (unsigned)enum; + +Options that are specified multiple times are redundant. Any instances after +the first are discarded. + +Reworking the above list example, we could replace `cl::list`_ with `cl::bits`_: + +.. code-block:: c++ + + cl::bits<Opts> OptimizationBits(cl::desc("Available Optimizations:"), + cl::values( + clEnumVal(dce , "Dead Code Elimination"), + clEnumVal(constprop , "Constant Propagation"), + clEnumValN(inlining, "inline", "Procedure Integration"), + clEnumVal(strip , "Strip Symbols"), + clEnumValEnd)); + +To test to see if ``constprop`` was specified, we can use the ``cl:bits::isSet`` +function: + +.. code-block:: c++ + + if (OptimizationBits.isSet(constprop)) { + ... + } + +It's also possible to get the raw bit vector using the ``cl::bits::getBits`` +function: + +.. code-block:: c++ + + unsigned bits = OptimizationBits.getBits(); + +Finally, if external storage is used, then the location specified must be of +**type** ``unsigned``. In all other ways a `cl::bits`_ option is equivalent to a +`cl::list`_ option. + +.. _additional extra text: + +Adding freeform text to help output +----------------------------------- + +As our program grows and becomes more mature, we may decide to put summary +information about what it does into the help output. The help output is styled +to look similar to a Unix ``man`` page, providing concise information about a +program. Unix ``man`` pages, however often have a description about what the +program does. To add this to your CommandLine program, simply pass a third +argument to the `cl::ParseCommandLineOptions`_ call in main. This additional +argument is then printed as the overview information for your program, allowing +you to include any additional information that you want. For example: + +.. code-block:: c++ + + int main(int argc, char **argv) { + cl::ParseCommandLineOptions(argc, argv, " CommandLine compiler example\n\n" + " This program blah blah blah...\n"); + ... + } + +would yield the help output: + +:: + + **OVERVIEW: CommandLine compiler example + + This program blah blah blah...** + + USAGE: compiler [options] <input file> + + OPTIONS: + ... + -help - display available options (-help-hidden for more) + -o <filename> - Specify output filename + +.. _Reference Guide: + +Reference Guide +=============== + +Now that you know the basics of how to use the CommandLine library, this section +will give you the detailed information you need to tune how command line options +work, as well as information on more "advanced" command line option processing +capabilities. + +.. _positional: +.. _positional argument: +.. _Positional Arguments: +.. _Positional arguments section: +.. _positional options: + +Positional Arguments +-------------------- + +Positional arguments are those arguments that are not named, and are not +specified with a hyphen. Positional arguments should be used when an option is +specified by its position alone. For example, the standard Unix ``grep`` tool +takes a regular expression argument, and an optional filename to search through +(which defaults to standard input if a filename is not specified). Using the +CommandLine library, this would be specified as: + +.. code-block:: c++ + + cl::opt<string> Regex (cl::Positional, cl::desc("<regular expression>"), cl::Required); + cl::opt<string> Filename(cl::Positional, cl::desc("<input file>"), cl::init("-")); + +Given these two option declarations, the ``-help`` output for our grep +replacement would look like this: + +:: + + USAGE: spiffygrep [options] <regular expression> <input file> + + OPTIONS: + -help - display available options (-help-hidden for more) + +... and the resultant program could be used just like the standard ``grep`` +tool. + +Positional arguments are sorted by their order of construction. This means that +command line options will be ordered according to how they are listed in a .cpp +file, but will not have an ordering defined if the positional arguments are +defined in multiple .cpp files. The fix for this problem is simply to define +all of your positional arguments in one .cpp file. + +Specifying positional options with hyphens +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +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: + +:: + + $ spiffygrep '-foo' test.txt + Unknown command line argument '-foo'. Try: spiffygrep -help' + + $ grep '-foo' test.txt + grep: illegal option -- f + 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 +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: + +:: + + $ spiffygrep -- -foo test.txt + ...output... + +Determining absolute position with getPosition() +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Sometimes an option can affect or modify the meaning of another option. For +example, consider ``gcc``'s ``-x LANG`` option. This tells ``gcc`` to ignore the +suffix of subsequent positional arguments and force the file to be interpreted +as if it contained source code in language ``LANG``. In order to handle this +properly, you need to know the absolute position of each argument, especially +those in lists, so their interaction(s) can be applied correctly. This is also +useful for options like ``-llibname`` which is actually a positional argument +that starts with a dash. + +So, generally, the problem is that you have two ``cl::list`` variables that +interact in some way. To ensure the correct interaction, you can use the +``cl::list::getPosition(optnum)`` method. This method returns the absolute +position (as found on the command line) of the ``optnum`` item in the +``cl::list``. + +The idiom for usage is like this: + +.. code-block:: c++ + + static cl::list<std::string> Files(cl::Positional, cl::OneOrMore); + static cl::list<std::string> Libraries("l", cl::ZeroOrMore); + + int main(int argc, char**argv) { + // ... + std::vector<std::string>::iterator fileIt = Files.begin(); + std::vector<std::string>::iterator libIt = Libraries.begin(); + unsigned libPos = 0, filePos = 0; + while ( 1 ) { + if ( libIt != Libraries.end() ) + libPos = Libraries.getPosition( libIt - Libraries.begin() ); + else + libPos = 0; + if ( fileIt != Files.end() ) + filePos = Files.getPosition( fileIt - Files.begin() ); + else + filePos = 0; + + if ( filePos != 0 && (libPos == 0 || filePos < libPos) ) { + // Source File Is next + ++fileIt; + } + else if ( libPos != 0 && (filePos == 0 || libPos < filePos) ) { + // Library is next + ++libIt; + } + else + break; // we're done with the list + } + } + +Note that, for compatibility reasons, the ``cl::opt`` also supports an +``unsigned getPosition()`` option that will provide the absolute position of +that option. You can apply the same approach as above with a ``cl::opt`` and a +``cl::list`` option as you can with two lists. + +.. _interpreter style options: +.. _cl::ConsumeAfter: +.. _this section for more information: + +The ``cl::ConsumeAfter`` modifier +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +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. + +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: + +.. code-block:: c++ + + 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: + +:: + + USAGE: spiffysh [options] <input script> <program arguments>... + + OPTIONS: + -help - display available options (-help-hidden for more) + -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 ``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). + +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, there must +not be any `cl::list`_ positional arguments, and the ``cl::ConsumeAfter`` option +should be a `cl::list`_ option. + +.. _can be changed: +.. _Internal vs External Storage: + +Internal vs External Storage +---------------------------- + +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. + +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 accessible (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``). + +To do this, set up your .h file with your option, like this for example: + +.. code-block:: c++ + + // DebugFlag.h - Get access to the '-debug' command line option + // + + // DebugFlag - This boolean is set to true if the '-debug' command line option + // is specified. This should probably not be referenced directly, instead, use + // the DEBUG macro below. + // + extern bool DebugFlag; + + // DEBUG macro - This macro should be used by code to emit debug information. + // In the '-debug' option is specified on the command line, and if this is a + // debug build, then the code specified as the option to the macro will be + // executed. Otherwise it will not be. + #ifdef NDEBUG + #define DEBUG(X) + #else + #define DEBUG(X) do { if (DebugFlag) { X; } } while (0) + #endif + +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 +additional argument to our command line argument processor, and we specify where +to fill in with the `cl::location`_ attribute: + +.. code-block:: c++ + + bool DebugFlag; // the actual value + static cl::opt<bool, true> // The parser + Debug("debug", cl::desc("Enable debug output"), cl::Hidden, cl::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 `cl::location`_ +attribute, so that ``DebugFlag`` is automatically set. + +Option Attributes +----------------- + +This section describes the basic attributes that you can specify on options. + +* The option name attribute (which is required for all options, except + `positional options`_) specifies what the option name is. This option is + specified in simple double quotes: + + .. code-block:: c++ + + cl::opt<**bool**> Quiet("quiet"); + +.. _cl::desc(...): + +* The **cl::desc** attribute specifies a description for the option to be + shown in the ``-help`` output for the program. + +.. _cl::value_desc: + +* The **cl::value_desc** attribute specifies a string that can be used to + fine tune the ``-help`` output for a command line option. Look `here`_ for an + example. + +.. _cl::init: + +* The **cl::init** attribute specifies an initial value for a `scalar`_ + option. If this attribute is not specified then the command line option value + defaults to the value created by the default constructor for the + type. + + .. warning:: + + If you specify both **cl::init** and **cl::location** for an option, you + must specify **cl::location** first, so that when the command-line parser + sees **cl::init**, it knows where to put the initial value. (You will get an + error at runtime if you don't put them in the right order.) + +.. _cl::location: + +* The **cl::location** attribute where to store the value for a parsed command + line option if using external storage. See the section on `Internal vs + External Storage`_ for more information. + +.. _cl::aliasopt: + +* The **cl::aliasopt** attribute specifies which option a `cl::alias`_ option is + an alias for. + +.. _cl::values: + +* The **cl::values** attribute specifies the string-to-value mapping to be used + by the generic parser. It takes a **clEnumValEnd terminated** list of + (option, value, description) triplets that specify the option name, the value + mapped to, and the description shown in the ``-help`` for the tool. Because |