ENH: support option aliases with versioning

- can be used for adjusting option names between versions
This commit is contained in:
Mark Olesen 2017-11-22 14:42:31 +01:00
parent 416a3790ea
commit aa112c3f26
6 changed files with 200 additions and 76 deletions

View File

@ -38,12 +38,24 @@ int main(int argc, char *argv[])
{ {
argList::noBanner(); argList::noBanner();
argList::noParallel(); argList::noParallel();
argList::noFunctionObjects(); // argList::noFunctionObjects();
argList::removeOption("case"); argList::removeOption("case");
argList::addOption("label", "value", "Test parsing of label"); argList::addOption("label", "value", "Test parsing of label");
argList::addOption("scalar", "value", "Test parsing of scalar"); argList::addOption("scalar", "value", "Test parsing of scalar");
// These are actually lies (never had -parseLabel, -parseScalar etc),
// but good for testing...
// Emits warning about it being old
argList::addOptionCompat("label", {"parseLabel", 1612});
// Specifying version=0 to use alias without any warnings
argList::addOptionCompat("scalar", {"parseScalar", 0});
// Fake a future option...
argList::addOptionCompat("label", {"parse-label", 2112});
argList args(argc, argv); argList args(argc, argv);
label ival; label ival;

View File

@ -25,36 +25,6 @@ License
#include "dictionary.H" #include "dictionary.H"
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
static void warnAboutAge(const int oldVersion)
{
if (oldVersion < 1000)
{
// Emit warning
std::cerr
<< " This keyword is considered to be VERY old!\n"
<< std::endl;
}
#if (OPENFOAM_PLUS > 1600)
else if (OPENFOAM_PLUS > oldVersion)
{
const int months =
(
// YYMM -> months
(12 * (OPENFOAM_PLUS/100) + (OPENFOAM_PLUS % 100))
- (12 * (oldVersion/100) + (oldVersion % 100))
);
std::cerr
<< " This keyword is deemed to be " << months
<< " months old.\n"
<< std::endl;
}
#endif
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::dictionary::const_searcher Foam::dictionary::csearchCompat Foam::dictionary::const_searcher Foam::dictionary::csearchCompat
@ -78,17 +48,20 @@ Foam::dictionary::const_searcher Foam::dictionary::csearchCompat
if (finder.found()) if (finder.found())
{ {
// Emit warning if (iter.second)
std::cerr {
<< "--> FOAM IOWarning :" << nl // Emit warning, but only if version (non-zero) was provided
<< " Found [v" << iter.second << "] '" std::cerr
<< iter.first << "' instead of '" << "--> FOAM IOWarning :" << nl
<< keyword.c_str() << "' in dictionary \"" << " Found [v" << iter.second << "] '"
<< name().c_str() << "\" " << iter.first << "' instead of '"
<< nl << keyword.c_str() << "' in dictionary \""
<< std::endl; << name().c_str() << "\" "
<< nl
<< std::endl;
warnAboutAge(iter.second); error::warnAboutAge("keyword", iter.second);
}
break; break;
} }

View File

@ -31,6 +31,44 @@ License
#include "Pstream.H" #include "Pstream.H"
#include "OSspecific.H" #include "OSspecific.H"
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
void Foam::error::warnAboutAge
(
const char* what,
const int oldVersion
)
{
if (oldVersion < 1000)
{
// Emit warning
std::cerr
<< " This " << what << " is considered to be VERY old!\n"
<< std::endl;
}
else if (OPENFOAM_PLUS > oldVersion)
{
const int months =
(
// YYMM -> months
(12 * (OPENFOAM_PLUS/100) + (OPENFOAM_PLUS % 100))
- (12 * (oldVersion/100) + (oldVersion % 100))
);
std::cerr
<< " This " << what << " is deemed to be " << months
<< " months old.\n"
<< std::endl;
}
///// Uncertain if this is desirable
/// else if (OPENFOAM_PLUS < oldVersion)
/// {
/// std::cerr
/// << " This " << what << " appears to be a future option\n"
/// << std::endl;
/// }
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //

View File

@ -100,6 +100,15 @@ public:
virtual ~error() throw(); virtual ~error() throw();
// Static Member Functions
//- Emit warning on stderr about something being old.
// \param what description for the warning
// \param oldVersion is a YYMM version value for determining the
// age in months.
static void warnAboutAge(const char* what, const int oldVersion);
// Member functions // Member functions
string message() const; string message() const;

View File

@ -54,6 +54,7 @@ Foam::SLList<Foam::string> Foam::argList::validArgs;
Foam::HashTable<Foam::string> Foam::argList::validOptions; Foam::HashTable<Foam::string> Foam::argList::validOptions;
Foam::HashTable<Foam::string> Foam::argList::validParOptions; Foam::HashTable<Foam::string> Foam::argList::validParOptions;
Foam::HashTable<Foam::string> Foam::argList::optionUsage; Foam::HashTable<Foam::string> Foam::argList::optionUsage;
Foam::HashTable<std::pair<Foam::word,int>> Foam::argList::validOptionsCompat;
Foam::SLList<Foam::string> Foam::argList::notes; Foam::SLList<Foam::string> Foam::argList::notes;
Foam::string::size_type Foam::argList::usageMin = 20; Foam::string::size_type Foam::argList::usageMin = 20;
Foam::string::size_type Foam::argList::usageMax = 80; Foam::string::size_type Foam::argList::usageMax = 80;
@ -97,7 +98,13 @@ Foam::argList::initValidTables::initValidTables()
"fileHandler", "fileHandler",
"handler", "handler",
"override the fileHandler" "override the fileHandler"
); );
// Some standard option aliases (with or without version warnings)
// argList::addOptionCompat
// (
// "noFunctionObjects", {"no-function-objects", 0 }
// );
Pstream::addValidParOptions(validParOptions); Pstream::addValidParOptions(validParOptions);
} }
@ -152,6 +159,7 @@ static void printHostsSubscription(const UList<string>& slaveProcs)
} }
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * // // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
void Foam::argList::addArgument(const string& argumentName) void Foam::argList::addArgument(const string& argumentName)
@ -185,6 +193,20 @@ void Foam::argList::addOption
} }
void Foam::argList::addOptionCompat
(
const word& optionName,
std::pair<const char*,int> compat
)
{
validOptionsCompat.insert
(
compat.first,
std::pair<word,int>(optionName, compat.second)
);
}
void Foam::argList::addUsage void Foam::argList::addUsage
( (
const word& opt, const word& opt,
@ -388,57 +410,106 @@ bool Foam::argList::postProcess(int argc, char *argv[])
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
Foam::word Foam::argList::optionCompat(const word& optionName)
{
if (!validOptionsCompat.empty())
{
auto canonical = validOptionsCompat.cfind(optionName.substr(1));
if (canonical.found())
{
const auto& iter = *canonical;
if (iter.second)
{
// Emit warning, but only if version (non-zero) was provided
std::cerr
<< "--> FOAM IOWarning :" << nl
<< " Found [v" << iter.second << "] '"
<< optionName << "' instead of '-"
<< iter.first << "' option"
<< nl
<< std::endl;
error::warnAboutAge("option", iter.second);
}
return "-" + iter.first;
}
}
// Nothing found - pass through the original input
return optionName;
}
bool Foam::argList::regroupArgv(int& argc, char**& argv) bool Foam::argList::regroupArgv(int& argc, char**& argv)
{ {
int nArgs = 1; int nArgs = 1;
unsigned listDepth = 0; unsigned depth = 0;
string tmpString; string group; // For grouping ( ... ) arguments
// Note: we rewrite directly into args_ // Note: we rewrite directly into args_
// and use a second pass to sort out args/options // and use a second pass to sort out args/options
args_[0] = fileName(argv[0]); args_[0] = fileName(argv[0]);
for (int argI = 1; argI < argc; ++argI) for (int argi = 1; argi < argc; ++argi)
{ {
if (strcmp(argv[argI], "(") == 0) if (strcmp(argv[argi], "(") == 0)
{ {
++listDepth; ++depth;
tmpString += "("; group += '(';
} }
else if (strcmp(argv[argI], ")") == 0) else if (strcmp(argv[argi], ")") == 0)
{ {
if (listDepth) if (depth)
{ {
--listDepth; --depth;
tmpString += ")"; group += ')';
if (!listDepth) if (!depth)
{ {
args_[nArgs++] = tmpString; args_[nArgs++] = group;
tmpString.clear(); group.clear();
} }
} }
else else
{ {
args_[nArgs++] = argv[argI]; args_[nArgs++] = argv[argi];
} }
} }
else if (listDepth) else if (depth)
{ {
// Quote each string element // Quote each string element
tmpString += "\""; group += '"';
tmpString += argv[argI]; group += argv[argi];
tmpString += "\""; group += '"';
}
else if (argv[argi][0] == '-')
{
// Appears to be an option
const char *optionName = &argv[argi][1];
if (validOptions.found(optionName))
{
// Known option name
args_[nArgs++] = argv[argi];
}
else
{
// Try alias for the option name
args_[nArgs++] = optionCompat(argv[argi]);
}
} }
else else
{ {
args_[nArgs++] = argv[argI]; args_[nArgs++] = argv[argi];
} }
} }
if (tmpString.size()) if (group.size())
{ {
// Group(s) not closed, but flush anything still pending // Group(s) not closed, but flush anything still pending
args_[nArgs++] = tmpString; args_[nArgs++] = group;
} }
args_.setSize(nArgs); args_.setSize(nArgs);
@ -530,11 +601,11 @@ Foam::argList::argList
{ {
// Check if this run is a parallel run by searching for any parallel option // Check if this run is a parallel run by searching for any parallel option
// If found call runPar which might filter argv // If found call runPar which might filter argv
for (int argI = 1; argI < argc; ++argI) for (int argi = 1; argi < argc; ++argi)
{ {
if (argv[argI][0] == '-') if (argv[argi][0] == '-')
{ {
const char *optionName = &argv[argI][1]; const char *optionName = &argv[argi][1];
if (validParOptions.found(optionName)) if (validParOptions.found(optionName))
{ {
@ -551,14 +622,14 @@ Foam::argList::argList
// Check arguments and options, argv[0] was already handled // Check arguments and options, argv[0] was already handled
int nArgs = 1; int nArgs = 1;
HashTable<string>::const_iterator optIter; HashTable<string>::const_iterator optIter;
for (int argI = 1; argI < args_.size(); ++argI) for (int argi = 1; argi < args_.size(); ++argi)
{ {
argListStr_ += ' '; argListStr_ += ' ';
argListStr_ += args_[argI]; argListStr_ += args_[argi];
if (args_[argI][0] == '-') if (args_[argi][0] == '-')
{ {
const char *optionName = &args_[argI][1]; const char *optionName = &args_[argi][1];
if (!*optionName) if (!*optionName)
{ {
@ -580,8 +651,8 @@ Foam::argList::argList
// If the option is known to require an argument, // If the option is known to require an argument,
// get it or emit a FatalError. // get it or emit a FatalError.
++argI; ++argi;
if (argI >= args_.size()) if (argi >= args_.size())
{ {
FatalError FatalError
<<"Option '-" << optionName <<"Option '-" << optionName
@ -591,9 +662,9 @@ Foam::argList::argList
} }
argListStr_ += ' '; argListStr_ += ' ';
argListStr_ += args_[argI]; argListStr_ += args_[argi];
// Handle duplicates by taking the last -option specified // Handle duplicates by taking the last -option specified
options_.set(optionName, args_[argI]); options_.set(optionName, args_[argi]);
} }
else else
{ {
@ -605,9 +676,9 @@ Foam::argList::argList
} }
else else
{ {
if (nArgs != argI) if (nArgs != argi)
{ {
args_[nArgs] = args_[argI]; args_[nArgs] = args_[argi];
} }
++nArgs; ++nArgs;
} }

View File

@ -103,6 +103,7 @@ SourceFiles
#include "parRun.H" #include "parRun.H"
#include "StringStream.H" #include "StringStream.H"
#include "OSspecific.H" #include "OSspecific.H"
#include <utility>
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -146,6 +147,9 @@ class argList
// Private Member Functions // Private Member Functions
//- Helper for resolving aliases for -options within validOptionsCompat
static word optionCompat(const word& optionName);
//- Helper function for printUsage //- Helper function for printUsage
static void printOptionUsage static void printOptionUsage
( (
@ -181,6 +185,10 @@ public:
//- A list of valid parallel options //- A list of valid parallel options
static HashTable<string> validParOptions; static HashTable<string> validParOptions;
//- A list of aliases for options.
// Stored as (alias = canonical, version)
static HashTable<std::pair<word,int>> validOptionsCompat;
//- Short usage information for validOptions //- Short usage information for validOptions
static HashTable<string> optionUsage; static HashTable<string> optionUsage;
@ -369,6 +377,19 @@ public:
const string& usage = "" const string& usage = ""
); );
//- Add an alias for the optionName.
//
// \param optionName the currently used option name
// OpenFOAM version for which they were used.
// \param compat alias name and the last OpenFOAM version
// (YYMM) for when the alias was not needed.
// Setting a version of 0 suppresses warnings about the alias.
static void addOptionCompat
(
const word& optionName,
std::pair<const char*, int> compat
);
//- Add option usage information to optionUsage //- Add option usage information to optionUsage
static void addUsage static void addUsage
( (