All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
CLToolMain.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 "config/Config.h"
23 #include "tools/Exception.h"
24 #include "tools/Communicator.h"
25 #include "CLTool.h"
26 #include "CLToolMain.h"
27 #include "CLToolRegister.h"
28 #include "tools/Tools.h"
29 #include "tools/DLLoader.h"
30 #include <string>
31 #include <cstdlib>
32 #include <cstdio>
33 #include <iostream>
34 #include <algorithm>
35 
36 using namespace std;
37 namespace PLMD{
38 
39 CLToolMain::CLToolMain():
40 argc(0),
41 in(stdin),
42 out(stdout),
43 comm(*new Communicator)
44 {
45 }
46 
48  delete &comm;
49 }
50 
51 #define CHECK_NULL(val,word) plumed_massert(val,"NULL pointer received in cmd(\"CLTool " + word + "\")");
52 
53 void CLToolMain::cmd(const std::string& word,void*val){
54  if(false){
55  } else if(word=="setArgc"){
56  CHECK_NULL(val,word);
57  argc=*static_cast<int*>(val);
58  } else if(word=="setArgv"){
59  CHECK_NULL(val,word);
60  char**v=static_cast<char**>(val);
61  for(int i=0;i<argc;++i) argv.push_back(string(v[i]));
62  } else if(word=="setArgvLine"){
63  CHECK_NULL(val,word);
64  const char*v=static_cast<char*>(val);
66  } else if(word=="setIn"){
67  CHECK_NULL(val,word);
68  in=static_cast<FILE*>(val);
69  } else if(word=="setOut"){
70  CHECK_NULL(val,word);
71  out=static_cast<FILE*>(val);
72  } else if(word=="setMPIComm"){
73  comm.Set_comm(val);
74  } else if(word=="setMPIFComm"){
75  comm.Set_fcomm(val);
76  } else if(word=="run"){
77  CHECK_NULL(val,word);
78  argc=argv.size();
79  char**v=new char* [argc];
80  for(int i=0;i<argc;++i){
81  v[i]=new char [argv[i].length()+1];
82  for(unsigned c=0;c<argv[i].length();++c) v[i][c]=argv[i][c];
83  v[i][argv[i].length()]=0;
84  }
85  int ret=run(argc,v,in,out,comm);
86  for(int i=0;i<argc;++i) delete [] v[i];
87  delete [] v;
88  *static_cast<int*>(val)=ret;
89  } else {
90  plumed_merror("cannot interpret cmd(\"CLTool " + word + "\"). check plumed developers manual to see the available commands.");
91  }
92 }
93 
94 /**
95 This is the entry point to the command line tools
96 included in the plumed library.
97 */
98 
99 int CLToolMain::run(int argc, char **argv,FILE*in,FILE*out,Communicator& pc){
100  int i;
101  bool printhelp=false;
102 
103  DLLoader dlloader;
104 
105  string root=config::getPlumedRoot();
106 
107  bool standalone_executable=false;
108 
109 // Start parsing options
110  string prefix("");
111  string a("");
112  for(i=1;i<argc;i++){
113  a=prefix+argv[i];
114  if(a.length()==0) continue;
115  if(a=="help" || a=="-h" || a=="--help"){
116  printhelp=true;
117  break;
118  } else if(a=="--has-mpi"){
119  if(Communicator::initialized()) return 0;
120  else return 1;
121  } else if(a=="--has-matheval"){
122  return (config::hasMatheval()?0:1);
123  } else if(a=="--has-almost"){
124  return (config::hasAlmost()?0:1);
125  } else if(a=="--has-cregex"){
126  return (config::hasCregex()?0:1);
127  } else if(a=="--has-dlopen"){
128  return (config::hasDlopen()?0:1);
129  } else if(a=="--no-mpi"){
130 // this is ignored, as it is parsed in main
131  if(i>1){
132  fprintf(stderr,"--no-mpi option should can only be used as the first option");
133  return 1;
134  }
135  } else if(a=="--standalone-executable"){
136  standalone_executable=true;
137  } else if(a.find("--load=")==0){
138  a.erase(0,a.find("=")+1);
139  prefix="";
140  void *p=dlloader.load(a);
141  if(!p){
142  fprintf(stderr,"ERROR: cannot load library %s\n",a.c_str());
143  fprintf(stderr,"ERROR: %s\n",dlloader.error().c_str());
144  return 1;
145  }
146  } else if(a=="--load"){
147  prefix="--load=";
148  } else if(a[0]=='-') {
149  string msg="ERROR: Unknown option " +a;
150  fprintf(stderr,"%s\n",msg.c_str());
151  return 1;
152  } else break;
153  }
154 
155 // Check if plumedRoot/patches/ directory exists (as a further check)
156  if(!standalone_executable){
157  vector<string> files=Tools::ls(root);
158  if(find(files.begin(),files.end(),"patches")==files.end()) {
159  string msg=
160  "ERROR: I cannot find "+root+"/patches/ directory\n";
161  fprintf(stderr,"%s",msg.c_str());
162  return 1;
163  }
164  }
165 
166 // Build list of available C++ tools:
167  vector<string> availableCxx=cltoolRegister().list();
168 // Build list of available shell tools:
169  vector<string> availableShell;
170  if(!standalone_executable) {
171  vector<string> tmp;
172  tmp=Tools::ls(string(root+"/scripts"));
173  for(unsigned j=0;j<tmp.size();++j){
174  size_t ff=tmp[j].find(".sh");
175  if(ff==string::npos) tmp[j].erase();
176  else tmp[j].erase(ff);
177  }
178  for(unsigned j=0;j<tmp.size();++j) if(tmp[j].length()>0) availableShell.push_back(tmp[j]);
179  }
180 
181  if(printhelp){
182  string msg=
183  "Usage: plumed [options] [command] [command options]\n"
184  " plumed [command] -h|--help: to print help for a specific command\n"
185  "Options:\n"
186  " [help|-h|--help] : to print this help\n"
187  " [--has-mpi] : fails if plumed is running without MPI\n"
188  " [--has-matheval] : fails if plumed is compiled without matheval\n"
189  " [--has-almost] : fails if plumed is compiled without almost\n"
190  " [--has-dlopen] : fails if plumed is compiled without dlopen\n"
191  " [--load LIB] : loads a shared object (typically a plugin library)\n"
192  " [--standalone-executable] : tells plumed not to look for commands implemented as scripts\n"
193  "Commands:\n";
194  fprintf(out,"%s",msg.c_str());
195  for(unsigned j=0;j<availableCxx.size();++j){
196  CLTool *cl=cltoolRegister().create(availableCxx[j]);
197  plumed_assert(cl);
198  string manual=availableCxx[j]+" : "+cl->description();
199  delete cl;
200  fprintf(out," plumed %s\n", manual.c_str());
201  }
202  for(unsigned j=0;j<availableShell.size();++j){
203  string cmd="env PLUMED_ROOT="+root+" "+root+"/scripts/"+availableShell[j]+".sh --description";
204  FILE *fp=popen(cmd.c_str(),"r");
205  string line,manual;
206  while(Tools::getline(fp,line))manual+=line;
207  pclose(fp);
208  manual= availableShell[j]+" : "+manual;
209  fprintf(out," plumed %s\n", manual.c_str());
210  }
211  return 0;
212  }
213  if(i==argc) {
214  fprintf(out,"%s","Nothing to do. Use 'plumed help' for help\n");
215  return 0;
216  }
217 
218 // this is the command to be executed:
219  string command(argv[i]);
220 
221  if(find(availableCxx.begin(),availableCxx.end(),command)!=availableCxx.end()){
222  CLTool *cl=cltoolRegister().create(command);
223  plumed_assert(cl);
224  // Read the command line options (returns false if we are just printing help)
225  if( !cl->readInput( argc-i,&argv[i],in,out ) ){ delete cl; return 0; }
226  int ret=cl->main(in,out,pc);
227  delete cl;
228  return ret;
229  }
230 
231  if(find(availableShell.begin(),availableShell.end(),command)!=availableShell.end()){
232  plumed_massert(in==stdin,"shell tools can only work on stdin");
233  plumed_massert(out==stdout,"shell tools can only work on stdin");
234  string cmd="env PLUMED_ROOT="+root+" "+root+"/scripts/"+command+".sh";
235  for(int j=i+1;j<argc;j++) cmd+=string(" ")+argv[j];
236  system(cmd.c_str());
237  return 0;
238  }
239 
240  string msg="ERROR: unknown command " + command + ". Use 'plumed help' for help";
241  fprintf(stderr,"%s\n",msg.c_str());
242  return 1;
243 
244 }
245 }
std::vector< std::string > list() const
Returns a list of the allowed CLTools.
static bool initialized()
Tests if MPI library is initialized.
std::string getPlumedRoot()
Definition: Config.cpp:34
Class taking care of dynamic loading.
Definition: DLLoader.h:40
static bool getline(FILE *, std::string &line)
Get a line from the file pointer ifile.
Definition: Tools.cpp:190
Communicator & comm
Definition: CLToolMain.h:86
static std::vector< std::string > ls(const std::string &)
list files in a directory
Definition: Tools.cpp:272
bool readInput(int argc, char **argv, FILE *in, FILE *out)
Read the arguments from the command line.
Definition: CLTool.cpp:60
virtual int main(FILE *in, FILE *out, Communicator &pc)=0
virtual function mapping to the specific main for each tool
Class containing wrappers to MPI.
Definition: Communicator.h:44
STL namespace.
#define CHECK_NULL(val, word)
Definition: CLToolMain.cpp:51
static int run(int argc, char **argv, FILE *in, FILE *out, Communicator &pc)
This is the entry point to the command line tools included in the plumed library. ...
Definition: CLToolMain.cpp:99
This is the abstract base class to use for implementing new command line tool, within it there is inf...
Definition: CLTool.h:55
void cmd(const std::string &key, void *val=NULL)
Send messages to the CLToolMain.
Definition: CLToolMain.cpp:53
const std::string & error()
Returns the last error in dynamic loader.
Definition: DLLoader.cpp:54
std::vector< std::string > argv
arguments for command-line mode:
Definition: CLToolMain.h:83
bool hasAlmost()
Definition: Config.cpp:73
static std::vector< std::string > getWords(const std::string &line, const char *sep=NULL, int *parlevel=NULL, const char *parenthesis="{")
Split the line in words using separators.
Definition: Tools.cpp:112
CLTool * create(const CLToolOptions &ao)
Create an CLTool of the type indicated in the options.
bool hasCregex()
Definition: Config.cpp:82
bool hasDlopen()
Definition: Config.cpp:65
CLToolRegister & cltoolRegister()
virtual std::string description() const
virtual function returning a one-line descriptor for the tool
Definition: CLTool.h:98
void * load(const std::string &)
Load a library, returning its handle.
Definition: DLLoader.cpp:39
int argc
arguments for command-line mode:
Definition: CLToolMain.h:81
void Set_comm(MPI_Comm)
Set from a real MPI communicator.
void Set_fcomm(void *comm)
Set from a pointer to a real MPI communicator (FORTRAN)
void const char const char int double * a
Definition: Matrix.h:42
bool hasMatheval()
Definition: Config.cpp:57