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 //! Mutex for updates to the global program info objects.
66 tMPI::mutex g_programInfoMutex;
67 //! Partially filled program info, needed to support set_program_name().
68 boost::scoped_ptr<ProgramInfo> g_partialProgramInfo;
69 //! Global program info; stores the object initialized with ProgramInfo::init().
70 boost::scoped_ptr<ProgramInfo> g_programInfo;
73 /********************************************************************
77 class ProgramInfo::Impl
81 Impl(const char *realBinaryName, int argc, const char *const argv[]);
83 std::string realBinaryName_;
84 std::string fullInvokedProgram_;
85 std::string programName_;
86 std::string invariantProgramName_;
87 std::string commandLine_;
90 ProgramInfo::Impl::Impl()
91 : realBinaryName_("GROMACS"), fullInvokedProgram_("GROMACS"),
92 programName_("GROMACS"), invariantProgramName_("GROMACS")
96 ProgramInfo::Impl::Impl(const char *realBinaryName,
97 int argc, const char *const argv[])
98 : realBinaryName_(realBinaryName != NULL ? realBinaryName : ""),
99 fullInvokedProgram_(argc != 0 ? argv[0] : ""),
100 programName_(Path::splitToPathAndFilename(fullInvokedProgram_).second)
102 // Temporary hack to make things work on Windows while waiting for #950.
103 // Some places in the existing code expect to have DIR_SEPARATOR in all
104 // input paths, but Windows may also give '/' (and does that, e.g., for
105 // tests invoked through CTest).
106 // When removing this, remove also the #include "futil.h".
107 if (DIR_SEPARATOR == '\\')
109 std::replace(fullInvokedProgram_.begin(), fullInvokedProgram_.end(),
112 programName_ = stripSuffixIfPresent(programName_, ".exe");
113 invariantProgramName_ = programName_;
114 #ifdef GMX_BINARY_SUFFIX
115 invariantProgramName_ =
116 stripSuffixIfPresent(invariantProgramName_, GMX_BINARY_SUFFIX);
118 if (realBinaryName == NULL)
120 realBinaryName_ = invariantProgramName_;
123 for (int i = 0; i < argc; ++i)
127 commandLine_.append(" ");
129 const char *arg = argv[i];
130 bool bSpaces = (std::strchr(arg, ' ') != NULL);
133 commandLine_.append("'");
135 commandLine_.append(arg);
138 commandLine_.append("'");
143 /********************************************************************
148 const ProgramInfo &ProgramInfo::getInstance()
150 tMPI::lock_guard<tMPI::mutex> lock(g_programInfoMutex);
151 if (g_programInfo.get() == NULL)
153 if (g_partialProgramInfo.get() != NULL)
155 return *g_partialProgramInfo;
157 static ProgramInfo fallbackInfo;
160 return *g_programInfo;
164 const ProgramInfo &ProgramInfo::init(int argc, const char *const argv[])
166 return init(NULL, argc, argv);
170 const ProgramInfo &ProgramInfo::init(const char *realBinaryName,
171 int argc, const char *const argv[])
175 tMPI::lock_guard<tMPI::mutex> lock(g_programInfoMutex);
176 if (g_programInfo.get() == NULL)
178 // TODO: Remove this hack with negative argc once there is no need for
179 // set_program_name().
182 if (g_partialProgramInfo.get() == NULL)
184 g_partialProgramInfo.reset(
185 new ProgramInfo(realBinaryName, -argc, argv));
187 return *g_partialProgramInfo;
189 g_programInfo.reset(new ProgramInfo(realBinaryName, argc, argv));
191 return *g_programInfo;
193 catch (const std::exception &ex)
195 printFatalErrorMessage(stderr, ex);
200 ProgramInfo::ProgramInfo()
205 ProgramInfo::ProgramInfo(const char *realBinaryName)
206 : impl_(new Impl(realBinaryName, 1, &realBinaryName))
210 ProgramInfo::ProgramInfo(int argc, const char *const argv[])
211 : impl_(new Impl(NULL, argc, argv))
215 ProgramInfo::ProgramInfo(const char *realBinaryName,
216 int argc, const char *const argv[])
217 : impl_(new Impl(realBinaryName, argc, argv))
221 ProgramInfo::~ProgramInfo()
225 const std::string &ProgramInfo::realBinaryName() const
227 return impl_->realBinaryName_;
230 const std::string &ProgramInfo::programNameWithPath() const
232 return impl_->fullInvokedProgram_;
235 const std::string &ProgramInfo::programName() const
237 return impl_->programName_;
240 const std::string &ProgramInfo::invariantProgramName() const
242 return impl_->invariantProgramName_;
245 const std::string &ProgramInfo::commandLine() const
247 return impl_->commandLine_;