All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
CLTool.cpp
Go to the documentation of this file.
1 /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2  Copyright (c) 2013 The plumed team
3  (see the PEOPLE file at the root of the distribution for a list of names)
4 
5  See http://www.plumed-code.org for more information.
6 
7  This file is part of plumed, version 2.0.
8 
9  plumed is free software: you can redistribute it and/or modify
10  it under the terms of the GNU Lesser General Public License as published by
11  the Free Software Foundation, either version 3 of the License, or
12  (at your option) any later version.
13 
14  plumed 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
17  GNU Lesser General Public License for more details.
18 
19  You should have received a copy of the GNU Lesser General Public License
20  along with plumed. If not, see <http://www.gnu.org/licenses/>.
21 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
22 #include "CLTool.h"
23 
24 namespace PLMD{
25 
27 
28 CLToolOptions::CLToolOptions(const std::string &name):
29 line(1,name),
30 keys(emptyKeys)
31 {
32 }
33 
35 line(co.line),
36 keys(k)
37 {
38 }
39 
41  keys.addFlag("--help/-h",false,"print this help");
42 }
43 
45 name(co.line[0]),
46 keywords(co.keys),
47 inputdata(unset)
48 {
49 }
50 
51 void CLTool::parseFlag( const std::string&key, bool&t ){
52  plumed_massert(keywords.exists(key),"keyword " + key + " has not been registered");
53  plumed_massert(keywords.style(key,"flag"),"keyword " + key + " has not been registered as a flag");
54  plumed_assert(inputData.count(key)>0);
55  if( inputData[key]=="true") t=true;
56  else if( inputData[key]=="false") t=false;
57  else plumed_error();
58 }
59 
60 bool CLTool::readInput( int argc, char**argv, FILE* in, FILE*out ){
61  plumed_massert( inputdata!=unset,"You have not specified where your tool reads its input. "
62  "If it is from the command line (like driver) add inputdata=commandline to the "
63  "tools constructor. If it reads everything from an input file (like simplemd) "
64  "add inputdata=ifile to the tools constructor");
65  if(inputdata==commandline) return readCommandLineArgs( argc, argv, out );
66  if(inputdata==ifile) return readInputFile( argc, argv, in, out );
67  return true;
68 }
69 
70 bool CLTool::readCommandLineArgs( int argc, char**argv, FILE*out ){
71  plumed_assert(inputdata==commandline);
72  std::string prefix(""), a(""), thiskey;
73 
74  // Set all flags to default false
75  for(int k=0;k<keywords.size();++k){
76  thiskey=keywords.get(k);
77  if( keywords.style(thiskey,"flag") ) inputData.insert(std::pair<std::string,std::string>(thiskey,"false"));
78  }
79 
80  // Read command line arguments
81  bool printhelp=false;
82  for(int i=1;i<argc;i++){
83  a=prefix+argv[i];
84  if(a.length()==0) continue;
85  if(a=="-h" || a=="--help"){
86  printhelp=true;
87  } else {
88  bool found=false;
89  for(int k=0;k<keywords.size();++k){
90  thiskey=keywords.get(k);
91  if( keywords.style(thiskey,"flag") ){
92  if( a==thiskey ){ found=true; inputData[thiskey]="true"; }
93  } else {
94  if( a==thiskey ){
95  prefix=thiskey+"="; found=true;
96  inputData.insert(std::pair<std::string,std::string>(thiskey,""));
97  } else if( a.find(thiskey+"=")==0){
98  a.erase(0,a.find("=")+1); prefix=""; found=true;
99  if(inputData.count(thiskey)==0){
100  inputData.insert(std::pair<std::string,std::string>(thiskey,a));
101  } else {
102  inputData[thiskey]=a;
103  }
104  }
105  }
106  }
107  if(!found){
108  fprintf(stderr,"ERROR in input for command line tool %s : %s option is unknown \n\n", name.c_str(), a.c_str() );
109  fprintf(out,"Usage: %s < inputFile \n", name.c_str() );
110  fprintf(out,"inputFile should contain one directive per line. The directives should come from amongst the following\n\n");
111  keywords.print( out );
112  printhelp=true;
113  }
114  }
115  if(printhelp) break;
116  }
117 
118  if(!printhelp) setRemainingToDefault(out);
119 
120  if(printhelp){
121  fprintf(out,"Usage: %s [options] \n\n", name.c_str() );
122  keywords.print( out );
123  }
124 
125  return !printhelp;
126 }
127 
129  std::string def, thiskey;
130  for(int k=0;k<keywords.size();++k){
131  thiskey=keywords.get(k);
132  if( keywords.style(thiskey,"compulsory") ){
133  if( inputData.count(thiskey)==0 ){
134  if( keywords.getDefaultValue(thiskey,def) ){
135  plumed_assert( def.length()>0 );
136  inputData.insert(std::pair<std::string,std::string>(thiskey,def));
137  } else {
138  fprintf(out,"ERROR : argument %s is compulsory. Use --help option for help\n",thiskey.c_str() );
139  plumed_error();
140  }
141  }
142  }
143  }
144 }
145 
146 bool CLTool::readInputFile( int argc, char**argv, FILE* in, FILE*out ){
147  plumed_assert(inputdata==ifile);
148 
149  // Check if use is just asking for help
150  std::string a;
151  for(int i=1;i<argc;i++){
152  a=argv[i];
153  if(a.length()==0) continue;
154  if(a=="-h" || a=="--help"){
155  fprintf(out,"Usage: %s < inputFile \n", name.c_str() );
156  fprintf(out,"inputFile should contain one directive per line. The directives should come from amongst the following\n\n");
157  keywords.print( out );
158  return false;
159  }
160  }
161 
162  FILE* mystdin=in;
163  if(argc==2){
164  mystdin=fopen(argv[1],"r");
165  if(!mystdin){
166  fprintf(stderr,"ERROR: cannot open file %s\n\n",argv[1]);
167  fprintf(out,"Usage: %s < inputFile \n", name.c_str() );
168  fprintf(out,"inputFile should contain one directive per line. The directives should come from amongst the following\n\n");
169  keywords.print( out );
170  return false;
171  }
172  }
173 
174  char buffer[256]; std::string line; line.resize(256);
175  while(fgets(buffer,256,mystdin)){
176  line=buffer;
177  for(int i=0;i<line.length();++i) if(line[i]=='#' || line[i]=='\n') line.erase(i);
179  if(line.length()==0) continue;
180  sscanf(line.c_str(),"%255s",buffer);
181  std::string keyword=buffer; bool found=false;
182  for(unsigned i=0;i<keywords.size();++i){
183  std::string thiskey=keywords.get(i);
184  if(thiskey==keyword){
185  found=true;
186  std::size_t keypos=line.find_first_of(keyword)+keyword.length();
187  inputData.insert(std::pair<std::string,std::string>(thiskey,line.substr(keypos)));
189  }
190  }
191  if(!found){
192  fprintf(stderr,"ERROR in input for command line tool %s : unknown keyword %s found in input file\n\n",name.c_str(),keyword.c_str());
193  fprintf(out,"Usage: %s < inputFile \n", name.c_str() );
194  fprintf(out,"inputFile should contain one directive per line. The directives should come from amongst the following\n\n");
195  keywords.print( out );
196  if(mystdin) fclose(mystdin);
197  return false;
198  }
199  }
200 
201  if(argc==2) fclose(mystdin);
203  return true;
204 }
205 
206 void CLTool::error( const std::string& msg ){
207  fprintf(stderr,"ERROR : in input for command line tool %s : %s\n",name.c_str(),msg.c_str());
208  plumed_error();
209 }
210 
211 }
static void registerKeywords(Keywords &keys)
Create the help keywords.
Definition: CLTool.cpp:40
void setRemainingToDefault(FILE *out)
Set arguments from the default options provided to Keywords.
Definition: CLTool.cpp:128
bool readInput(int argc, char **argv, FILE *in, FILE *out)
Read the arguments from the command line.
Definition: CLTool.cpp:60
bool getDefaultValue(std::string key, std::string &def) const
Get the value of the default for the keyword named key.
Definition: Keywords.cpp:543
CLToolOptions(const std::string &name)
Definition: CLTool.cpp:28
This class holds the keywords and their documentation.
Definition: Keywords.h:36
bool readInputFile(int argc, char **argv, FILE *in, FILE *out)
Read the arguments from an input file specified on the command line.
Definition: CLTool.cpp:146
std::string get(const unsigned k) const
Get the ith keyword.
Definition: Keywords.cpp:529
const std::string name
The name of this command line tool.
Definition: CLTool.h:58
void print(Log &log) const
Print the documentation to the log file (used by PLMD::Action::error)
Definition: Keywords.cpp:461
CLTool(const CLToolOptions &co)
Definition: CLTool.cpp:44
const Keywords & keywords
The list of keywords for this CLTool.
Definition: CLTool.h:60
bool style(const std::string &k, const std::string &t) const
Check if the keyword with name k has style t.
Definition: Keywords.cpp:223
static void stripLeadingAndTrailingBlanks(std::string &str)
removes leading and trailing blanks from a string
Definition: Tools.cpp:283
bool exists(const std::string &k) const
Check if there is a keyword with name k.
Definition: Keywords.cpp:239
void parseFlag(const std::string &key, bool &t)
Find out whether one of the command line flags is present or not.
Definition: CLTool.cpp:51
std::map< std::string, std::string > inputData
The data read in from the command line stored in a map with the keywords.
Definition: CLTool.h:62
enum PLMD::CLTool::@0 inputdata
How is the input specified on the command line or in an input file.
void error(const std::string &msg)
Crash the command line tool with an error.
Definition: CLTool.cpp:206
bool readCommandLineArgs(int argc, char **argv, FILE *out)
Read the arguments from the command line.
Definition: CLTool.cpp:70
void const char const char int double * a
Definition: Matrix.h:42
static Keywords emptyKeys
Definition: CLTool.h:43
void addFlag(const std::string &k, const bool def, const std::string &d)
Add a falg with name k that is by default on if def is true and off if def is false. d should provide a description of the flag.
Definition: Keywords.cpp:193
unsigned size() const
Return the number of defined keywords.
Definition: Keywords.cpp:230