- The ProgramInfo class now stores the full command line.
Moved functionality to add quotes to arguments with spaces from
gmx::test::CommandLine to ProgramInfo.
- ProgramInfo initialization is now protected by a mutex for
completeness.
- oenv.c and statutil.c now use ProgramInfo internally to store/return
the binary name and command line. Removes duplicate implementations
of this functionality. Required changing the return values of
ProgramInfo methods from std::string values to const references.
- Removed many unnecessary #include directives from these two files.
- Fixed warnings that were produced from these files when switching them
to C++ compilation (one cppcheck warning suppressed for now).
- Add a temporary hack for Windows to try to make get_libdir() work for
tests that are run through CTest.
Helps with #950.
Change-Id: I1bfd4231b8b7055d0a014b41be67a7c1c99e36b0
fun:inflateInit2_
}
-{
- set_program_name
- Memcheck:Leak
- ...
- fun:set_program_name
-}
-
-{
- set_command_line
- Memcheck:Leak
- ...
- fun:set_command_line
-}
-
{
read_tps_conf
Memcheck:Leak
* And Hey:
* GROningen Mixture of Alchemy and Childrens' Stories
*/
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
+#include "oenv.h"
-#include <ctype.h>
-#include <assert.h>
-#include "sysstuff.h"
-#include "macros.h"
-#include "string2.h"
#include "smalloc.h"
-#include "pbc.h"
-#include "statutil.h"
-#include "names.h"
-#include "vec.h"
-#include "futil.h"
-#include "wman.h"
-#include "tpxio.h"
-#include "gmx_fatal.h"
-#include "network.h"
-#include "vec.h"
-#include "mtop_util.h"
-#include "gmxfio.h"
-#include "oenv.h"
-#ifdef GMX_THREAD_MPI
-#include "thread_mpi.h"
-#endif
+#include "gromacs/utility/exceptions.h"
+#include "gromacs/utility/programinfo.h"
struct output_env
{
+ output_env()
+ {
+ setDefaults();
+ }
+ output_env(int argc, const char *const argv[])
+ : programInfo(argc, argv)
+ {
+ setDefaults();
+ }
+
+ void setDefaults()
+ {
+ time_unit = time_ps;
+ view = FALSE;
+ xvg_format = exvgNONE;
+ verbosity = 0;
+ debug_level = 0;
+ }
+
+ gmx::ProgramInfo programInfo;
+
time_unit_t time_unit; /* the time unit, enum defined in oenv.h */
gmx_bool view; /* view of file requested */
xvg_format_t xvg_format; /* xvg output format, enum defined in oenv.h */
int verbosity; /* The level of verbosity for this program */
int debug_level; /* the debug level */
-
- char *program_name; /* the program name */
- char *cmd_line; /* the re-assembled command line */
};
/* The source code in this file should be thread-safe.
"ms", "s", NULL };
-
/***** OUTPUT_ENV MEMBER FUNCTIONS ******/
void output_env_init(output_env_t *oenvp, int argc, char *argv[],
time_unit_t tmu, gmx_bool view, xvg_format_t xvg_format,
int verbosity, int debug_level)
{
- int i;
- int cmdlength=0;
- char *argvzero=NULL;
- output_env_t oenv;
-
- snew(oenv, 1);
- *oenvp = oenv;
- oenv->time_unit = tmu;
- oenv->view=view;
- oenv->xvg_format = xvg_format;
- oenv->verbosity=verbosity;
- oenv->debug_level=debug_level;
- oenv->program_name=NULL;
-
- if (argv)
- {
- argvzero=argv[0];
- assert(argvzero);
- }
- /* set program name */
- if (argvzero)
- {
- oenv->program_name=strdup(argvzero);
- }
- if (oenv->program_name == NULL)
- oenv->program_name = strdup("GROMACS");
-
- /* copy command line */
- if (argv)
+ try
{
- cmdlength = strlen(argvzero);
- for (i=1; i<argc; i++)
- {
- cmdlength += strlen(argv[i]);
- }
- }
-
- /* Fill the cmdline string */
- snew(oenv->cmd_line,cmdlength+argc+1);
- if (argv)
- {
- for (i=0; i<argc; i++)
- {
- strcat(oenv->cmd_line,argv[i]);
- strcat(oenv->cmd_line," ");
- }
+ output_env_t oenv = new output_env(argc, argv);
+ *oenvp = oenv;
+ oenv->time_unit = tmu;
+ oenv->view = view;
+ oenv->xvg_format = xvg_format;
+ oenv->verbosity = verbosity;
+ oenv->debug_level = debug_level;
}
+ GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
}
-
void output_env_init_default(output_env_t *oenvp)
{
- output_env_init(oenvp, 0, NULL, time_ps, FALSE, exvgNONE, 0, 0);
+ try
+ {
+ output_env_t oenv = new output_env();
+ *oenvp = oenv;
+ }
+ GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
}
-
void output_env_done(output_env_t oenv)
{
- sfree(oenv->program_name);
- sfree(oenv->cmd_line);
- sfree(oenv);
+ delete oenv;
}
-
int output_env_get_verbosity(const output_env_t oenv)
{
return oenv->verbosity;
return oenv->debug_level;
}
-
const char *output_env_get_time_unit(const output_env_t oenv)
{
return time_units_str[oenv->time_unit];
return label;
}
-
real output_env_get_time_factor(const output_env_t oenv)
{
return timefactors[oenv->time_unit];
return time*timefactors[oenv->time_unit];
}
-
void output_env_conv_times(const output_env_t oenv, int n, real *time)
{
int i;
const char *output_env_get_program_name(const output_env_t oenv)
{
- return oenv->program_name;
+ try
+ {
+ return oenv->programInfo.programNameWithPath().c_str();
+ }
+ GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
}
const char *output_env_get_short_program_name(const output_env_t oenv)
{
- const char *pr,*ret;
- pr=ret=oenv->program_name;
- if ((pr=strrchr(ret,DIR_SEPARATOR)) != NULL)
- ret=pr+1;
- return ret;
+ try
+ {
+ return oenv->programInfo.programName().c_str();
+ }
+ GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
}
-
-
const char *output_env_get_cmd_line(const output_env_t oenv)
{
- return oenv->cmd_line;
+ try
+ {
+ return oenv->programInfo.commandLine().c_str();
+ }
+ GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
}
-
-
#include "string2.h"
#include "vec.h"
#include "macros.h"
+#include "wman.h"
/* The source code in this file should be thread-safe.
Please keep it that way. */
#include <config.h>
#endif
-#include <ctype.h>
-#include <assert.h>
+#include <cctype>
+#include <cmath>
+#include <cstdlib>
+
#include "copyrite.h"
#include "sysstuff.h"
#include "macros.h"
#include "string2.h"
#include "smalloc.h"
-#include "pbc.h"
#include "statutil.h"
-#include "names.h"
-#include "vec.h"
-#include "futil.h"
#include "wman.h"
#include "tpxio.h"
#include "gmx_fatal.h"
#include "network.h"
-#include "vec.h"
-#include "mtop_util.h"
#include "gmxfio.h"
-#ifdef GMX_THREAD_MPI
-#include "thread_mpi.h"
-#endif
+#include "gromacs/utility/exceptions.h"
+#include "gromacs/utility/gmxassert.h"
+#include "gromacs/utility/programinfo.h"
+
+#include "thread_mpi/threads.h"
#ifdef HAVE_UNISTD_H
#include <unistd.h>
*
******************************************************************/
-/* inherently globally shared names: */
-static const char *program_name=NULL;
-static char *cmd_line=NULL;
-
-#ifdef GMX_THREAD_MPI
-/* For now, some things here are simply not re-entrant, so
- we have to actively lock them. */
-static tMPI_Thread_mutex_t init_mutex=TMPI_THREAD_MUTEX_INITIALIZER;
-#endif
-
-
/****************************************************************
*
* E X P O R T E D F U N C T I O N S
const char *ShortProgram(void)
{
- const char *pr,*ret;
-#ifdef GMX_THREAD_MPI
- tMPI_Thread_mutex_lock(&init_mutex);
-#endif
- pr=ret=program_name;
-#ifdef GMX_THREAD_MPI
- tMPI_Thread_mutex_unlock(&init_mutex);
-#endif
- if (ret == NULL)
- return "GROMACS";
- if ((pr=strrchr(ret,DIR_SEPARATOR)) != NULL)
- ret=pr+1;
- return ret;
+ try
+ {
+ return gmx::ProgramInfo::getInstance().programName().c_str();
+ }
+ GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
}
const char *Program(void)
{
- const char *ret;
-#ifdef GMX_THREAD_MPI
- tMPI_Thread_mutex_lock(&init_mutex);
-#endif
- ret=program_name;
-#ifdef GMX_THREAD_MPI
- tMPI_Thread_mutex_unlock(&init_mutex);
-#endif
- return ret;
+ try
+ {
+ return gmx::ProgramInfo::getInstance().programNameWithPath().c_str();
+ }
+ GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
}
const char *command_line(void)
{
- const char *ret;
-#ifdef GMX_THREAD_MPI
- tMPI_Thread_mutex_lock(&init_mutex);
-#endif
- ret=cmd_line;
-#ifdef GMX_THREAD_MPI
- tMPI_Thread_mutex_unlock(&init_mutex);
-#endif
- return ret;
-}
-
-void set_program_name(const char *argvzero)
-{
-#ifdef GMX_THREAD_MPI
- tMPI_Thread_mutex_lock(&init_mutex);
-#endif
- if (program_name == NULL)
+ try
{
- program_name = strdup(argvzero);
+ return gmx::ProgramInfo::getInstance().commandLine().c_str();
}
- if (program_name == NULL)
- program_name="GROMACS";
-#ifdef GMX_THREAD_MPI
- tMPI_Thread_mutex_unlock(&init_mutex);
-#endif
+ GMX_CATCH_ALL_AND_EXIT_WITH_FATAL_ERROR;
}
-
-void set_command_line(int argc, char *argv[])
+void set_program_name(const char *argvzero)
{
- int i;
- size_t cmdlength;
-
-#ifdef GMX_THREAD_MPI
- tMPI_Thread_mutex_lock(&init_mutex);
-#endif
- if (cmd_line==NULL)
- {
- cmdlength = strlen(argv[0]);
- for (i=1; i<argc; i++)
- {
- cmdlength += strlen(argv[i]);
- }
-
- /* Fill the cmdline string */
- snew(cmd_line,cmdlength+argc+1);
- for (i=0; i<argc; i++)
- {
- strcat(cmd_line,argv[i]);
- strcat(cmd_line," ");
- }
- }
-#ifdef GMX_THREAD_MPI
- tMPI_Thread_mutex_unlock(&init_mutex);
-#endif
-
+ // The negative argc is a hack to make the ProgramInfo overridable in
+ // parse_common_args(), where the full command-line is known.
+ gmx::ProgramInfo::init(-1, &argvzero);
}
/* utility functions */
tol = 2*(bDouble ? GMX_DOUBLE_EPS : GMX_FLOAT_EPS);
- iq = (a - b + tol*a)/c;
+ iq = static_cast<int>((a - b + tol*a)/c);
- if (fabs(a - b - c*iq) <= tol*fabs(a))
+ if (std::fabs(a - b - c*iq) <= tol*std::fabs(a))
return TRUE;
else
return FALSE;
int check_times2(real t,real t0,real tp, real tpp, gmx_bool bDouble)
{
int r;
- real margin;
#ifndef GMX_DOUBLE
/* since t is float, we can not use double precision for bRmod */
bDouble = FALSE;
#endif
- if (t-tp>0 && tp-tpp>0)
- margin = 0.1*min(t-tp,tp-tpp);
- else
- margin = 0;
-
r=-1;
if ((!bTimeSet(TBEGIN) || (t >= rTimeValue(TBEGIN))) &&
(!bTimeSet(TEND) || (t <= rTimeValue(TEND)))) {
static void set_default_time_unit(const char *time_list[], gmx_bool bCanTime)
{
- int i=0,j;
+ int i=0;
const char *select;
if (bCanTime)
static void set_default_xvg_format(const char *xvg_list[])
{
- int i,j;
- const char *select,*tmp;
+ int i;
+ const char *select;
select = getenv("GMX_VIEW_XVG");
if (select == NULL)
static void usage(const char *type,const char *arg)
{
- assert(arg);
+ GMX_ASSERT(arg != NULL, "NULL command-line argument should not occur");
gmx_fatal(FARGS,"Expected %s argument for option %s\n",type,arg);
}
int iscan(int argc,char *argv[],int *i)
{
- int var;
-
- if (argc > (*i)+1) {
- if (!sscanf(argv[++(*i)],"%d",&var))
- usage("an integer",argv[(*i)-1]);
- } else
- usage("an integer",argv[*i]);
-
+ const char *const arg = argv[*i];
+ if (argc <= (*i)+1)
+ {
+ usage("an integer", arg);
+ }
+ const char *const value = argv[++(*i)];
+ char *endptr;
+ int var = std::strtol(value, &endptr, 10);
+ if (*value == '\0' || *endptr != '\0')
+ {
+ usage("an integer", arg);
+ }
return var;
}
gmx_large_int_t istepscan(int argc,char *argv[],int *i)
{
- gmx_large_int_t var;
-
- if (argc > (*i)+1) {
- if (!sscanf(argv[++(*i)],gmx_large_int_pfmt,&var))
- usage("an integer",argv[(*i)-1]);
- } else
- usage("an integer",argv[*i]);
-
+ const char *const arg = argv[*i];
+ if (argc <= (*i)+1)
+ {
+ usage("an integer", arg);
+ }
+ const char *const value = argv[++(*i)];
+ char *endptr;
+ gmx_large_int_t var = str_to_large_int_t(value, &endptr);
+ if (*value == '\0' || *endptr != '\0')
+ {
+ usage("an integer", arg);
+ }
return var;
}
double dscan(int argc,char *argv[],int *i)
{
- double var;
-
- if (argc > (*i)+1) {
- if (!sscanf(argv[++(*i)],"%lf",&var))
- usage("a real",argv[(*i)-1]);
- } else
- usage("a real",argv[*i]);
-
+ const char *const arg = argv[*i];
+ if (argc <= (*i)+1)
+ {
+ usage("a real", arg);
+ }
+ const char *const value = argv[++(*i)];
+ char *endptr;
+ double var = std::strtod(value, &endptr);
+ if (*value == '\0' || *endptr != '\0')
+ {
+ usage("a real", arg);
+ }
return var;
}
if ((int)strlen(ptr) < 70)
fprintf(stderr,"\t%s\n",ptr);
else {
- for(nptr=ptr+70; (nptr != ptr) && (!isspace(*nptr)); nptr--)
+ for(nptr=ptr+70; (nptr != ptr) && (!std::isspace(*nptr)); nptr--)
;
if (nptr == ptr)
fprintf(stderr,"\t%s\n",ptr);
/* This array should match the order of the enum in oenv.h */
const char *time_units[] = { NULL, "fs", "ps", "ns", "us", "ms", "s",
NULL };
- int nicelevel=0,mantp=0,npri=0,debug_level=0,verbose_level=0;
+ int nicelevel=0,debug_level=0,verbose_level=0;
char *deffnm=NULL;
real tbegin=0,tend=0,tdelta=0;
gmx_bool bView=FALSE;
t_pargs *all_pa=NULL;
+#ifdef __sgi
+ int npri=0;
t_pargs npri_pa = { "-npri", FALSE, etINT, {&npri},
"HIDDEN Set non blocking priority (try 128)" };
+#endif
t_pargs nice_pa = { "-nice", FALSE, etINT, {&nicelevel},
"Set the nicelevel" };
t_pargs deffnm_pa = { "-deffnm", FALSE, etSTR, {&deffnm},
#define NPCA_PA asize(pca_pa)
FILE *fp;
gmx_bool bPrint,bExit,bXvgr;
- int i,j,k,npall,max_pa,cmdlength;
- char *ptr,*newdesc;
- const char *envstr;
+ int i,j,k,npall,max_pa;
#define FF(arg) ((Flags & arg)==arg)
- cmdlength = strlen(argv[0]);
/* Check for double arguments */
for (i=1; (i<*argc); i++)
{
- cmdlength += strlen(argv[i]);
- if (argv[i] && (strlen(argv[i]) > 1) && (!isdigit(argv[i][1])))
+ if (argv[i] && (strlen(argv[i]) > 1) && (!std::isdigit(argv[i][1])))
{
for (j=i+1; (j<*argc); j++)
{
}
}
debug_gmx();
- set_program_name(argv[0]);
- set_command_line(*argc, argv);
+ gmx::ProgramInfo::init(*argc, argv);
/* Handle the flags argument, which is a bit field
* The FF macro returns whether or not the bit is set
max_pa = NPCA_PA + EXTRA_PA + npargs+1;
snew(all_pa,max_pa);
- for(i=npall=0; (i<NPCA_PA); i++)
+ for(i=npall=0; (i<static_cast<int>(NPCA_PA)); i++)
npall = add_parg(npall,all_pa,&(pca_pa[i]));
#ifdef __sgi
- envstr = getenv("GMXNPRIALL");
+ const char *envstr = getenv("GMXNPRIALL");
if (envstr)
npri=strtol(envstr,NULL,10);
if (FF(PCA_BE_NICE)) {
#endif
#ifdef HAVE_UNISTD_H
-
#ifndef GMX_NO_NICE
/* The some system, e.g. the catamount kernel on cray xt3 do not have nice(2). */
if (nicelevel != 0 && !bExit)
{
-#ifdef GMX_THREAD_MPI
static gmx_bool nice_set=FALSE; /* only set it once */
+ static tMPI_Thread_mutex_t init_mutex = TMPI_THREAD_MUTEX_INITIALIZER;
tMPI_Thread_mutex_lock(&init_mutex);
if (!nice_set)
{
-#endif
- i=nice(nicelevel); /* assign ret value to avoid warnings */
-#ifdef GMX_THREAD_MPI
+ if (nice(nicelevel) == -1)
+ {
+ /* Do nothing, but use the return value to avoid warnings. */
+ }
nice_set=TRUE;
}
tMPI_Thread_mutex_unlock(&init_mutex);
-#endif
}
#endif
#endif
#ifndef _oenv_h
#define _oenv_h
-#include "typedefs.h"
+#include "types/simple.h"
+#include "types/oenv.h"
#ifdef __cplusplus
extern "C" {
gmx_bool output_env_get_view(const output_env_t oenv);
/* Return TRUE when user requested viewing of the file */
-
xvg_format_t output_env_get_xvg_format(const output_env_t oenv);
/* Returns enum (see above) for xvg output formatting */
const char *output_env_get_short_program_name(const output_env_t oenv);
/* get the short version (without path component) of the program name */
-
-
#ifdef __cplusplus
}
#endif
#ifndef _statutil_h
#define _statutil_h
-#include <stdio.h>
#include "typedefs.h"
#include "filenm.h"
#include "readinp.h"
-#include "wman.h"
#include "pdbio.h"
#include "oenv.h"
#include "gmxfio.h"
-
#ifdef __cplusplus
extern "C" {
#endif
/* Return the name of the program */
const char *command_line(void);
-void set_command_line(int argc, char *argv[]);
/* set the program name to the provided string, but note
* that it must be a real file - we determine the library
* And Hey:
* GRoups of Organic Molecules in ACtion for Science
*/
+#ifndef GMX_TYPES_OENV_H
+#define GMX_TYPES_OENV_H
#ifdef __cplusplus
extern "C" {
#endif
-/* output options opaque type, for functions in statutil.c */
+/* output options opaque type, for functions in statutil.h and oenv.h */
typedef struct output_env *output_env_t;
#ifdef __cplusplus
}
#endif
+#endif
flags.h
gmx_header_config.h
gmxassert.h
+ programinfo.h
stringutil.h
uniqueptr.h)
install(FILES ${UTILITY_PUBLIC_HEADERS}
#include <cstdlib>
#include <cstring>
+#include <algorithm>
#include <string>
#include <boost/scoped_ptr.hpp>
-#include "gromacs/legacyheaders/statutil.h"
+#include "gromacs/legacyheaders/futil.h"
+#include "gromacs/legacyheaders/thread_mpi/mutex.h"
#include "gromacs/utility/exceptions.h"
#include "gromacs/utility/path.h"
namespace
{
+tMPI::mutex g_programInfoMutex;
+//! Partially filled program info, needed to support set_program_name().
+boost::scoped_ptr<ProgramInfo> g_partialProgramInfo;
boost::scoped_ptr<ProgramInfo> g_programInfo;
} // namespace
std::string fullInvokedProgram_;
std::string programName_;
std::string invariantProgramName_;
+ std::string commandLine_;
};
ProgramInfo::Impl::Impl()
- : realBinaryName_("GROMACS"), fullInvokedProgram_("GROMACS")
+ : realBinaryName_("GROMACS"), fullInvokedProgram_("GROMACS"),
+ programName_("GROMACS"), invariantProgramName_("GROMACS")
{
}
ProgramInfo::Impl::Impl(const char *realBinaryName,
int argc, const char *const argv[])
: realBinaryName_(realBinaryName != NULL ? realBinaryName : ""),
- fullInvokedProgram_(argv[0]),
+ fullInvokedProgram_(argc != 0 ? argv[0] : ""),
programName_(Path::splitToPathAndFilename(fullInvokedProgram_).second),
invariantProgramName_(programName_)
{
+ // Temporary hack to make things work on Windows while waiting for #950.
+ // Some places in the existing code expect to have DIR_SEPARATOR in all
+ // input paths, but Windows may also give '/' (and does that, e.g., for
+ // tests invoked through CTest).
+ // When removing this, remove also the #include "futil.h".
+ if (DIR_SEPARATOR == '\\')
+ {
+ std::replace(fullInvokedProgram_.begin(), fullInvokedProgram_.end(),
+ '/', '\\');
+ }
invariantProgramName_ = stripSuffixIfPresent(invariantProgramName_, ".exe");
#ifdef GMX_BINARY_SUFFIX
invariantProgramName_ =
{
realBinaryName_ = invariantProgramName_;
}
+
+ for (int i = 0; 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("'");
+ }
+ }
}
/********************************************************************
// static
const ProgramInfo &ProgramInfo::getInstance()
{
- // TODO: For completeness, this should be thread-safe.
+ tMPI::lock_guard<tMPI::mutex> lock(g_programInfoMutex);
if (g_programInfo.get() == NULL)
{
- g_programInfo.reset(new ProgramInfo());
+ if (g_partialProgramInfo.get() != NULL)
+ {
+ return *g_partialProgramInfo;
+ }
+ static ProgramInfo fallbackInfo;
+ return fallbackInfo;
}
return *g_programInfo;
}
{
try
{
- set_program_name(argv[0]);
- // TODO: Constness should not be cast away.
- set_command_line(argc, const_cast<char **>(argv));
- // TODO: For completeness, this should be thread-safe.
- g_programInfo.reset(new ProgramInfo(realBinaryName, argc, argv));
+ tMPI::lock_guard<tMPI::mutex> lock(g_programInfoMutex);
+ if (g_programInfo.get() == NULL)
+ {
+ // TODO: Remove this hack with negative argc once there is no need for
+ // set_program_name().
+ if (argc < 0)
+ {
+ if (g_partialProgramInfo.get() == NULL)
+ {
+ g_partialProgramInfo.reset(
+ new ProgramInfo(realBinaryName, -argc, argv));
+ }
+ return *g_partialProgramInfo;
+ }
+ g_programInfo.reset(new ProgramInfo(realBinaryName, argc, argv));
+ }
return *g_programInfo;
}
catch (const std::exception &ex)
{
}
-std::string ProgramInfo::realBinaryName() const
+const std::string &ProgramInfo::realBinaryName() const
{
return impl_->realBinaryName_;
}
-std::string ProgramInfo::programNameWithPath() const
+const std::string &ProgramInfo::programNameWithPath() const
{
return impl_->fullInvokedProgram_;
}
-std::string ProgramInfo::programName() const
+const std::string &ProgramInfo::programName() const
{
return impl_->programName_;
}
-std::string ProgramInfo::invariantProgramName() const
+const std::string &ProgramInfo::invariantProgramName() const
{
return impl_->invariantProgramName_;
}
+const std::string &ProgramInfo::commandLine() const
+{
+ return impl_->commandLine_;
+}
+
} // namespace gmx
* \returns The same object as initialized with the last call to init().
* \throws std::bad_alloc if out of memory (only if this is the first
* call and init() has not been called either).
+ * \throws tMPI::system_error on thread synchronization errors.
*/
static const ProgramInfo &getInstance();
/*! \brief
*
* The returned value is comparable to invariantProgramName(), i.e., it
* has suffixes and OS-specific extensions removed.
+ *
+ * Does not throw.
*/
- std::string realBinaryName() const;
+ const std::string &realBinaryName() const;
/*! \brief
* Returns the path and name of the binary as it was invoked.
+ *
+ * Does not throw.
*/
- std::string programNameWithPath() const;
+ const std::string &programNameWithPath() const;
/*! \brief
* Returns the name of the binary as it was invoked without any path.
+ *
+ * Does not throw.
*/
- std::string programName() const;
+ const std::string &programName() const;
/*! \brief
* Returns an invariant name of the binary.
*
* The returned value has OS-specific extensions (.exe on Windows)
* removed, as well as any binary suffix that was configured.
+ *
+ * Does not throw.
+ */
+ const std::string &invariantProgramName() const;
+ /*! \brief
+ * Returns the full command line used to invoke the binary.
+ *
+ * Does not throw.
*/
- std::string invariantProgramName() const;
+ const std::string &commandLine() const;
private:
class Impl;
#include <new>
#include <vector>
+#include "gromacs/utility/programinfo.h"
+
namespace gmx
{
namespace test
std::string CommandLine::toString() const
{
- std::string result;
- for (size_t i = 0; i < impl_->args_.size(); ++i)
- {
- if (i > 0)
- {
- result.append(" ");
- }
- const char *arg = impl_->args_[i];
- bool bSpaces = (std::strchr(arg, ' ') != NULL);
- if (bSpaces)
- {
- result.append("'");
- }
- result.append(arg);
- if (bSpaces)
- {
- result.append("'");
- }
- }
- return result;
+ return ProgramInfo(argc(), argv()).commandLine();
}
} // namespace test