class CommandLineModuleManager::Impl
{
public:
-
/*! \brief
* Initializes the implementation class.
*
- * \param[in] programInfo Program information for the running binary.
+ * \param programInfo Program information for the running binary.
*/
- explicit Impl(const ProgramInfo &programInfo);
+ explicit Impl(ProgramInfo *programInfo);
/*! \brief
* Finds a module that matches a name.
*/
CommandLineModuleMap modules_;
//! Information about the currently running program.
- const ProgramInfo &programInfo_;
+ ProgramInfo &programInfo_;
/*! \brief
* Module that implements help for the binary.
*
bool bQuiet_;
//! Whether to write the startup information to stdout iso stderr.
bool bStdOutInfo_;
+
+ private:
+ GMX_DISALLOW_COPY_AND_ASSIGN(Impl);
};
-CommandLineModuleManager::Impl::Impl(const ProgramInfo &programInfo)
- : programInfo_(programInfo), helpModule_(NULL), bQuiet_(false),
+CommandLineModuleManager::Impl::Impl(ProgramInfo *programInfo)
+ : programInfo_(*programInfo), helpModule_(NULL), bQuiet_(false),
bStdOutInfo_(false)
{
}
std::string message = formatString("'%s' is not a GROMACS command.", moduleName);
GMX_THROW(InvalidInputError(message));
}
+ programInfo_.setDisplayName(
+ programInfo_.realBinaryName() + "-" + module->first);
*argc -= moduleArgOffset;
*argv += moduleArgOffset;
return module->second.get();
* CommandLineModuleManager
*/
-CommandLineModuleManager::CommandLineModuleManager(const ProgramInfo &programInfo)
+CommandLineModuleManager::CommandLineModuleManager(ProgramInfo *programInfo)
: impl_(new Impl(programInfo))
{
impl_->helpModule_ = new CommandLineHelpModule(impl_->modules_);
/*! \brief
* Initializes a command-line module manager.
*
- * \param[in] programInfo Program information for the running binary.
+ * \param programInfo Program information for the running binary.
* \throws std::bad_alloc if out of memory.
*
* The binary name is used to detect when the binary is run through a
* symlink, and automatically invoke a matching module in such a case.
+ *
+ * \p programInfo is non-const to allow the manager to amend it based
+ * on the actual module that is getting executed.
*/
- explicit CommandLineModuleManager(const ProgramInfo &programInfo);
+ explicit CommandLineModuleManager(ProgramInfo *programInfo);
~CommandLineModuleManager();
/*! \brief
{
manager_.reset();
programInfo_.reset(new gmx::ProgramInfo("g_test", args.argc(), args.argv()));
- manager_.reset(new gmx::CommandLineModuleManager(*programInfo_));
+ manager_.reset(new gmx::CommandLineModuleManager(programInfo_.get()));
manager_->setQuiet(true);
}
#ifdef GMX_DOUBLE
precisionString = " (double precision)";
#endif
- const std::string &name = programInfo.programName();
+ const std::string &name = programInfo.displayName();
if (settings.bGeneratedByHeader_)
{
fprintf(fp, "%sCreated by:%s\n", prefix, suffix);
{
try
{
+ // TODO: Use the display name once it doesn't break anything.
return oenv->programInfo.programName().c_str();
}
GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
{
try
{
+ // TODO: Use the display name once it doesn't break anything.
return gmx::ProgramInfo::getInstance().programName().c_str();
}
GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
const char *programName = "GROMACS";
try
{
- programName = ProgramInfo::getInstance().programName().c_str();
+ programName = ProgramInfo::getInstance().displayName().c_str();
}
catch (const std::exception &)
{
#include "gromacs/legacyheaders/thread_mpi/mutex.h"
#include "gromacs/utility/exceptions.h"
+#include "gromacs/utility/gmxassert.h"
#include "gromacs/utility/path.h"
#include "gromacs/utility/stringutil.h"
namespace
{
+
//! Mutex for updates to the global program info objects.
tMPI::mutex g_programInfoMutex;
//! Global program info; stores the object initialized with ProgramInfo::init().
boost::scoped_ptr<ProgramInfo> g_programInfo;
+
+/*! \brief
+ * Quotes a string if it contains spaces.
+ */
+std::string quoteIfNecessary(const char *str)
+{
+ const bool bSpaces = (std::strchr(str, ' ') != NULL);
+ if (bSpaces)
+ {
+ return formatString("'%s'", str);
+ }
+ return str;
+}
+
} // namespace
/********************************************************************
Impl();
Impl(const char *realBinaryName, int argc, const char *const argv[]);
- std::string realBinaryName_;
- std::string fullInvokedProgram_;
- std::string programName_;
- std::string invariantProgramName_;
- std::string commandLine_;
+ std::string realBinaryName_;
+ std::string fullInvokedProgram_;
+ std::string programName_;
+ std::string invariantProgramName_;
+ std::string commandLine_;
+ std::string displayName_;
+ mutable tMPI::mutex displayNameMutex_;
};
ProgramInfo::Impl::Impl()
realBinaryName_ = invariantProgramName_;
}
- for (int i = 0; i < argc; ++i)
+ commandLine_ = quoteIfNecessary(programName_.c_str());
+ for (int i = 1; i < argc; ++i)
{
- if (i > 0)
- {
- commandLine_.append(" ");
- }
- const char *arg = argv[i];
- bool bSpaces = (std::strchr(arg, ' ') != NULL);
- if (bSpaces)
- {
- commandLine_.append("'");
- }
- commandLine_.append(arg);
- if (bSpaces)
- {
- commandLine_.append("'");
- }
+ commandLine_.append(" ");
+ commandLine_.append(quoteIfNecessary(argv[i]));
}
}
}
// static
-const ProgramInfo &ProgramInfo::init(const char *realBinaryName,
- int argc, const char *const argv[])
+ProgramInfo &ProgramInfo::init(const char *realBinaryName,
+ int argc, const char *const argv[])
{
try
{
{
}
+void ProgramInfo::setDisplayName(const std::string &name)
+{
+ tMPI::lock_guard<tMPI::mutex> lock(impl_->displayNameMutex_);
+ GMX_RELEASE_ASSERT(impl_->displayName_.empty(),
+ "Can only set display name once");
+ impl_->displayName_ = name;
+}
+
const std::string &ProgramInfo::realBinaryName() const
{
return impl_->realBinaryName_;
return impl_->invariantProgramName_;
}
+const std::string &ProgramInfo::displayName() const
+{
+ tMPI::lock_guard<tMPI::mutex> lock(impl_->displayNameMutex_);
+ return impl_->displayName_.empty()
+ ? impl_->programName_
+ : impl_->displayName_;
+}
+
const std::string &ProgramInfo::commandLine() const
{
return impl_->commandLine_;
*
* Does not throw. Terminates the program on out-of-memory error.
*/
- static const ProgramInfo &init(const char *realBinaryName,
- int argc, const char *const argv[]);
+ static ProgramInfo &init(const char *realBinaryName,
+ int argc, const char *const argv[]);
/*! \brief
* Constructs an empty program info objects.
int argc, const char *const argv[]);
~ProgramInfo();
+ /*! \brief
+ * Sets a display name for the binary.
+ *
+ * \throws std::bad_alloc if out of memory.
+ * \throws tMPI::system_error on thread synchronization errors.
+ *
+ * This is used with the wrapper binary to add the name of the invoked
+ * module to the name of the binary shown.
+ */
+ void setDisplayName(const std::string &name);
+
/*! \brief
* Returns the real name of the binary.
*
* Does not throw.
*/
const std::string &invariantProgramName() const;
+ /*! \brief
+ * Returns a display name of the current module.
+ *
+ * \throws tMPI::system_error on thread synchronization errors.
+ *
+ * The returned value equals programName(), unless a separate display
+ * name has been set with setDisplayName().
+ */
+ const std::string &displayName() const;
/*! \brief
* Returns the full command line used to invoke the binary.
*
int
main(int argc, char *argv[])
{
- const gmx::ProgramInfo &info =
- gmx::ProgramInfo::init("gmx", argc, argv);
+ gmx::ProgramInfo &info = gmx::ProgramInfo::init("gmx", argc, argv);
try
{
- gmx::CommandLineModuleManager manager(info);
+ gmx::CommandLineModuleManager manager(&info);
registerTrajectoryAnalysisModules(&manager);
registerLegacyModules(&manager);
manager.addHelpTopic(gmx::SelectionCollection::createDefaultHelpTopic());