ProgOptions is a component for handling of program command string options.
Using ProgOptions it is possible to simply implement following facilities:
--a Oh
syntax for "a" option with "Oh" argument is valid as well as the
--a="Say Oh"
syntax for the same option with another "Say Oh" argument;
This document is a non-formal description of package, the full specification is present in
API reference.
(www.gradsoft.kiev.ua/common/ToolBox/ProgOptions/API/index.html).
The "basic" way of ProgOption usage is suitable for the case of command line accessble through the pair (argc,argv) with personnels determined as (int) and (char**) obtained through the "main" function arguments. If this case is present, obtaining of ProgOptions functionality needs following steps:
ProgOptions::ProgOptions(const char* optPrefix="-", const char* pkgPrefix="", bool allowUnknownOptions=false);
where
ProgOptions::is_set("option") you can check option setting.
For options with argument you can read value of argument by using
ProgOptions::argument("option")
Example:
#include <GradSoft/ProgOptions.h> // first step
GradSoft::ProgOptions options; // construct a new instance of ProgOptions:
void init()
{
options.put("qqq", "qqq option", false ); // discribe the option "qqq"
// which not need arguments
options.put("zzz", "option with argument", true ); // discribe the option "zzz"
// which need an argument
options.setAdditionalHelp(true, //
"This program illustate usage of GradSoft library"// set additional help messages
); //
options.setAdditionalHelp(false, //
"and this is shown at the end of usage screen" //
); //
};
int main(int argc, char** argv)
{
init();
if (!options.parse(argc,argv)) return 1; // parse options
if (options.is_set("qqq")) { // find out, is the option seted
cout << "qqq is set" << endl;
}
// find out, is the option seted
// and get his argument if yes
if (options.is_set("zzz")) {
cout << "zzz is set with argument:" << options.argument("zzz") << endl;
}
return 0;
}
Now run this program:
./a.out --qqq --zzz zz-arg qqq is set zzz is set with argument:zz-arg
And now run with option not described:
./a.out --Go a:Go:unknown option
In addition to set of options, described by programmer, ProgOptions define
two specially acting options: --<pkgPrefix>help and --<pkg>config.
The result of calling program with option --<pkgPrefix>help is passing
to stdandart error stream (cerr) a standard help message (which is the list of options
with descriptions inputted on the step of using ProgOptions::put) added by additional
help messages specified via ProgOptions::setAdditionalHelp.
The result of calling program with --<pkg>config fname is parsing options described
in the file <fname> (see next section 4.1 for more details).
Example:
Start program mentioned with option --help::
./a.out --help This program illustate usage of ProgOptions library --qqq qqq option --zzz <argument> option with argument and this is shown at the end of usage screen
Note:
Using --config <filename> leads to some troubles for us
when some part of options must be passed into "external" software,
let us, into function ORB_init().
The point is that the ProgOptions::parse(argc,argv) method merge all options,
given in argv vector and extracted from the file
in especial argument vector being used then, and do not change starting argv.
Therefore, if you call ORB_init() with argc and argv being parameters of main(),
options from the file will be lost.
Therefore, if you want to pass command-line options from the file into ORB_init() really,
you must:
ProgOptions options("--","",true);
if (!options.parse(argc,argv)) return 1;
ProgOptions::ArgsHolder argsHolder;
argsHolder.takeArgv(options);
CORBA::ORB_var orb = CORBA::ORB_init(argsHolder.argc,argsHolder.argv);
It is handly, because new argv created via argsHolder::takeArgv(const ProgOptions&)
will be deleted automatically when destructor of argsHolder will be called.
Note: to date, syntax --config=<filename> do not possible
for special option --config. Use --config=<filename> instead.
You can overload special option --help and --config
using method ProgOption::put. Overloaded option has no feature and default action.
Yet one way of handling options handling: callback functions. You can specify
such function in parameter |callback| of method ProgOptions::put and
it will be called during parsing appropriate option.
To illustrate this, let's add to our program next piece of code:
bool zz1Callback(const GradSoft::ProgOptions* options, const char* argument,
void* )
{
cout << "zz1:callback called with argument " <<
((!argument) ? "NULL" : argument) << endl;
return true;
}
void init()
{
.....
options.put("zz1", "option with argument and callback", true, zz1Callback );
};
Now run program with this option:
/a.out --zz1 xx zz1:callback called with argument xx
Callback function is called during each occurence of option in command string, so you can organize handling of few identical options.
/a.out --zz1 xx --zz1 yy zz1:callback called with argument xx zz1:callback called with argument yy
<optPrefix><pkgPrefix><optionName>.
-- and empty string accordinally
ProgOptions::setAllowUnknownOptions(bool);
bool ProgOptions::getAllowUnknownOptions()
As it will be mentioned above, if you use ProgOptions::parse in you program,
it will lead to options described in the file fname will be parsed
if the end user of program apply --config fname in the command line.
The additional possibility is that: you may read options from file and parse them independently of end user choice using special method ProgOptions::parseFile(const char* configFname, const char* executable="unspecified"). For example, calling
options.parseFile("D:\Demo\config.ini");
(where options is instance of ProgOptions)
means that the text in the D:\Demo\config.ini will be readed, parts of text
recognized as "options" will be extracted and then interpreted as well as
these options be in command line. (Second parameter of this method constitutes the name
of the program asking for options and is optional: you may set it
in the case of call of ProgOptions::parse not precede the call of ProgOptions::parseFile.)
The next mean allow you to combine all option parsed by ProgOptions::parse,
ProgOptions::parseFile and ProgOptions::parseString (see following for the latter)
and save these into the file specified using method
ProgOptions::saveToFile.
For example, using
ProgOptions options;
...
options.parse(argc,argv);
...
options.parseFile("D:\Demo\config.ini");
...
options.saveToFile("D:\Democonfig1.ini");
in continuous block leads to all options gotten by argv and readed from the file
D:\Demo\config.ini (either recognized and not recognized) will be saved in formatted
file D:\Demo\config1.ini, and will be obtained again if programmer use ProgOptions::parseFile.
It is important:
Bouth ProgOptions::parseFile and ProgOptions::saveToFile methods return boolean value, which indicate success or unsuccess of operatuion. In the case of ProgOptions::saveToFile, if the method return false, than the system error has been occured and error information is aviable via operation system errno interface. Thus, the standard code fragment for storing options in file looks like the next example:
if (!optios.saveToFile(configFname)) {
perror(options.argv(0));
....
}
....
In the case of ProgOptions::parseFile the precidence rule analogous is not valid because ProgOptions::parseFile return false in few different cases:
The file to parse must been formatted:
Example:
aaa_bbb "aaa bbb" aaa" bbb ccc"will be interpreted as three separate words
'aaa_bbb', 'aaa bbb' and 'aaa bbb ccc'
'/*' and '*/' and every characters standing between them;
'//' and part of string after it;
'#'.
Examples:
# This string will be ignored aaa /* This part of string will be ignored */ bbb ccc // This part of string will be ignored too
\"'.
The trivial example which illustrate the structure of ProgOptions config file is follow:
@"ProgOptions config file"
# The list of options:
--a /* single option */
--b c // option with argument
--d="a b c" // another option with argument
The next additional possibility is that you may parse the string in C-style
with result the same as string has been readed from file.
The methodv ProgOptions::parseFile(const char* configFname, const char* executable="unspecified") do it.
The small difference in acting of ProgOptions::parseFile and ProgOptions::parseString methods
is that the file marker '@ProgOptions Config File' and symbol '#' at the begining of string
must not have and have any special sence in latter case.
Using Progoptions on Windows NT, you must:
--config <filename> option described
--config=<filename> syntax
for non-overloaded option --config added.
GradSoft/ProgOptions don't used from date);