From aa112c3f26d45a5dc8ecfeb659da4bb8071d2550 Mon Sep 17 00:00:00 2001 From: Mark Olesen Date: Wed, 22 Nov 2017 14:42:31 +0100 Subject: [PATCH] ENH: support option aliases with versioning - can be used for adjusting option names between versions --- applications/test/argList/Test-argList.C | 14 +- src/OpenFOAM/db/dictionary/dictionaryCompat.C | 53 ++----- src/OpenFOAM/db/error/error.C | 38 +++++ src/OpenFOAM/db/error/error.H | 9 ++ src/OpenFOAM/global/argList/argList.C | 141 +++++++++++++----- src/OpenFOAM/global/argList/argList.H | 21 +++ 6 files changed, 200 insertions(+), 76 deletions(-) diff --git a/applications/test/argList/Test-argList.C b/applications/test/argList/Test-argList.C index 50763f15af..e885ff9fb0 100644 --- a/applications/test/argList/Test-argList.C +++ b/applications/test/argList/Test-argList.C @@ -38,12 +38,24 @@ int main(int argc, char *argv[]) { argList::noBanner(); argList::noParallel(); - argList::noFunctionObjects(); + // argList::noFunctionObjects(); argList::removeOption("case"); argList::addOption("label", "value", "Test parsing of label"); 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); label ival; diff --git a/src/OpenFOAM/db/dictionary/dictionaryCompat.C b/src/OpenFOAM/db/dictionary/dictionaryCompat.C index 624231fd14..4d865a1468 100644 --- a/src/OpenFOAM/db/dictionary/dictionaryCompat.C +++ b/src/OpenFOAM/db/dictionary/dictionaryCompat.C @@ -25,36 +25,6 @@ License #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 * * * * * * * * * * * * * // Foam::dictionary::const_searcher Foam::dictionary::csearchCompat @@ -78,17 +48,20 @@ Foam::dictionary::const_searcher Foam::dictionary::csearchCompat if (finder.found()) { - // Emit warning - std::cerr - << "--> FOAM IOWarning :" << nl - << " Found [v" << iter.second << "] '" - << iter.first << "' instead of '" - << keyword.c_str() << "' in dictionary \"" - << name().c_str() << "\" " - << nl - << std::endl; + if (iter.second) + { + // Emit warning, but only if version (non-zero) was provided + std::cerr + << "--> FOAM IOWarning :" << nl + << " Found [v" << iter.second << "] '" + << iter.first << "' instead of '" + << keyword.c_str() << "' in dictionary \"" + << name().c_str() << "\" " + << nl + << std::endl; - warnAboutAge(iter.second); + error::warnAboutAge("keyword", iter.second); + } break; } diff --git a/src/OpenFOAM/db/error/error.C b/src/OpenFOAM/db/error/error.C index d72835e175..42a63d30f6 100644 --- a/src/OpenFOAM/db/error/error.C +++ b/src/OpenFOAM/db/error/error.C @@ -31,6 +31,44 @@ License #include "Pstream.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 * * * * * * * * * * * * * * // diff --git a/src/OpenFOAM/db/error/error.H b/src/OpenFOAM/db/error/error.H index bf59c5facb..5674df7a69 100644 --- a/src/OpenFOAM/db/error/error.H +++ b/src/OpenFOAM/db/error/error.H @@ -100,6 +100,15 @@ public: 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 string message() const; diff --git a/src/OpenFOAM/global/argList/argList.C b/src/OpenFOAM/global/argList/argList.C index 0b64d229e3..2001bb0a84 100644 --- a/src/OpenFOAM/global/argList/argList.C +++ b/src/OpenFOAM/global/argList/argList.C @@ -54,6 +54,7 @@ Foam::SLList Foam::argList::validArgs; Foam::HashTable Foam::argList::validOptions; Foam::HashTable Foam::argList::validParOptions; Foam::HashTable Foam::argList::optionUsage; +Foam::HashTable> Foam::argList::validOptionsCompat; Foam::SLList Foam::argList::notes; Foam::string::size_type Foam::argList::usageMin = 20; Foam::string::size_type Foam::argList::usageMax = 80; @@ -97,7 +98,13 @@ Foam::argList::initValidTables::initValidTables() "fileHandler", "handler", "override the fileHandler" - ); + ); + + // Some standard option aliases (with or without version warnings) +// argList::addOptionCompat +// ( +// "noFunctionObjects", {"no-function-objects", 0 } +// ); Pstream::addValidParOptions(validParOptions); } @@ -152,6 +159,7 @@ static void printHostsSubscription(const UList& slaveProcs) } + // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * // void Foam::argList::addArgument(const string& argumentName) @@ -185,6 +193,20 @@ void Foam::argList::addOption } +void Foam::argList::addOptionCompat +( + const word& optionName, + std::pair compat +) +{ + validOptionsCompat.insert + ( + compat.first, + std::pair(optionName, compat.second) + ); +} + + void Foam::argList::addUsage ( const word& opt, @@ -388,57 +410,106 @@ bool Foam::argList::postProcess(int argc, char *argv[]) // * * * * * * * * * * * * * 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) { int nArgs = 1; - unsigned listDepth = 0; - string tmpString; + unsigned depth = 0; + string group; // For grouping ( ... ) arguments // Note: we rewrite directly into args_ // and use a second pass to sort out args/options 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; - tmpString += "("; + ++depth; + group += '('; } - else if (strcmp(argv[argI], ")") == 0) + else if (strcmp(argv[argi], ")") == 0) { - if (listDepth) + if (depth) { - --listDepth; - tmpString += ")"; - if (!listDepth) + --depth; + group += ')'; + if (!depth) { - args_[nArgs++] = tmpString; - tmpString.clear(); + args_[nArgs++] = group; + group.clear(); } } else { - args_[nArgs++] = argv[argI]; + args_[nArgs++] = argv[argi]; } } - else if (listDepth) + else if (depth) { // Quote each string element - tmpString += "\""; - tmpString += argv[argI]; - tmpString += "\""; + group += '"'; + group += argv[argi]; + 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 { - args_[nArgs++] = argv[argI]; + args_[nArgs++] = argv[argi]; } } - if (tmpString.size()) + if (group.size()) { // Group(s) not closed, but flush anything still pending - args_[nArgs++] = tmpString; + args_[nArgs++] = group; } args_.setSize(nArgs); @@ -530,11 +601,11 @@ Foam::argList::argList { // Check if this run is a parallel run by searching for any parallel option // 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)) { @@ -551,14 +622,14 @@ Foam::argList::argList // Check arguments and options, argv[0] was already handled int nArgs = 1; HashTable::const_iterator optIter; - for (int argI = 1; argI < args_.size(); ++argI) + for (int argi = 1; argi < args_.size(); ++argi) { 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) { @@ -580,8 +651,8 @@ Foam::argList::argList // If the option is known to require an argument, // get it or emit a FatalError. - ++argI; - if (argI >= args_.size()) + ++argi; + if (argi >= args_.size()) { FatalError <<"Option '-" << optionName @@ -591,9 +662,9 @@ Foam::argList::argList } argListStr_ += ' '; - argListStr_ += args_[argI]; + argListStr_ += args_[argi]; // Handle duplicates by taking the last -option specified - options_.set(optionName, args_[argI]); + options_.set(optionName, args_[argi]); } else { @@ -605,9 +676,9 @@ Foam::argList::argList } else { - if (nArgs != argI) + if (nArgs != argi) { - args_[nArgs] = args_[argI]; + args_[nArgs] = args_[argi]; } ++nArgs; } diff --git a/src/OpenFOAM/global/argList/argList.H b/src/OpenFOAM/global/argList/argList.H index 50f8cc18e7..19714b0fa8 100644 --- a/src/OpenFOAM/global/argList/argList.H +++ b/src/OpenFOAM/global/argList/argList.H @@ -103,6 +103,7 @@ SourceFiles #include "parRun.H" #include "StringStream.H" #include "OSspecific.H" +#include // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -146,6 +147,9 @@ class argList // Private Member Functions + //- Helper for resolving aliases for -options within validOptionsCompat + static word optionCompat(const word& optionName); + //- Helper function for printUsage static void printOptionUsage ( @@ -181,6 +185,10 @@ public: //- A list of valid parallel options static HashTable validParOptions; + //- A list of aliases for options. + // Stored as (alias = canonical, version) + static HashTable> validOptionsCompat; + //- Short usage information for validOptions static HashTable optionUsage; @@ -369,6 +377,19 @@ public: 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 compat + ); + //- Add option usage information to optionUsage static void addUsage (