#include "gromacs/legacyheaders/copyrite.h"
#include "gromacs/commandline/cmdlinemodule.h"
+#include "gromacs/commandline/cmdlineparser.h"
#include "gromacs/onlinehelp/helpformat.h"
#include "gromacs/onlinehelp/helpmanager.h"
#include "gromacs/onlinehelp/helptopic.h"
#include "gromacs/onlinehelp/helpwritercontext.h"
-#include "gromacs/utility/file.h"
+#include "gromacs/options/basicoptions.h"
+#include "gromacs/options/options.h"
#include "gromacs/utility/exceptions.h"
+#include "gromacs/utility/file.h"
#include "gromacs/utility/gmxassert.h"
#include "gromacs/utility/programinfo.h"
#include "gromacs/utility/stringutil.h"
virtual int run(int argc, char *argv[]);
virtual void writeHelp(const HelpWriterContext &context) const;
- //! Prints usage message to stderr.
- void printUsage() const;
-
private:
CompositeHelpTopicPointer rootTopic_;
// TODO: More information.
}
-void CommandLineHelpModule::printUsage() const
-{
- HelpWriterContext context(&File::standardError(),
- eHelpOutputFormat_Console);
- rootTopic_->writeHelp(context);
-}
-
/********************************************************************
* CommandLineModuleManager::Impl
*/
CommandLineModuleMap::const_iterator
findModuleFromBinaryName(const ProgramInfo &programInfo) const;
+ /*! \brief
+ * Processes command-line options for the wrapper binary.
+ *
+ * \param[in,out] argc On input, argc passed to run().
+ * On output, argc to be passed to the module.
+ * \param[in,out] argv On input, argv passed to run().
+ * On output, argv to be passed to the module.
+ * \throws InvalidInputError if there are invalid options.
+ * \returns The module that should be run.
+ *
+ * Handles command-line options that affect the wrapper binary
+ * (potentially changing the members of \c this in response to the
+ * options). Also finds the module that should be run and the
+ * arguments that should be passed to it.
+ */
+ CommandLineModuleInterface *
+ processCommonOptions(int *argc, char ***argv);
+
/*! \brief
* Maps module names to module objects.
*
* The pointed module is owned by the \a modules_ container.
*/
CommandLineHelpModule *helpModule_;
+ //! Settings for what to write in the startup header.
+ BinaryInformationSettings binaryInfoSettings_;
//! Whether all stderr output should be suppressed.
bool bQuiet_;
+ //! Whether to write the startup information to stdout iso stderr.
+ bool bStdOutInfo_;
};
CommandLineModuleManager::Impl::Impl(const ProgramInfo &programInfo)
- : programInfo_(programInfo), helpModule_(NULL), bQuiet_(false)
+ : programInfo_(programInfo), helpModule_(NULL), bQuiet_(false),
+ bStdOutInfo_(false)
{
}
return findModuleByName(binaryName);
}
+CommandLineModuleInterface *
+CommandLineModuleManager::Impl::processCommonOptions(int *argc, char ***argv)
+{
+ // Check if the module is called through a symlink.
+ CommandLineModuleMap::const_iterator module
+ = findModuleFromBinaryName(programInfo_);
+ if (module != modules_.end())
+ {
+ // TODO: Process common options also in this case.
+ return module->second.get();
+ }
+ // If not, process options to the wrapper binary.
+ // TODO: This should be done by CommandLineParser
+ // (together with the above TODO).
+ int moduleArgOffset = 1;
+ while (moduleArgOffset < *argc && (*argv)[moduleArgOffset][0] == '-')
+ {
+ ++moduleArgOffset;
+ }
+ bool bHelp = false;
+ bool bVersion = false;
+ bool bCopyright = false;
+ if (moduleArgOffset > 1)
+ {
+ // TODO: Print these options into the help.
+ // TODO: It would be nice to propagate at least the -quiet option to
+ // the modules so that they can also be quiet in response to this.
+ Options options(NULL, NULL);
+ options.addOption(BooleanOption("h").store(&bHelp));
+ options.addOption(BooleanOption("quiet").store(&bQuiet_));
+ options.addOption(BooleanOption("version").store(&bVersion));
+ options.addOption(BooleanOption("copyright").store(&bCopyright));
+ CommandLineParser(&options).parse(&moduleArgOffset, *argv);
+ options.finish();
+ binaryInfoSettings_.extendedInfo(bVersion);
+ binaryInfoSettings_.copyright(bCopyright);
+ }
+ if (bVersion || bCopyright)
+ {
+ bQuiet_ = false;
+ bStdOutInfo_ = true;
+ return NULL;
+ }
+ // If no module or help requested, show the help.
+ if (moduleArgOffset == *argc || bHelp)
+ {
+ *argc = 1;
+ return helpModule_;
+ }
+ // Find the module to run and arguments to it.
+ const char *moduleName = (*argv)[moduleArgOffset];
+ module = findModuleByName(moduleName);
+ if (module == modules_.end())
+ {
+ std::string message = formatString("'%s' is not a GROMACS command.", moduleName);
+ GMX_THROW(InvalidInputError(message));
+ }
+ *argc -= moduleArgOffset;
+ *argv += moduleArgOffset;
+ return module->second.get();
+}
+
/********************************************************************
* CommandLineModuleManager
*/
int CommandLineModuleManager::run(int argc, char *argv[])
{
- int argOffset = 0;
- CommandLineModuleMap::const_iterator module
- = impl_->findModuleFromBinaryName(impl_->programInfo_);
- if (!impl_->bQuiet_)
+ CommandLineModuleInterface *module;
+ try
{
- printBinaryInformation(stderr, impl_->programInfo_);
+ module = impl_->processCommonOptions(&argc, &argv);
}
- if (module == impl_->modules_.end())
+ catch (const std::exception &)
{
- if (argc < 2)
+ if (!impl_->bQuiet_)
{
- impl_->helpModule_->printUsage();
- if (!impl_->bQuiet_)
- {
- gmx_thanx(stderr);
- }
- return 2;
+ printBinaryInformation(stderr, impl_->programInfo_);
}
- module = impl_->findModuleByName(argv[1]);
- argOffset = 1;
+ throw;
}
- if (module == impl_->modules_.end())
+ if (!impl_->bQuiet_)
{
- fprintf(stderr, "Unknown command: '%s'\n\n", argv[1]);
- impl_->helpModule_->printUsage();
- if (!impl_->bQuiet_)
- {
- gmx_thanx(stderr);
- }
- return 2;
+ printBinaryInformation(impl_->bStdOutInfo_ ? stdout : stderr,
+ impl_->programInfo_, impl_->binaryInfoSettings_);
+ }
+ if (module == NULL)
+ {
+ return 0;
}
- int rc = module->second->run(argc - argOffset, argv + argOffset);
+ int rc = module->run(argc, argv);
if (!impl_->bQuiet_)
{
gmx_thanx(stderr);
sfree(tmpstr);
}
-void CopyRight(FILE *out)
+static void CopyRight(FILE *out)
{
static const char * const CopyrightText[] = {
"Written by Emile Apol, Rossen Apostolov, Herman J.C. Berendsen,",
char tmpstr[1024];
int i;
+ // TODO: Consider making the output more compact to fit better with
+ // other information written by printBinaryInformation().
ster_print(out, "G R O M A C S");
fprintf(out, "\n");
namespace gmx
{
+BinaryInformationSettings::BinaryInformationSettings()
+ : bExtendedInfo_(false), bCopyright_(false)
+{
+}
+
void printBinaryInformation(FILE *fp, const ProgramInfo &programInfo)
+{
+ printBinaryInformation(fp, programInfo, BinaryInformationSettings());
+}
+
+void printBinaryInformation(FILE *fp, const ProgramInfo &programInfo,
+ const BinaryInformationSettings &settings)
{
const char *precisionString = "";
#ifdef GMX_DOUBLE
GromacsVersion(), precisionString);
fprintf(fp, "Executable: %s\n", programInfo.programNameWithPath().c_str());
fprintf(fp, "Command line:\n %s\n", programInfo.commandLine().c_str());
+ if (settings.bCopyright_)
+ {
+ fprintf(fp, "\n");
+ CopyRight(fp);
+ }
+ if (settings.bExtendedInfo_)
+ {
+ fprintf(fp, "\n");
+ gmx_print_version_info(fp);
+ }
fprintf(fp, "\n");
}
// Ensure that the program info is initialized; if already done, returns
// the already initialized object.
const gmx::ProgramInfo &programInfo = gmx::ProgramInfo::init(*argc, argv);
- if (FF(PCA_STANDALONE))
- {
- gmx::printBinaryInformation(stderr, programInfo);
- }
/* Check for double arguments */
for (i = 1; (i < *argc); i++)
{
output_env_init(oenv, *argc, argv, (time_unit_t)nenum(time_units), bView,
(xvg_format_t)nenum(xvg_format), 0, debug_level);
- if (bVersion)
+ if (!FF(PCA_QUIET) && FF(PCA_STANDALONE) && (!bQuiet || bVersion))
{
- printf("Program: %s\n", output_env_get_program_name(*oenv));
- gmx_print_version_info(stdout);
- exit(0);
+ gmx::BinaryInformationSettings settings;
+ settings.extendedInfo(bVersion);
+ gmx::printBinaryInformation(bVersion ? stdout : stderr,
+ programInfo, settings);
}
if (FF(PCA_CAN_SET_DEFFNM) && (deffnm != NULL))
all_pa[i].desc = mk_desc(&(all_pa[i]), output_env_get_time_unit(*oenv));
}
- bExit = bHelp || (strcmp(manstr[0], "no") != 0);
+ bExit = bHelp || bVersion || (strcmp(manstr[0], "no") != 0);
#if (defined __sgi && USE_SGI_FPE)
doexceptions();
class ProgramInfo;
+/*! \brief
+ * Settings for printBinaryInformation().
+ *
+ * This class is used to specify what printBinaryInformation() prints.
+ */
+class BinaryInformationSettings
+{
+ public:
+ BinaryInformationSettings();
+
+ //! Print information about build settings.
+ BinaryInformationSettings &extendedInfo(bool bEnabled)
+ {
+ bExtendedInfo_ = bEnabled;
+ return *this;
+ }
+ //! Print copyright and license information.
+ BinaryInformationSettings ©right(bool bEnabled)
+ {
+ bCopyright_ = bEnabled;
+ return *this;
+ }
+
+ private:
+ bool bExtendedInfo_;
+ bool bCopyright_;
+
+ //! Needed to read the members without otherwise unnecessary accessors.
+ friend void printBinaryInformation(FILE *fp, const ProgramInfo &programInfo,
+ const BinaryInformationSettings &settings);
+};
+
/*! \brief
* Print basic information about the executable.
*
* \param[in] programInfo Program information object to use.
*/
void printBinaryInformation(FILE *fp, const ProgramInfo &programInfo);
+/*! \brief
+ * Print basic information about the executable with custom settings.
+ *
+ * \param fp Where to print the information to.
+ * \param[in] programInfo Program information object to use.
+ * \param[in] settings Specifies what to print.
+ *
+ * \see BinaryInformationSettings
+ */
+void printBinaryInformation(FILE *fp, const ProgramInfo &programInfo,
+ const BinaryInformationSettings &settings);
} // namespace gmx;