* \author Teemu Murtola <teemu.murtola@gmail.com>
* \ingroup module_commandline
*/
+#include "gmxpre.h"
+
#include "cmdlinemodulemanager.h"
+#include "config.h"
+
#include <cstdio>
#include <string>
#include <utility>
-#include "gromacs/legacyheaders/copyrite.h"
-#include "gromacs/legacyheaders/network.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
#include "gromacs/commandline/cmdlinehelpcontext.h"
-#include "gromacs/commandline/cmdlinehelpmodule.h"
#include "gromacs/commandline/cmdlineinit.h"
#include "gromacs/commandline/cmdlinemodule.h"
-#include "gromacs/commandline/cmdlinemodulemanager-impl.h"
#include "gromacs/commandline/cmdlineparser.h"
#include "gromacs/commandline/cmdlineprogramcontext.h"
+#include "gromacs/legacyheaders/copyrite.h"
#include "gromacs/options/basicoptions.h"
#include "gromacs/options/options.h"
+#include "gromacs/utility/basenetwork.h"
#include "gromacs/utility/exceptions.h"
+#include "gromacs/utility/fatalerror.h"
#include "gromacs/utility/gmxassert.h"
#include "gromacs/utility/stringutil.h"
-// For GMX_BINARY_SUFFIX
-#include "config.h"
+#include "cmdlinehelpmodule.h"
+#include "cmdlinemodulemanager-impl.h"
namespace gmx
{
return shortDescription_;
}
+ virtual void init(CommandLineModuleSettings * /*settings*/)
+ {
+ }
virtual int run(int argc, char *argv[])
{
return mainFunction_(argc, argv);
}
virtual void writeHelp(const CommandLineHelpContext &context) const
{
- char *argv[2];
- int argc = 1;
- // TODO: The constness should not be cast away.
- argv[0] = const_cast<char *>(name_);
- argv[1] = NULL;
- GlobalCommandLineHelpContext global(context);
- mainFunction_(argc, argv);
+ writeCommandLineHelpCMain(context, name_, mainFunction_);
}
private:
const char *name_;
const char *shortDescription_;
CMainFunction mainFunction_;
-
};
+//! \}
+
+} // namespace
+
/********************************************************************
- * CommonOptionsHolder
+ * CommandLineCommonOptionsHolder
*/
-/*! \brief
- * Encapsulates some handling of common options to the wrapper binary.
- */
-class CommonOptionsHolder
+CommandLineCommonOptionsHolder::CommandLineCommonOptionsHolder()
+ : options_(NULL, NULL), bHelp_(false), bHidden_(false),
+ bQuiet_(false), bVersion_(false), bCopyright_(true),
+ niceLevel_(19), debugLevel_(0)
{
- public:
- CommonOptionsHolder()
- : options_(NULL, NULL), bHelp_(false), bHidden_(false),
- bQuiet_(false), bVersion_(false), bCopyright_(true)
- {
- binaryInfoSettings_.copyright(true);
- }
-
- //! Initializes the common options.
- void initOptions()
- {
- options_.addOption(BooleanOption("h").store(&bHelp_)
- .description("Print help and quit"));
- options_.addOption(BooleanOption("hidden").store(&bHidden_)
- .hidden()
- .description("Show hidden options in help"));
- options_.addOption(BooleanOption("quiet").store(&bQuiet_)
- .description("Do not print common startup info or quotes"));
- options_.addOption(BooleanOption("version").store(&bVersion_)
- .description("Print extended version information and quit"));
- options_.addOption(BooleanOption("copyright").store(&bCopyright_)
- .description("Print copyright information on startup"));
- }
-
- /*! \brief
- * Finishes option parsing.
- *
- * \returns `false` if the wrapper binary should quit without executing
- * any module.
- */
- bool finishOptions()
- {
- options_.finish();
- binaryInfoSettings_.extendedInfo(bVersion_);
- // The latter condition suppresses the copyright with
- // -quiet -version.
- binaryInfoSettings_.copyright(bCopyright_ && !bQuiet_);
- return !bVersion_;
- }
-
- //! Returns the internal Options object.
- Options *options() { return &options_; }
- //! Returns the settings for printing startup information.
- const BinaryInformationSettings &binaryInfoSettings() const
- {
- return binaryInfoSettings_;
- }
-
- /*! \brief
- * Returns `true` if common options are set such that the wrapper
- * binary should quit, without running the actual module.
- */
- bool shouldIgnoreActualModule() const
- {
- return bHelp_ || bVersion_;
- }
- //! Returns whether common options specify showing help.
- bool shouldShowHelp() const { return bHelp_; }
- //! Returns whether common options specify showing hidden options in help.
- bool shouldShowHidden() const { return bHidden_; }
- //! Returns whether common options specify quiet execution.
- bool shouldBeQuiet() const
- {
- return bQuiet_ && !bVersion_;
- }
+ binaryInfoSettings_.copyright(true);
+}
- //! Returns the file to which startup information should be printed.
- FILE *startupInfoFile() const { return (bVersion_ ? stdout : stderr); }
+CommandLineCommonOptionsHolder::~CommandLineCommonOptionsHolder()
+{
+}
- private:
- Options options_;
- //! Settings for what to write in the startup header.
- BinaryInformationSettings binaryInfoSettings_;
- bool bHelp_;
- bool bHidden_;
- bool bQuiet_;
- bool bVersion_;
- bool bCopyright_;
-};
+void CommandLineCommonOptionsHolder::initOptions()
+{
+ options_.addOption(BooleanOption("h").store(&bHelp_)
+ .description("Print help and quit"));
+ options_.addOption(BooleanOption("hidden").store(&bHidden_)
+ .hidden()
+ .description("Show hidden options in help"));
+ options_.addOption(BooleanOption("quiet").store(&bQuiet_)
+ .description("Do not print common startup info or quotes"));
+ options_.addOption(BooleanOption("version").store(&bVersion_)
+ .description("Print extended version information and quit"));
+ options_.addOption(BooleanOption("copyright").store(&bCopyright_)
+ .description("Print copyright information on startup"));
+ options_.addOption(IntegerOption("nice").store(&niceLevel_)
+ .description("Set the nicelevel (default depends on command)"));
+ options_.addOption(IntegerOption("debug").store(&debugLevel_)
+ .hidden().defaultValueIfSet(1)
+ .description("Write file with debug information, "
+ "1: short (default), 2: also x and f"));
+}
-//! \}
+bool CommandLineCommonOptionsHolder::finishOptions()
+{
+ options_.finish();
+ binaryInfoSettings_.extendedInfo(bVersion_);
+ // The latter condition suppresses the copyright with
+ // -quiet -version.
+ binaryInfoSettings_.copyright(bCopyright_ && !bQuiet_);
+ return !bVersion_;
+}
-} // namespace
+void CommandLineCommonOptionsHolder::adjustFromSettings(
+ const CommandLineModuleSettings &settings)
+{
+ if (!options_.isSet("nice"))
+ {
+ niceLevel_ = settings.defaultNiceLevel();
+ }
+}
/********************************************************************
* CommandLineModuleManager::Impl
/*! \brief
* Initializes the implementation class.
*
- * \param[in] binaryName Name of the running binary
+ * \param[in] binaryName Name of the running binary
* (without Gromacs binary suffix or .exe on Windows).
- * \param programInfo Program information for the running binary.
+ * \param programContext Program information for the running binary.
*/
- Impl(const char *binaryName, ProgramInfo *programInfo);
+ Impl(const char *binaryName, CommandLineProgramContext *programContext);
/*! \brief
* Helper method that adds a given module to the module manager.
/*! \brief
* Finds a module that the name of the binary.
*
- * \param[in] programInfo Program information object to use.
+ * \param[in] invokedName Name by which the program was invoked.
* \throws std::bad_alloc if out of memory.
* \returns Iterator to the found module, or
* \c modules_.end() if not found.
* is different from \a binaryName_, and if so, checks
* if a module name matches the name of the symlink.
*
- * Note that the \p programInfo parameter is currently not necessary
- * (as the program info object is also contained as a member), but it
- * clarifies the control flow.
+ * Note that the \p invokedName parameter is currently not necessary
+ * (as the program context object is also available and provides this
+ * value), but it clarifies the control flow.
*/
CommandLineModuleMap::const_iterator
- findModuleFromBinaryName(const ProgramInfo &programInfo) const;
+ findModuleFromBinaryName(const char *invokedName) const;
/*! \brief
* Processes command-line options for the wrapper binary.
* arguments that should be passed to it.
*/
CommandLineModuleInterface *
- processCommonOptions(CommonOptionsHolder *optionsHolder,
+ processCommonOptions(CommandLineCommonOptionsHolder *optionsHolder,
int *argc, char ***argv);
/*! \brief
*/
CommandLineModuleGroupList moduleGroups_;
//! Information about the currently running program.
- ProgramInfo &programInfo_;
+ CommandLineProgramContext &programContext_;
//! Name of the binary.
std::string binaryName_;
/*! \brief
GMX_DISALLOW_COPY_AND_ASSIGN(Impl);
};
-CommandLineModuleManager::Impl::Impl(const char *binaryName,
- ProgramInfo *programInfo)
- : programInfo_(*programInfo),
+CommandLineModuleManager::Impl::Impl(const char *binaryName,
+ CommandLineProgramContext *programContext)
+ : programContext_(*programContext),
binaryName_(binaryName != NULL ? binaryName : ""),
helpModule_(NULL), singleModule_(NULL),
bQuiet_(false)
{
+ GMX_RELEASE_ASSERT(binaryName_.find('-') == std::string::npos,
+ "Help export does not currently work with binary names with dashes");
}
void CommandLineModuleManager::Impl::addModule(CommandLineModulePointer module)
{
if (helpModule_ == NULL)
{
- helpModule_ = new CommandLineHelpModule(programInfo_, binaryName_,
+ helpModule_ = new CommandLineHelpModule(programContext_, binaryName_,
modules_, moduleGroups_);
addModule(CommandLineModulePointer(helpModule_));
}
CommandLineModuleMap::const_iterator
CommandLineModuleManager::Impl::findModuleFromBinaryName(
- const ProgramInfo &programInfo) const
+ const char *invokedName) const
{
- std::string moduleName = programInfo.programName();
+ std::string moduleName = invokedName;
#ifdef GMX_BINARY_SUFFIX
moduleName = stripSuffixIfPresent(moduleName, GMX_BINARY_SUFFIX);
#endif
CommandLineModuleInterface *
CommandLineModuleManager::Impl::processCommonOptions(
- CommonOptionsHolder *optionsHolder, int *argc, char ***argv)
+ CommandLineCommonOptionsHolder *optionsHolder, int *argc, char ***argv)
{
// Check if we are directly invoking a certain module.
CommandLineModuleInterface *module = singleModule_;
{
// Also check for invokation through named symlinks.
CommandLineModuleMap::const_iterator moduleIter
- = findModuleFromBinaryName(programInfo_);
+ = findModuleFromBinaryName(programContext_.programName());
if (moduleIter != modules_.end())
{
module = moduleIter->second.get();
{
if (singleModule_ == NULL)
{
- programInfo_.setDisplayName(binaryName_ + " " + module->name());
+ programContext_.setDisplayName(binaryName_ + " " + module->name());
}
// Recognize the common options also after the module name.
// TODO: It could be nicer to only recognize -h/-hidden if module is not
if (module == helpModule_)
{
helpModule_->setShowHidden(optionsHolder->shouldShowHidden());
- helpModule_->setCommonOptions(optionsHolder->options());
}
return module;
}
* CommandLineModuleManager
*/
-CommandLineModuleManager::CommandLineModuleManager(const char *binaryName,
- ProgramInfo *programInfo)
- : impl_(new Impl(binaryName, programInfo))
+CommandLineModuleManager::CommandLineModuleManager(
+ const char *binaryName, CommandLineProgramContext *programContext)
+ : impl_(new Impl(binaryName, programContext))
{
}
impl_->bQuiet_ = bQuiet;
}
+void CommandLineModuleManager::setOutputRedirect(File *output)
+{
+ impl_->ensureHelpModuleExists();
+ impl_->helpModule_->setOutputRedirect(output);
+}
+
void CommandLineModuleManager::setSingleModule(CommandLineModuleInterface *module)
{
impl_->singleModule_ = module;
int CommandLineModuleManager::run(int argc, char *argv[])
{
- CommandLineModuleInterface *module;
- const bool bMaster = (!gmx_mpi_initialized() || gmx_node_rank() == 0);
- bool bQuiet = impl_->bQuiet_ || !bMaster;
- CommonOptionsHolder optionsHolder;
+ CommandLineModuleInterface *module;
+ const bool bMaster = (gmx_node_rank() == 0);
+ bool bQuiet = impl_->bQuiet_ || !bMaster;
+ CommandLineCommonOptionsHolder optionsHolder;
try
{
optionsHolder.initOptions();
bQuiet |= optionsHolder.shouldBeQuiet();
if (!bQuiet)
{
- printBinaryInformation(stderr, impl_->programInfo_,
+ printBinaryInformation(stderr, impl_->programContext_,
optionsHolder.binaryInfoSettings());
}
throw;
if (!bQuiet)
{
FILE *out = optionsHolder.startupInfoFile();
- printBinaryInformation(out, impl_->programInfo_,
+ printBinaryInformation(out, impl_->programContext_,
optionsHolder.binaryInfoSettings());
fprintf(out, "\n");
}
{
return 0;
}
- int rc = module->run(argc, argv);
+
+ CommandLineModuleSettings settings;
+ module->init(&settings);
+ optionsHolder.adjustFromSettings(settings);
+
+ // Open the debug file.
+ if (optionsHolder.debugLevel() > 0)
+ {
+ std::string filename(impl_->programContext_.programName());
+ if (gmx_node_num() > 1)
+ {
+ filename.append(formatString("%d", gmx_node_rank()));
+ }
+ filename.append(".debug");
+
+ fprintf(stderr, "Will write debug log file: %s\n", filename.c_str());
+ gmx_init_debug(optionsHolder.debugLevel(), filename.c_str());
+ }
+#if defined(HAVE_UNISTD_H) && !defined(GMX_NO_NICE) && !defined(__MINGW32__)
+ // Set the nice level unless disabled in the configuration.
+ if (optionsHolder.niceLevel() != 0)
+ {
+ static bool bNiceSet = false; // Only set it once.
+ if (!bNiceSet)
+ {
+ if (nice(optionsHolder.niceLevel()) == -1)
+ {
+ // Do nothing, but use the return value to avoid warnings.
+ }
+ bNiceSet = true;
+ }
+ }
+#endif
+
+ int rc = 0;
+ if (!(module == impl_->helpModule_ && !bMaster))
+ {
+ rc = module->run(argc, argv);
+ }
if (!bQuiet)
{
gmx_thanx(stderr);
int CommandLineModuleManager::runAsMainSingleModule(
int argc, char *argv[], CommandLineModuleInterface *module)
{
- ProgramInfo &programInfo = gmx::initForCommandLine(&argc, &argv);
+ CommandLineProgramContext &programContext = gmx::initForCommandLine(&argc, &argv);
try
{
- CommandLineModuleManager manager(NULL, &programInfo);
+ CommandLineModuleManager manager(NULL, &programContext);
manager.setSingleModule(module);
int rc = manager.run(argc, argv);
gmx::finalizeForCommandLine();
catch (const std::exception &ex)
{
printFatalErrorMessage(stderr, ex);
- return processExceptionAtExit(ex);
+ return processExceptionAtExitForCommandLine(ex);
}
}