LCOV - code coverage report
Current view: top level - core - CLToolMain.cpp (source / functions) Hit Total Coverage
Test: plumed test coverage Lines: 96 158 60.8 %
Date: 2018-12-19 07:49:13 Functions: 7 7 100.0 %

          Line data    Source code
       1             : /* +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
       2             :    Copyright (c) 2012-2018 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.org for more information.
       6             : 
       7             :    This file is part of plumed, version 2.
       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 "CLToolMain.h"
      23             : #include "config/Config.h"
      24             : #include "tools/Exception.h"
      25             : #include "tools/Communicator.h"
      26             : #include "CLTool.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         828 : CLToolMain::CLToolMain():
      40             :   argc(0),
      41             :   in(stdin),
      42             :   out(stdout),
      43         828 :   comm(*new Communicator)
      44             : {
      45         828 : }
      46             : 
      47        2484 : CLToolMain::~CLToolMain() {
      48         828 :   delete &comm;
      49        1656 : }
      50             : 
      51             : #define CHECK_NULL(val,word) plumed_massert(val,"NULL pointer received in cmd(\"CLTool " + word + "\")");
      52             : 
      53        2653 : void CLToolMain::cmd(const std::string& word,void*val) {
      54             :   if(false) {
      55        2653 :   } else if(word=="setArgc") {
      56         828 :     CHECK_NULL(val,word);
      57         828 :     argc=*static_cast<int*>(val);
      58        1825 :   } else if(word=="setArgv") {
      59         828 :     CHECK_NULL(val,word);
      60         828 :     char**v=static_cast<char**>(val);
      61         828 :     for(int i=0; i<argc; ++i) argv.push_back(string(v[i]));
      62         997 :   } else if(word=="setArgvLine") {
      63           0 :     CHECK_NULL(val,word);
      64           0 :     const char*v=static_cast<char*>(val);
      65           0 :     argv=Tools::getWords(v);
      66         997 :   } else if(word=="setIn") {
      67           0 :     CHECK_NULL(val,word);
      68           0 :     in=static_cast<FILE*>(val);
      69         997 :   } else if(word=="setOut") {
      70           0 :     CHECK_NULL(val,word);
      71           0 :     out=static_cast<FILE*>(val);
      72         997 :   } else if(word=="setMPIComm") {
      73         169 :     comm.Set_comm(val);
      74         828 :   } else if(word=="setMPIFComm") {
      75           0 :     comm.Set_fcomm(val);
      76         828 :   } else if(word=="run") {
      77         828 :     CHECK_NULL(val,word);
      78         828 :     argc=argv.size();
      79         828 :     char**v=new char* [argc];
      80        6877 :     for(int i=0; i<argc; ++i) {
      81        6049 :       v[i]=new char [argv[i].length()+1];
      82        6049 :       for(unsigned c=0; c<argv[i].length(); ++c) v[i][c]=argv[i][c];
      83        6049 :       v[i][argv[i].length()]=0;
      84             :     }
      85         828 :     int ret=run(argc,v,in,out,comm);
      86         828 :     for(int i=0; i<argc; ++i) delete [] v[i];
      87         828 :     delete [] v;
      88         828 :     *static_cast<int*>(val)=ret;
      89             :   } else {
      90           0 :     plumed_merror("cannot interpret cmd(\"CLTool " + word + "\"). check plumed developers manual to see the available commands.");
      91             :   }
      92        2653 : }
      93             : 
      94             : /**
      95             : This is the entry point to the command line tools
      96             : included in the plumed library.
      97             : */
      98             : 
      99         828 : int CLToolMain::run(int argc, char **argv,FILE*in,FILE*out,Communicator& pc) {
     100             :   int i;
     101         828 :   bool printhelp=false;
     102             : 
     103         828 :   DLLoader dlloader;
     104             : 
     105        1656 :   string root=config::getPlumedRoot();
     106             : 
     107         828 :   bool standalone_executable=false;
     108             : 
     109             : // Start parsing options
     110        1656 :   string prefix("");
     111        1656 :   string a("");
     112        1487 :   for(i=1; i<argc; i++) {
     113        1487 :     a=prefix+argv[i];
     114        1487 :     if(a.length()==0) continue;
     115        1487 :     if(a=="help" || a=="-h" || a=="--help") {
     116           0 :       printhelp=true;
     117           0 :       break;
     118        1487 :     } else if(a=="--has-mpi") {
     119           0 :       if(Communicator::initialized()) return 0;
     120           0 :       else return 1;
     121        1487 :     } else if(a=="--has-matheval") {
     122           0 :       return (config::hasMatheval()?0:1);
     123        1487 :     } else if(a=="--has-cregex") {
     124           0 :       return (config::hasCregex()?0:1);
     125        1487 :     } else if(a=="--has-dlopen") {
     126           0 :       return (config::hasDlopen()?0:1);
     127        1487 :     } else if(a=="--has-molfile") {
     128           0 :       return (config::hasMolfile()?0:1);
     129        1487 :     } else if(a=="--has-external-molfile") {
     130           0 :       return (config::hasExternalMolfile()?0:1);
     131        1487 :     } else if(a=="--has-zlib") {
     132           0 :       return (config::hasZlib()?0:1);
     133        1487 :     } else if(a=="--has-xdrfile") {
     134           0 :       return (config::hasXdrfile()?0:1);
     135        1487 :     } else if(a=="--is-installed") {
     136          10 :       return (config::isInstalled()?0:1);
     137        1477 :     } else if(a=="--no-mpi") {
     138             : // this is ignored, as it is parsed in main
     139         659 :       if(i>1) {
     140           0 :         fprintf(stderr,"--no-mpi option can only be used as the first option");
     141           0 :         return 1;
     142             :       }
     143         818 :     } else if(a=="--mpi") {
     144             : // this is ignored, as it is parsed in main
     145           0 :       if(i>1) {
     146           0 :         fprintf(stderr,"--mpi option can only be used as the first option");
     147           0 :         return 1;
     148             :       }
     149         818 :     } else if(a=="--standalone-executable") {
     150           0 :       standalone_executable=true;
     151         818 :     } else if(Tools::startWith(a,"--load=")) {
     152           0 :       a.erase(0,a.find("=")+1);
     153           0 :       prefix="";
     154           0 :       void *p=dlloader.load(a);
     155           0 :       if(!p) {
     156           0 :         fprintf(stderr,"ERROR: cannot load library %s\n",a.c_str());
     157           0 :         fprintf(stderr,"ERROR: %s\n",dlloader.error().c_str());
     158           0 :         return 1;
     159             :       }
     160         818 :     } else if(a=="--load") {
     161           0 :       prefix="--load=";
     162         818 :     } else if(a[0]=='-') {
     163           0 :       string msg="ERROR: Unknown option " +a;
     164           0 :       fprintf(stderr,"%s\n",msg.c_str());
     165           0 :       return 1;
     166         818 :     } else break;
     167             :   }
     168             : 
     169             : // Check if plumedRoot/patches/ directory exists (as a further check)
     170         818 :   if(!standalone_executable) {
     171         818 :     vector<string> files=Tools::ls(root);
     172         818 :     if(find(files.begin(),files.end(),"patches")==files.end()) {
     173             :       string msg=
     174           0 :         "WARNING: I cannot find "+root+"/patches/ directory. Set PLUMED_ROOT or reinstall PLUMED\n\n";
     175           0 :       fprintf(stderr,"%s",msg.c_str());
     176         818 :     }
     177             :   }
     178             : 
     179             : // Build list of available C++ tools:
     180        1636 :   vector<string> availableCxx=cltoolRegister().list();
     181             : // Build list of available shell tools:
     182        1636 :   vector<string> availableShell;
     183         818 :   if(!standalone_executable) {
     184         818 :     vector<string> tmp;
     185         818 :     tmp=Tools::ls(string(root+"/scripts"));
     186        6544 :     for(unsigned j=0; j<tmp.size(); ++j) {
     187        5726 :       size_t ff=tmp[j].find(".sh");
     188        5726 :       if(ff==string::npos) tmp[j].erase();
     189        4908 :       else                 tmp[j].erase(ff);
     190             :     }
     191         818 :     for(unsigned j=0; j<tmp.size(); ++j) if(tmp[j].length()>0) availableShell.push_back(tmp[j]);
     192             :   }
     193             : 
     194         818 :   if(printhelp) {
     195             :     string msg=
     196             :       "Usage: plumed [options] [command] [command options]\n"
     197             :       "  plumed [command] -h|--help: to print help for a specific command\n"
     198             :       "Options:\n"
     199             :       "  [help|-h|--help]          : to print this help\n"
     200             :       "  [--is-installed]          : fails if plumed is not installed\n"
     201             :       "  [--has-mpi]               : fails if plumed is running without MPI\n"
     202             :       "  [--has-matheval]          : fails if plumed is compiled without matheval\n"
     203             :       "  [--has-dlopen]            : fails if plumed is compiled without dlopen\n"
     204             :       "  [--load LIB]              : loads a shared object (typically a plugin library)\n"
     205             :       "  [--standalone-executable] : tells plumed not to look for commands implemented as scripts\n"
     206           0 :       "Commands:\n";
     207           0 :     fprintf(out,"%s",msg.c_str());
     208           0 :     for(unsigned j=0; j<availableCxx.size(); ++j) {
     209           0 :       CLTool *cl=cltoolRegister().create(CLToolOptions(availableCxx[j]));
     210           0 :       plumed_assert(cl);
     211           0 :       string manual=availableCxx[j]+" : "+cl->description();
     212           0 :       delete cl;
     213           0 :       fprintf(out,"  plumed %s\n", manual.c_str());
     214           0 :     }
     215           0 :     for(unsigned j=0; j<availableShell.size(); ++j) {
     216           0 :       string cmd=config::getEnvCommand()+" \""+root+"/scripts/"+availableShell[j]+".sh\" --description";
     217           0 :       FILE *fp=popen(cmd.c_str(),"r");
     218           0 :       string line,manual;
     219           0 :       while(Tools::getline(fp,line))manual+=line;
     220           0 :       pclose(fp);
     221           0 :       manual= availableShell[j]+" : "+manual;
     222           0 :       fprintf(out,"  plumed %s\n", manual.c_str());
     223           0 :     }
     224           0 :     return 0;
     225             :   }
     226         818 :   if(i==argc) {
     227           0 :     fprintf(out,"%s","Nothing to do. Use 'plumed help' for help\n");
     228           0 :     return 0;
     229             :   }
     230             : 
     231             : // this is the command to be executed:
     232        1636 :   string command(argv[i]);
     233             : 
     234         818 :   if(find(availableCxx.begin(),availableCxx.end(),command)!=availableCxx.end()) {
     235         724 :     CLTool *cl=cltoolRegister().create(CLToolOptions(command));
     236         724 :     plumed_assert(cl);
     237             :     // Read the command line options (returns false if we are just printing help)
     238         724 :     if( !cl->readInput( argc-i,&argv[i],in,out ) ) { delete cl; return 0; }
     239         724 :     int ret=cl->main(in,out,pc);
     240         724 :     delete cl;
     241         724 :     return ret;
     242             :   }
     243             : 
     244          94 :   if(find(availableShell.begin(),availableShell.end(),command)!=availableShell.end()) {
     245          94 :     plumed_massert(in==stdin,"shell tools can only work on stdin");
     246          94 :     plumed_massert(out==stdout,"shell tools can only work on stdin");
     247          94 :     string cmd=config::getEnvCommand()+" \""+root+"/scripts/"+command+".sh\"";
     248          94 :     for(int j=i+1; j<argc; j++) cmd+=string(" ")+argv[j];
     249          94 :     int r=system(cmd.c_str());
     250             : // this is necessary since system seems to return numbers which are multiple
     251             : // of 256. this would make the interpretation by the shell wrong
     252             : // I just return 1 in case of failure and 0 in case of success
     253          94 :     if(r!=0) return 1;
     254          94 :     else return 0;
     255             :   }
     256             : 
     257           0 :   string msg="ERROR: unknown command " + command + ". Use 'plumed help' for help";
     258           0 :   fprintf(stderr,"%s\n",msg.c_str());
     259         828 :   return 1;
     260             : 
     261             : }
     262        2523 : }

Generated by: LCOV version 1.13