2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 2012,2013, by the GROMACS development team, led by
5 * David van der Spoel, Berk Hess, Erik Lindahl, and including many
6 * others, as listed in the AUTHORS file in the top-level source
7 * directory and at http://www.gromacs.org.
9 * GROMACS is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Lesser General Public License
11 * as published by the Free Software Foundation; either version 2.1
12 * of the License, or (at your option) any later version.
14 * GROMACS is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with GROMACS; if not, see
21 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
22 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 * If you want to redistribute modifications to GROMACS, please
25 * consider that scientific software is very special. Version
26 * control is crucial - bugs must be traceable. We will be happy to
27 * consider code for inclusion in the official distribution, but
28 * derived work must not be called official GROMACS. Details are found
29 * in the README & COPYING files - if they are missing, get the
30 * official version at http://www.gromacs.org.
32 * To help us fund GROMACS development, we humbly ask that you cite
33 * the research papers on the package. Check out http://www.gromacs.org.
37 * Implements gmx::ProgramInfo.
39 * \author Teemu Murtola <teemu.murtola@gmail.com>
40 * \ingroup module_utility
42 #include "programinfo.h"
44 // For GMX_BINARY_SUFFIX
55 #include <boost/scoped_ptr.hpp>
57 #include "gromacs/legacyheaders/futil.h"
58 #include "gromacs/legacyheaders/thread_mpi/mutex.h"
60 #include "gromacs/utility/exceptions.h"
61 #include "gromacs/utility/gmxassert.h"
62 #include "gromacs/utility/path.h"
63 #include "gromacs/utility/stringutil.h"
71 //! Mutex for updates to the global program info objects.
72 tMPI::mutex g_programInfoMutex;
73 //! Global program info; stores the object initialized with ProgramInfo::init().
74 boost::scoped_ptr<ProgramInfo> g_programInfo;
77 * Quotes a string if it contains spaces.
79 std::string quoteIfNecessary(const char *str)
81 const bool bSpaces = (std::strchr(str, ' ') != NULL);
84 return formatString("'%s'", str);
91 /********************************************************************
95 class ProgramInfo::Impl
99 Impl(const char *realBinaryName, int argc, const char *const argv[]);
101 std::string realBinaryName_;
102 std::string fullInvokedProgram_;
103 std::string programName_;
104 std::string invariantProgramName_;
105 std::string commandLine_;
106 std::string displayName_;
107 mutable tMPI::mutex displayNameMutex_;
110 ProgramInfo::Impl::Impl()
111 : realBinaryName_("GROMACS"), fullInvokedProgram_("GROMACS"),
112 programName_("GROMACS"), invariantProgramName_("GROMACS")
116 ProgramInfo::Impl::Impl(const char *realBinaryName,
117 int argc, const char *const argv[])
118 : realBinaryName_(realBinaryName != NULL ? realBinaryName : ""),
119 fullInvokedProgram_(argc != 0 ? argv[0] : ""),
120 programName_(Path::splitToPathAndFilename(fullInvokedProgram_).second)
122 // Temporary hack to make things work on Windows while waiting for #950.
123 // Some places in the existing code expect to have DIR_SEPARATOR in all
124 // input paths, but Windows may also give '/' (and does that, e.g., for
125 // tests invoked through CTest).
126 // When removing this, remove also the #include "futil.h".
127 if (DIR_SEPARATOR == '\\')
129 std::replace(fullInvokedProgram_.begin(), fullInvokedProgram_.end(),
132 programName_ = stripSuffixIfPresent(programName_, ".exe");
133 invariantProgramName_ = programName_;
134 #ifdef GMX_BINARY_SUFFIX
135 invariantProgramName_ =
136 stripSuffixIfPresent(invariantProgramName_, GMX_BINARY_SUFFIX);
138 if (realBinaryName == NULL)
140 realBinaryName_ = invariantProgramName_;
143 commandLine_ = quoteIfNecessary(programName_.c_str());
144 for (int i = 1; i < argc; ++i)
146 commandLine_.append(" ");
147 commandLine_.append(quoteIfNecessary(argv[i]));
151 /********************************************************************
156 const ProgramInfo &ProgramInfo::getInstance()
158 tMPI::lock_guard<tMPI::mutex> lock(g_programInfoMutex);
159 if (g_programInfo.get() == NULL)
161 static ProgramInfo fallbackInfo;
164 return *g_programInfo;
168 ProgramInfo &ProgramInfo::init(int argc, const char *const argv[])
170 return init(NULL, argc, argv);
174 ProgramInfo &ProgramInfo::init(const char *realBinaryName,
175 int argc, const char *const argv[])
179 tMPI::lock_guard<tMPI::mutex> lock(g_programInfoMutex);
180 if (g_programInfo.get() == NULL)
182 g_programInfo.reset(new ProgramInfo(realBinaryName, argc, argv));
184 return *g_programInfo;
186 catch (const std::exception &ex)
188 printFatalErrorMessage(stderr, ex);
189 std::exit(processExceptionAtExit(ex));
193 ProgramInfo::ProgramInfo()
198 ProgramInfo::ProgramInfo(const char *realBinaryName)
199 : impl_(new Impl(realBinaryName, 1, &realBinaryName))
203 ProgramInfo::ProgramInfo(int argc, const char *const argv[])
204 : impl_(new Impl(NULL, argc, argv))
208 ProgramInfo::ProgramInfo(const char *realBinaryName,
209 int argc, const char *const argv[])
210 : impl_(new Impl(realBinaryName, argc, argv))
214 ProgramInfo::~ProgramInfo()
218 void ProgramInfo::setDisplayName(const std::string &name)
220 tMPI::lock_guard<tMPI::mutex> lock(impl_->displayNameMutex_);
221 GMX_RELEASE_ASSERT(impl_->displayName_.empty(),
222 "Can only set display name once");
223 impl_->displayName_ = name;
226 const std::string &ProgramInfo::realBinaryName() const
228 return impl_->realBinaryName_;
231 const std::string &ProgramInfo::programNameWithPath() const
233 return impl_->fullInvokedProgram_;
236 const std::string &ProgramInfo::programName() const
238 return impl_->programName_;
241 const std::string &ProgramInfo::invariantProgramName() const
243 return impl_->invariantProgramName_;
246 const std::string &ProgramInfo::displayName() const
248 tMPI::lock_guard<tMPI::mutex> lock(impl_->displayNameMutex_);
249 return impl_->displayName_.empty()
250 ? impl_->programName_
251 : impl_->displayName_;
254 const std::string &ProgramInfo::commandLine() const
256 return impl_->commandLine_;