? static_cast<xvg_format_t>(impl_->settings_.plotFormat())
: exvgNONE);
output_env_t oenv;
- output_env_init(&oenv, getProgramContext(), time_unit, FALSE, xvg_format, 0, 0);
+ output_env_init(&oenv, getProgramContext(), time_unit, FALSE, xvg_format, 0);
boost::shared_ptr<output_env> oenvGuard(oenv, &output_env_done);
impl_->fp_ = xvgropen(impl_->filename_.c_str(), impl_->title_.c_str(),
impl_->xlabel_.c_str(), impl_->ylabel_.c_str(),
*
* Does not throw.
*/
- explicit RootHelpTopic(const std::string &binaryName)
- : binaryName_(binaryName)
+ explicit RootHelpTopic(const CommandLineHelpModuleImpl &helpModule)
+ : helpModule_(helpModule)
{
}
virtual void writeHelp(const HelpWriterContext &context) const;
private:
- std::string binaryName_;
+ const CommandLineHelpModuleImpl &helpModule_;
GMX_DISALLOW_COPY_AND_ASSIGN(RootHelpTopic);
};
}
{
CommandLineCommonOptionsHolder optionsHolder;
- CommandLineHelpContext cmdlineContext(context);
+ CommandLineHelpContext cmdlineContext(*helpModule_.context_);
+ cmdlineContext.setModuleDisplayName(helpModule_.binaryName_);
optionsHolder.initOptions();
- cmdlineContext.setModuleDisplayName(binaryName_);
// TODO: Add <command> [<args>] into the synopsis.
- // TODO: Propagate the -hidden option here.
CommandLineHelpWriter(*optionsHolder.options())
.writeHelp(cmdlineContext);
}
const std::string &binaryName,
const CommandLineModuleMap &modules,
const CommandLineModuleGroupList &groups)
- : rootTopic_(new RootHelpTopic(binaryName)), programContext_(programContext),
+ : rootTopic_(new RootHelpTopic(*this)), programContext_(programContext),
binaryName_(binaryName), modules_(modules), groups_(groups),
context_(NULL), moduleOverride_(NULL), bHidden_(false),
outputOverride_(NULL)
return bQuiet_ && !bVersion_;
}
+ //! Returns the debug level.
+ int debugLevel() const { return debugLevel_; }
+
//! Returns the file to which startup information should be printed.
FILE *startupInfoFile() const { return (bVersion_ ? stdout : stderr); }
bool bQuiet_;
bool bVersion_;
bool bCopyright_;
+ int debugLevel_;
GMX_DISALLOW_COPY_AND_ASSIGN(CommandLineCommonOptionsHolder);
};
#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"
CommandLineCommonOptionsHolder::CommandLineCommonOptionsHolder()
: options_(NULL, NULL), bHelp_(false), bHidden_(false),
- bQuiet_(false), bVersion_(false), bCopyright_(true)
+ bQuiet_(false), bVersion_(false), bCopyright_(true), debugLevel_(0)
{
binaryInfoSettings_.copyright(true);
}
.description("Print extended version information and quit"));
options_.addOption(BooleanOption("copyright").store(&bCopyright_)
.description("Print copyright information on startup"));
+ 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()
int CommandLineModuleManager::run(int argc, char *argv[])
{
CommandLineModuleInterface *module;
- const bool bMaster = (!gmx_mpi_initialized() || gmx_node_rank() == 0);
+ const bool bMaster = (gmx_node_rank() == 0);
bool bQuiet = impl_->bQuiet_ || !bMaster;
CommandLineCommonOptionsHolder optionsHolder;
try
{
return 0;
}
+ /* 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());
+ }
int rc = module->run(argc, argv);
if (!bQuiet)
{
#include <config.h>
#endif
-#include <cctype>
-#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "gromacs/options/options.h"
#include "gromacs/options/timeunitmanager.h"
#include "gromacs/utility/arrayref.h"
-#include "gromacs/utility/basenetwork.h"
#include "gromacs/utility/common.h"
#include "gromacs/utility/cstringutil.h"
#include "gromacs/utility/exceptions.h"
try
{
- int nicelevel = 0, debug_level = 0;
+ int nicelevel = 0;
double tbegin = 0.0, tend = 0.0, tdelta = 0.0;
bool bView = false;
int xvgFormat = 0;
options.addManager(&fileOptManager);
options.setDescription(gmx::ConstArrayRef<const char *>(desc, ndesc));
- options.addOption(
- gmx::IntegerOption("debug").store(&debug_level).hidden()
- .description("Write file with debug information, "
- "1: short, 2: also x and f"));
options.addOption(
gmx::IntegerOption("nice").store(&nicelevel)
/* set program name, command line, and default values for output options */
output_env_init(oenv, gmx::getProgramContext(),
(time_unit_t)(timeUnitManager.timeUnit() + 1), bView,
- (xvg_format_t)(xvgFormat + 1), 0, debug_level);
-
- /* Open the debug file */
- if (debug_level > 0)
- {
- char buf[256];
-
- if (gmx_mpi_initialized())
- {
- sprintf(buf, "%s%d.debug", output_env_get_short_program_name(*oenv),
- gmx_node_rank());
- }
- else
- {
- sprintf(buf, "%s.debug", output_env_get_short_program_name(*oenv));
- }
-
- init_debug(debug_level, buf);
- fprintf(stderr, "Opening debug file %s (src code file %s, line %d)\n",
- buf, __FILE__, __LINE__);
- }
+ (xvg_format_t)(xvgFormat + 1), 0);
/* Set the nice level */
#ifdef HAVE_UNISTD_H
view = FALSE;
xvg_format = exvgNONE;
verbosity = 0;
- debug_level = 0;
}
const gmx::ProgramContextInterface &programContext;
xvg_format_t xvg_format;
/* The level of verbosity for this program */
int verbosity;
- /* the debug level */
- int debug_level;
};
/* The source code in this file should be thread-safe.
void output_env_init(output_env_t *oenvp,
const gmx::ProgramContextInterface &context,
time_unit_t tmu, gmx_bool view, xvg_format_t xvg_format,
- int verbosity, int debug_level)
+ int verbosity)
{
try
{
oenv->view = view;
oenv->xvg_format = xvg_format;
oenv->verbosity = verbosity;
- oenv->debug_level = debug_level;
}
GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
}
return oenv->verbosity;
}
-int output_env_get_debug_level(const output_env_t oenv)
-{
- return oenv->debug_level;
-}
-
const char *output_env_get_time_unit(const output_env_t oenv)
{
return time_units_str[oenv->time_unit];
int output_env_get_verbosity(const output_env_t oenv);
/* return the verbosity */
-int output_env_get_debug_level(const output_env_t oenv);
-/* return the debug level */
-
const char *output_env_get_time_unit(const output_env_t oenv);
/* return time unit (e.g. ps or ns) */
void output_env_init(output_env_t *oenvp,
const gmx::ProgramContextInterface &context,
time_unit_t tmu, gmx_bool view, xvg_format_t xvg_format,
- int verbosity, int debug_level);
+ int verbosity);
/* initialize an output_env structure, setting the command line,
the default time value a gmx_boolean view that is set to TRUE when the
user requests direct viewing of graphs,
}
time_unit_t time_unit
= static_cast<time_unit_t>(impl_->settings_.timeUnit() + 1);
- output_env_init(&impl_->oenv_, getProgramContext(), time_unit, FALSE, exvgNONE, 0, 0);
+ output_env_init(&impl_->oenv_, getProgramContext(), time_unit, FALSE, exvgNONE, 0);
int frflags = impl_->settings_.frflags();
frflags |= TRX_NEED_X;
#include "gromacs/utility/programcontext.h"
#include "gromacs/utility/smalloc.h"
-static gmx_bool bDebug = FALSE;
-static FILE *log_file = NULL;
-
-static tMPI_Thread_mutex_t debug_mutex = TMPI_THREAD_MUTEX_INITIALIZER;
+static bool bDebug = false;
static tMPI_Thread_mutex_t where_mutex = TMPI_THREAD_MUTEX_INITIALIZER;
+FILE *debug = NULL;
+gmx_bool gmx_debug_at = FALSE;
+
+static FILE *log_file = NULL;
+static tMPI_Thread_mutex_t error_mutex = TMPI_THREAD_MUTEX_INITIALIZER;
static const char *const gmxuser
= "Please report this to the mailing list (gmx-users@gromacs.org)";
-gmx_bool bDebugMode(void)
+void gmx_init_debug(const int dbglevel, const char *dbgfile)
{
- return bDebug;
+ if (!bDebug)
+ {
+ gmx_disable_file_buffering();
+ debug = gmx_ffopen(dbgfile, "w+");
+ bDebug = true;
+ if (dbglevel >= 2)
+ {
+ gmx_debug_at = TRUE;
+ }
+ }
}
-void gmx_fatal_set_log_file(FILE *fp)
+gmx_bool bDebugMode(void)
{
- log_file = fp;
+ return bDebug;
}
void _where(const char *file, int line)
}
}
+void gmx_fatal_set_log_file(FILE *fp)
+{
+ log_file = fp;
+}
+
static int fatal_errno = 0;
static void default_error_handler(const char *msg)
{
- tMPI_Thread_mutex_lock(&debug_mutex);
+ tMPI_Thread_mutex_lock(&error_mutex);
if (fatal_errno == 0)
{
if (log_file)
}
perror(msg);
}
- tMPI_Thread_mutex_unlock(&debug_mutex);
+ tMPI_Thread_mutex_unlock(&error_mutex);
}
static void (*gmx_error_handler)(const char *msg) = default_error_handler;
{
// TODO: Either this is unnecessary, or also reads to the handler should be
// protected by a mutex.
- tMPI_Thread_mutex_lock(&debug_mutex);
+ tMPI_Thread_mutex_lock(&error_mutex);
gmx_error_handler = func;
- tMPI_Thread_mutex_unlock(&debug_mutex);
+ tMPI_Thread_mutex_unlock(&error_mutex);
}
static void call_error_handler(const char *key, const char *file, int line, const char *msg)
char msg[STRLEN];
vsprintf(msg, fmt, ap);
- tMPI_Thread_mutex_lock(&debug_mutex);
+ tMPI_Thread_mutex_lock(&error_mutex);
fatal_errno = f_errno;
- tMPI_Thread_mutex_unlock(&debug_mutex);
+ tMPI_Thread_mutex_unlock(&error_mutex);
call_error_handler("fatal", file, line, msg);
}
va_end(ap);
}
-/*
- * These files are global variables in the gromacs preprocessor
- * Every routine in a file that includes gmx_fatal.h can write to these
- * debug channels. Depending on the debuglevel used
- * 0 to 3 of these filed are redirected to /dev/null
- *
- */
-FILE *debug = NULL;
-gmx_bool gmx_debug_at = FALSE;
-
-void init_debug(const int dbglevel, const char *dbgfile)
-{
- tMPI_Thread_mutex_lock(&debug_mutex);
- if (!bDebug) /* another thread hasn't already run this*/
- {
- no_buffers();
- debug = gmx_ffopen(dbgfile, "w+");
- bDebug = TRUE;
- if (dbglevel >= 2)
- {
- gmx_debug_at = TRUE;
- }
- }
- tMPI_Thread_mutex_unlock(&debug_mutex);
-}
-
char *gmx_strerror(const char *key)
{
typedef struct {
#endif
#endif
+/*! \brief
+ * Debug log file.
+ *
+ * Functions can write to this file for debug info.
+ * Before writing to it, it should be checked whether the file is not NULL:
+ * \code
+ if (debug)
+ {
+ fprintf(debug, "%s", "Debug text");
+ }
+ \endcode
+ */
+extern FILE *debug;
+/** Whether extra debugging is enabled. */
+extern gmx_bool gmx_debug_at;
+
+/*! \brief
+ * Initializes debugging variables.
+ *
+ * This function is not threadsafe. It should be called as part of
+ * initializing \Gromacs, before any other thread accesses the library.
+ * For command line programs, gmx::CommandLineModuleManager takes care
+ * of this if the user requests debugging.
+ */
+void gmx_init_debug(const int dbglevel, const char *dbgfile);
+
+/** Returns TRUE when the program was started in debug mode */
+gmx_bool bDebugMode(void);
+
/** Implementation for where(). */
void
_where(const char *file, int line);
/** Prints filename and line to stdlog. */
#define where() _where(__FILE__, __LINE__)
+/** Sets the log file for printing error messages. */
+void
+gmx_fatal_set_log_file(FILE *fp);
+
+/*! \brief
+ * Sets an error handler for gmx_fatal() and other fatal error routines.
+ *
+ * The default handler prints the message.
+ * \Gromacs will terminate the program after the error handler returns.
+ * To make gmx_fatal_collective() work, the error handler should not terminate
+ * the program, as it cannot know what is the desired way of termination.
+ * The string passed to the handler may be a multi-line string.
+ *
+ * \see gmx_fatal()
+ */
+void
+set_gmx_error_handler(void (*func)(const char *msg));
+
/*! \brief
* Low-level fatal error reporting routine for collective MPI errors.
*
/** Helper macro to pass first three parameters to gmx_fatal(). */
#define FARGS 0, __FILE__, __LINE__
-/** Sets the log file for printing error messages. */
-void
-gmx_fatal_set_log_file(FILE *fp);
-
-/*! \brief
- * Debug log file.
- *
- * Functions can write to this file for debug info.
- * Before writing to it, it should be checked whether the file is not NULL:
- * \code
- if (debug)
- {
- fprintf(debug, "%s", "Debug text");
- }
- \endcode
- */
-extern FILE *debug;
-/** Whether extra debugging is enabled. */
-extern gmx_bool gmx_debug_at;
-
-/** Initializes debugging variables */
-void init_debug(const int dbglevel, const char *dbgfile);
-
-/** Returns TRUE when the program was started in debug mode */
-gmx_bool bDebugMode(void);
-
-/*! \brief
- * Implementation for range_check() and range_check_mesg().
- *
- * \p warn_str can be NULL.
- */
-void _range_check(int n, int n_min, int n_max, const char *warn_str,
- const char *var,
- const char *file, int line);
-
-/*! \brief
- * Checks that a variable is within a range.
- *
- * If \p n is not in range [n_min, n_max), a fatal error is raised.
- * \p n_min is inclusive, but \p n_max is not.
- */
-#define range_check_mesg(n, n_min, n_max, str) _range_check(n, n_min, n_max, str,#n, __FILE__, __LINE__)
-
-/*! \brief
- * Checks that a variable is within a range.
- *
- * This works as range_check_mesg(), but with a default error message.
- */
-#define range_check(n, n_min, n_max) _range_check(n, n_min, n_max, NULL,#n, __FILE__, __LINE__)
-
/*! \brief
* Returns error message corresponding to a string key.
*
/*! \} */
/*! \brief
- * Sets an error handler for gmx_fatal() and other fatal error routines.
+ * Implementation for range_check() and range_check_mesg().
*
- * The default handler prints the message.
- * \Gromacs will terminate the program after the error handler returns.
- * To make gmx_fatal_collective() work, the error handler should not terminate
- * the program, as it cannot know what is the desired way of termination.
- * The string passed to the handler may be a multi-line string.
+ * \p warn_str can be NULL.
+ */
+void _range_check(int n, int n_min, int n_max, const char *warn_str,
+ const char *var,
+ const char *file, int line);
+
+/*! \brief
+ * Checks that a variable is within a range.
*
- * \see gmx_fatal()
+ * If \p n is not in range [n_min, n_max), a fatal error is raised.
+ * \p n_min is inclusive, but \p n_max is not.
*/
-void
-set_gmx_error_handler(void (*func)(const char *msg));
+#define range_check_mesg(n, n_min, n_max, str) _range_check(n, n_min, n_max, str,#n, __FILE__, __LINE__)
+
+/*! \brief
+ * Checks that a variable is within a range.
+ *
+ * This works as range_check_mesg(), but with a default error message.
+ */
+#define range_check(n, n_min, n_max) _range_check(n, n_min, n_max, NULL,#n, __FILE__, __LINE__)
/*! \brief
* Prints a warning message to stderr.
} t_pstack;
static t_pstack *pstack = NULL;
-static gmx_bool bUnbuffered = FALSE;
+static bool bUnbuffered = false;
/* this linked list is an intrinsically globally shared object, so we have
to protect it with mutexes */
static tMPI_Thread_mutex_t pstack_mutex = TMPI_THREAD_MUTEX_INITIALIZER;
-void no_buffers(void)
+void gmx_disable_file_buffering(void)
{
- bUnbuffered = TRUE;
+ bUnbuffered = true;
}
void push_ps(FILE *fp)
typedef gmx_int64_t gmx_off_t;
/*! \brief
- * Turn off buffering of files (which is default) for debugging purposes.
+ * Turn off buffering for output files (which is default) for debugging
+ * purposes.
*
* This only has effect on files opened with gmx_ffopen().
*/
-void no_buffers(void);
+void gmx_disable_file_buffering(void);
/*! \brief
* Check whether a path exists.