Merge "Detect module name from symlinks."
[alexxy/gromacs.git] / src / gromacs / commandline / cmdlinemodulemanager.h
1 /*
2  *
3  *                This source code is part of
4  *
5  *                 G   R   O   M   A   C   S
6  *
7  *          GROningen MAchine for Chemical Simulations
8  *
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.
13
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.
18  *
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.
25  *
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.
28  *
29  * For more info, check our website at http://www.gromacs.org
30  */
31 /*! \file
32  * \brief
33  * Declares gmx::CommandLineModuleManager.
34  *
35  * \author Teemu Murtola <teemu.murtola@cbr.su.se>
36  * \inpublicapi
37  * \ingroup module_commandline
38  */
39 #ifndef GMX_COMMANDLINE_CMDLINEMODULEMANAGER_H
40 #define GMX_COMMANDLINE_CMDLINEMODULEMANAGER_H
41
42 #include "../utility/common.h"
43 #include "../utility/uniqueptr.h"
44
45 namespace gmx
46 {
47
48 class CommandLineModuleInterface;
49
50 //! Smart pointer type for managing a CommandLineModuleInterface.
51 typedef gmx_unique_ptr<CommandLineModuleInterface>::type
52         CommandLineModulePointer;
53
54 namespace internal
55 {
56 class CommandLineHelpModule;
57 }
58
59 /*! \brief
60  * Implements a wrapper command-line interface for multiple modules.
61  *
62  * Typical usage:
63  * \code
64 int
65 main(int argc, char *argv[])
66 {
67     CopyRight(stderr, argv[0]);
68     try
69     {
70         gmx::CommandLineModuleManager manager("g_ana");
71         // <register all necessary modules>
72         return manager.run(argc, argv);
73     }
74     catch (const std::exception &ex)
75     {
76         fprintf(stderr, "%s", gmx::formatErrorMessage(ex).c_str());
77         return 1;
78     }
79 }
80  * \endcode
81  *
82  * \inpublicapi
83  * \ingroup module_commandline
84  */
85 class CommandLineModuleManager
86 {
87     public:
88         /*! \brief
89          * Initializes a command-line module manager.
90          *
91          * \param[in] realBinaryName  Name of the binary that this manager runs
92          *     (without Gromacs binary suffix or .exe on Windows).
93          * \throws    std::bad_alloc if out of memory.
94          *
95          * The binary name is used to detect when the binary is run through a
96          * symlink, and automatically invoke a matching module in such a case.
97          */
98         explicit CommandLineModuleManager(const char *realBinaryName);
99         ~CommandLineModuleManager();
100
101         /*! \brief
102          * Adds a given module to this manager.
103          *
104          * \param   module  Module to add.
105          * \throws  std::bad_alloc if out of memory.
106          *
107          * The manager takes ownership of the object.
108          *
109          * This method is public mostly for testing purposes; for typical uses,
110          * registerModule() is a more convenient way of adding modules.
111          *
112          * \see registerModule()
113          */
114         void addModule(CommandLineModulePointer module);
115         /*! \brief
116          * Registers a module of a certain type to this manager.
117          *
118          * \tparam  Module  Type of module to register.
119          * \throws  std::bad_alloc if out of memory.
120          *
121          * \p Module must be default-constructible and implement
122          * CommandLineModuleInterface.
123          *
124          * This method is provided as a convenient alternative to addModule()
125          * for cases where each module is implemented by a different type
126          * (which should be the case for typical situations outside unit
127          * tests).
128          */
129         template <class Module>
130         void registerModule()
131         {
132             addModule(CommandLineModulePointer(new Module));
133         }
134
135         /*! \brief
136          * Runs a module based on given command line.
137          *
138          * \param[in] argc  Number of elements in \p argv.
139          * \param[in] argv  Command-line arguments.
140          * \throws   unspecified  Throws any exception that the selected module
141          *      throws.
142          * \returns  Exit code for the program.
143          * \retval   0 on successful termination.
144          * \retval   2 if no module is specified, or if the module is not found.
145          *
146          * Runs the module whose name matches \p argv[1].
147          */
148         int run(int argc, char *argv[]);
149
150     private:
151         class Impl;
152
153         PrivateImplPointer<Impl> impl_;
154
155         /*! \brief
156          * Needed to access information about registered modules etc.
157          */
158         friend class internal::CommandLineHelpModule;
159 };
160
161 } // namespace gmx
162
163 #endif