3 * This source code is part of
7 * GROningen MAchine for Chemical Simulations
9 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
10 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
11 * Copyright (c) 2001-2009, The GROMACS development team,
12 * check out http://www.gromacs.org for more information.
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
19 * If you want to redistribute modifications, please consider that
20 * scientific software is very special. Version control is crucial -
21 * bugs must be traceable. We will be happy to consider code for
22 * inclusion in the official distribution, but derived work must not
23 * be called official GROMACS. Details are found in the README & COPYING
24 * files - if they are missing, get the official version at www.gromacs.org.
26 * To help us fund GROMACS development, we humbly ask that you cite
27 * the papers on the package - you can find them in the top README file.
29 * For more info, check our website at http://www.gromacs.org
33 * Implements gmx::ProgramInfo.
35 * \author Teemu Murtola <teemu.murtola@cbr.su.se>
36 * \ingroup module_utility
38 #include "programinfo.h"
40 // For GMX_BINARY_SUFFIX
51 #include <boost/scoped_ptr.hpp>
53 #include "gromacs/legacyheaders/futil.h"
54 #include "gromacs/legacyheaders/thread_mpi/mutex.h"
56 #include "gromacs/utility/exceptions.h"
57 #include "gromacs/utility/path.h"
58 #include "gromacs/utility/stringutil.h"
65 tMPI::mutex g_programInfoMutex;
66 //! Partially filled program info, needed to support set_program_name().
67 boost::scoped_ptr<ProgramInfo> g_partialProgramInfo;
68 boost::scoped_ptr<ProgramInfo> g_programInfo;
71 /********************************************************************
75 class ProgramInfo::Impl
79 Impl(const char *realBinaryName, int argc, const char *const argv[]);
81 std::string realBinaryName_;
82 std::string fullInvokedProgram_;
83 std::string programName_;
84 std::string invariantProgramName_;
85 std::string commandLine_;
88 ProgramInfo::Impl::Impl()
89 : realBinaryName_("GROMACS"), fullInvokedProgram_("GROMACS"),
90 programName_("GROMACS"), invariantProgramName_("GROMACS")
94 ProgramInfo::Impl::Impl(const char *realBinaryName,
95 int argc, const char *const argv[])
96 : realBinaryName_(realBinaryName != NULL ? realBinaryName : ""),
97 fullInvokedProgram_(argc != 0 ? argv[0] : ""),
98 programName_(Path::splitToPathAndFilename(fullInvokedProgram_).second)
100 // Temporary hack to make things work on Windows while waiting for #950.
101 // Some places in the existing code expect to have DIR_SEPARATOR in all
102 // input paths, but Windows may also give '/' (and does that, e.g., for
103 // tests invoked through CTest).
104 // When removing this, remove also the #include "futil.h".
105 if (DIR_SEPARATOR == '\\')
107 std::replace(fullInvokedProgram_.begin(), fullInvokedProgram_.end(),
110 programName_ = stripSuffixIfPresent(programName_, ".exe");
111 invariantProgramName_ = programName_;
112 #ifdef GMX_BINARY_SUFFIX
113 invariantProgramName_ =
114 stripSuffixIfPresent(invariantProgramName_, GMX_BINARY_SUFFIX);
116 if (realBinaryName == NULL)
118 realBinaryName_ = invariantProgramName_;
121 for (int i = 0; i < argc; ++i)
125 commandLine_.append(" ");
127 const char *arg = argv[i];
128 bool bSpaces = (std::strchr(arg, ' ') != NULL);
131 commandLine_.append("'");
133 commandLine_.append(arg);
136 commandLine_.append("'");
141 /********************************************************************
146 const ProgramInfo &ProgramInfo::getInstance()
148 tMPI::lock_guard<tMPI::mutex> lock(g_programInfoMutex);
149 if (g_programInfo.get() == NULL)
151 if (g_partialProgramInfo.get() != NULL)
153 return *g_partialProgramInfo;
155 static ProgramInfo fallbackInfo;
158 return *g_programInfo;
162 const ProgramInfo &ProgramInfo::init(int argc, const char *const argv[])
164 return init(NULL, argc, argv);
168 const ProgramInfo &ProgramInfo::init(const char *realBinaryName,
169 int argc, const char *const argv[])
173 tMPI::lock_guard<tMPI::mutex> lock(g_programInfoMutex);
174 if (g_programInfo.get() == NULL)
176 // TODO: Remove this hack with negative argc once there is no need for
177 // set_program_name().
180 if (g_partialProgramInfo.get() == NULL)
182 g_partialProgramInfo.reset(
183 new ProgramInfo(realBinaryName, -argc, argv));
185 return *g_partialProgramInfo;
187 g_programInfo.reset(new ProgramInfo(realBinaryName, argc, argv));
189 return *g_programInfo;
191 catch (const std::exception &ex)
193 printFatalErrorMessage(stderr, ex);
198 ProgramInfo::ProgramInfo()
203 ProgramInfo::ProgramInfo(const char *realBinaryName)
204 : impl_(new Impl(realBinaryName, 1, &realBinaryName))
208 ProgramInfo::ProgramInfo(int argc, const char *const argv[])
209 : impl_(new Impl(NULL, argc, argv))
213 ProgramInfo::ProgramInfo(const char *realBinaryName,
214 int argc, const char *const argv[])
215 : impl_(new Impl(realBinaryName, argc, argv))
219 ProgramInfo::~ProgramInfo()
223 const std::string &ProgramInfo::realBinaryName() const
225 return impl_->realBinaryName_;
228 const std::string &ProgramInfo::programNameWithPath() const
230 return impl_->fullInvokedProgram_;
233 const std::string &ProgramInfo::programName() const
235 return impl_->programName_;
238 const std::string &ProgramInfo::invariantProgramName() const
240 return impl_->invariantProgramName_;
243 const std::string &ProgramInfo::commandLine() const
245 return impl_->commandLine_;