Code beautification with uncrustify
[alexxy/gromacs.git] / src / gromacs / commandline / cmdlineparser.cpp
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 /*! \internal \file
32  * \brief
33  * Implements gmx::CommandLineParser.
34  *
35  * \author Teemu Murtola <teemu.murtola@cbr.su.se>
36  * \ingroup module_commandline
37  */
38 #include "cmdlineparser.h"
39
40 #include <cctype>
41
42 #include <string>
43 #include <vector>
44
45 #include "gromacs/options/optionsassigner.h"
46 #include "gromacs/utility/exceptions.h"
47
48 namespace gmx
49 {
50
51 /********************************************************************
52  * CommandLineParser::Impl
53  */
54
55 /*! \internal \brief
56  * Private implementation class for CommandLineParser.
57  *
58  * \ingroup module_commandline
59  */
60 class CommandLineParser::Impl
61 {
62     public:
63         //! Sets the options object to parse to.
64         explicit Impl(Options *options);
65
66         //! Helper object for assigning the options.
67         OptionsAssigner         assigner_;
68 };
69
70 CommandLineParser::Impl::Impl(Options *options)
71     : assigner_(options)
72 {
73     assigner_.setAcceptBooleanNoPrefix(true);
74     assigner_.setNoStrictSectioning(true);
75 }
76
77 /********************************************************************
78  * CommandLineParser
79  */
80
81 CommandLineParser::CommandLineParser(Options *options)
82     : impl_(new Impl(options))
83 {
84 }
85
86 CommandLineParser::~CommandLineParser()
87 {
88 }
89
90 void CommandLineParser::parse(int *argc, char *argv[])
91 {
92     std::vector<std::string> commandLine;
93     for (int i = 0; i < *argc; ++i)
94     {
95         commandLine.push_back(argv[i]);
96     }
97     parse(&commandLine);
98 }
99
100 void CommandLineParser::parse(std::vector<std::string> *commandLine)
101 {
102     ExceptionInitializer errors("Invalid command-line options");
103     std::string          currentContext;
104     // Start in the discard phase to skip options that can't be understood.
105     bool                 bDiscard = true;
106
107     impl_->assigner_.start();
108     std::vector<std::string>::const_iterator arg;
109     for (arg = commandLine->begin() + 1; arg != commandLine->end(); ++arg)
110     {
111         // Lone '-' and numbers are passed as values.
112         if ((*arg)[0] == '-' && std::isalpha((*arg)[1]))
113         {
114             if (!bDiscard)
115             {
116                 try
117                 {
118                     impl_->assigner_.finishOption();
119                 }
120                 catch (UserInputError &ex)
121                 {
122                     ex.prependContext(currentContext);
123                     errors.addCurrentExceptionAsNested();
124                 }
125                 currentContext.clear();
126             }
127             currentContext = "In command-line option " + *arg;
128             bDiscard       = false;
129             try
130             {
131                 const char *name = arg->c_str() + 1;
132                 impl_->assigner_.startOption(name);
133             }
134             catch (UserInputError &ex)
135             {
136                 bDiscard = true;
137                 ex.prependContext(currentContext);
138                 errors.addCurrentExceptionAsNested();
139                 currentContext.clear();
140             }
141         }
142         else if (!bDiscard)
143         {
144             try
145             {
146                 impl_->assigner_.appendValue(*arg);
147             }
148             catch (UserInputError &ex)
149             {
150                 ex.prependContext(currentContext);
151                 errors.addCurrentExceptionAsNested();
152             }
153         }
154     }
155     if (!bDiscard)
156     {
157         try
158         {
159             impl_->assigner_.finishOption();
160         }
161         catch (UserInputError &ex)
162         {
163             ex.prependContext(currentContext);
164             errors.addCurrentExceptionAsNested();
165         }
166     }
167     impl_->assigner_.finish();
168     if (errors.hasNestedExceptions())
169     {
170         // TODO: This exception type may not always be appropriate.
171         GMX_THROW(InvalidInputError(errors));
172     }
173 }
174
175 } // namespace gmx