]> git.donarmstrong.com Git - mothur.git/blob - engine.cpp
fixed catchall PATH variable bug added trimera to chimera.slayer
[mothur.git] / engine.cpp
1 /*
2  *  engine.cpp
3  *  
4  *
5  *  Created by Pat Schloss on 8/15/08.
6  *  Copyright 2008 Patrick D. Schloss. All rights reserved.
7  *
8  *  There's a TON of duplicated code between InteractEngine and BatchEngine
9  *  I couldn't figure out how to transition between ifstream (batch) and cin (interact)
10  *  Fix later, don't have time now.
11  *
12  */
13
14
15 #include "engine.hpp"
16
17 /***********************************************************************/
18 Engine::Engine(){
19         try {
20                 cFactory = CommandFactory::getInstance();
21                 mout = MothurOut::getInstance();
22         }
23         catch(exception& e) {
24                 mout->errorOut(e, "Engine", "Engine");
25                 exit(1);
26         }
27 }
28 /***********************************************************************/
29 string Engine::findMothursPath(){
30         try { 
31                 
32                 string envPath = getenv("PATH");
33                 string mothurPath = "";
34                 
35                 //delimiting path char
36                 char delim;
37                 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux)
38                         delim = ':';
39                 #else
40                         delim = ';';
41                 #endif
42                 
43                 //break apart path variable by ':'
44                 vector<string> dirs;
45                 mout->splitAtChar(envPath, dirs, delim);
46                 
47                 //get path related to mothur
48                 for (int i = 0; i < dirs.size(); i++) {
49                         //to lower so we can find it
50                         string tempLower = "";
51                         for (int j = 0; j < dirs[i].length(); j++) {  tempLower += tolower(dirs[i][j]);  }
52                         
53                         //is this mothurs path?
54                         if (tempLower.find("mothur") != -1) {  mothurPath = dirs[i]; break;  }
55                 }
56                 
57                 if (mothurPath != "") {
58                         //add mothur so it looks like what argv would look like
59                         #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux)
60                                 mothurPath += "/mothur";
61                         #else
62                                 mothurPath += "\\mothur";
63                         #endif
64                 }else {
65                         //okay mothur is not in the path, so the folder mothur is in must be in the path
66                         //lets find out which one
67                         
68                         //get path related to mothur
69                         for (int i = 0; i < dirs.size(); i++) {
70                                                                 
71                                 //is this mothurs path?
72                                 ifstream in;
73                                 string tempIn = dirs[i];
74                                 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux)
75                                         tempIn += "/mothur";
76                                 #else
77                                         tempIn += "\\mothur";
78                                 #endif
79                                 mout->openInputFile(tempIn, in, "");
80                                 
81                                 //if this file exists
82                                 if (in) { in.close(); mothurPath = tempIn;  break;  }
83                         }
84                 }
85                 
86                 return mothurPath;
87                 
88         }
89         catch(exception& e) {
90                 mout->errorOut(e, "Engine", "findMothursPath");
91                 exit(1);
92         }
93 }
94 /***********************************************************************/
95
96 InteractEngine::InteractEngine(string path){
97
98         globaldata = GlobalData::getInstance();
99         
100         string temppath = path.substr(0, (path.find_last_of("othur")-5));
101         
102         //this will happen if you set the path variable to contain mothur's exe location
103         if (temppath == "") { path = findMothursPath(); }
104         
105         globaldata->argv = path;
106 }
107
108 /***********************************************************************/
109
110 InteractEngine::~InteractEngine(){}
111
112 /***********************************************************************/
113 //This function allows the user to input commands one line at a time until they quit.
114 //If the command is garbage it does nothing.
115 bool InteractEngine::getInput(){
116         try {
117                 string input = "";
118                 string commandName = "";
119                 string options = "";
120                 int quitCommandCalled = 0;
121                 
122                 while(quitCommandCalled != 1){
123
124                         #ifdef USE_MPI
125                                 int pid, processors;
126                                 MPI_Status status;
127                                 MPI_Comm_rank(MPI_COMM_WORLD, &pid); 
128                                 MPI_Comm_size(MPI_COMM_WORLD, &processors);
129                                 
130                                 if (pid == 0) {
131                                 
132                         #endif
133                         
134                         mout->mothurOutEndLine();
135                         
136                         input = getCommand();   
137                         mout->mothurOutEndLine();       
138                         
139                         if (mout->control_pressed) { input = "quit()"; }
140                         
141                         //allow user to omit the () on the quit command
142                         if (input == "quit") { input = "quit()"; }
143
144                         
145                         #ifdef USE_MPI
146                                 //send commandName
147                                 for(int i = 1; i < processors; i++) { 
148                                                 int length = input.length();
149                                                 MPI_Send(&length, 1, MPI_INT, i, 2001, MPI_COMM_WORLD);
150                                                 MPI_Send(&input[0], length, MPI_CHAR, i, 2001, MPI_COMM_WORLD);
151         
152                                         }
153                                 }else {
154                                         int length;
155                                         MPI_Recv(&length, 1, MPI_INT, 0, 2001, MPI_COMM_WORLD, &status);
156                                         //recieve container
157                                         char* tempBuf = new char[length];
158                                         MPI_Recv(&tempBuf[0], length, MPI_CHAR, 0, 2001, MPI_COMM_WORLD, &status);
159                                         
160                                         input = tempBuf;
161                                         if (input.length() > length) { input = input.substr(0, length);  }
162                                         delete tempBuf; 
163                                 }
164
165                         
166                         #endif
167                 
168                         CommandOptionParser parser(input);
169                         commandName = parser.getCommandString();
170         
171                         options = parser.getOptionString();
172                         
173                         if (commandName != "") {
174                                         mout->executing = true;
175                                         #ifdef USE_MPI
176                                                 int pid;
177                                                 MPI_Comm_rank(MPI_COMM_WORLD, &pid); 
178                                                 
179                                                 if ((cFactory->MPIEnabled(commandName)) || (pid == 0)) {
180                                         //cout << pid << " is in execute " << commandName << endl;
181                                         #endif
182                                         //executes valid command
183                                         Command* command = cFactory->getCommand(commandName, options);
184                                         quitCommandCalled = command->execute();
185                                                         
186                                         //if we aborted command
187                                         if (quitCommandCalled == 2) {  mout->mothurOut("[ERROR]: did not complete " + commandName + "."); mout->mothurOutEndLine(); }
188
189                                         mout->control_pressed = 0;
190                                         mout->executing = false;
191                                                                                 
192                                         #ifdef USE_MPI
193                                                 }
194                                         #endif
195                                 }else {         
196                                         mout->mothurOut("Invalid."); 
197                                         mout->mothurOutEndLine();
198                                 }
199                 }       
200                 return 1;
201         }
202         catch(exception& e) {
203                 mout->errorOut(e, "InteractEngine", "getInput");
204                 exit(1);
205         }
206 }
207 /***********************************************************************/
208 string Engine::getCommand()  {
209         try {
210         
211                 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux)
212                         #ifdef USE_READLINE
213                                 char* nextCommand = NULL;
214                                 nextCommand = readline("mothur > ");
215                                 
216                                 if(nextCommand != NULL) {  add_history(nextCommand);  } 
217                                 else{ //^D causes null string and we want it to quit mothur
218                                         strcpy(nextCommand, "quit"); 
219                                         mout->mothurOut(nextCommand);
220                                 }       
221                                 
222                                 mout->mothurOutJustToLog("mothur > " + toString(nextCommand));
223                                 return nextCommand;
224                         #else
225                                 string nextCommand = "";
226                                 mout->mothurOut("mothur > ");
227                                 getline(cin, nextCommand);
228                                 mout->mothurOutJustToLog("mothur > " + toString(nextCommand));
229                                 
230                                 return nextCommand;
231                         #endif
232                 #else
233                                 string nextCommand = "";
234                                 
235                                 mout->mothurOut("mothur > ");
236                                 getline(cin, nextCommand);
237                                 mout->mothurOutJustToLog(toString(nextCommand));
238                                 
239                                 return nextCommand;
240                 #endif
241         
242                                                 
243         }
244         catch(exception& e) {
245                 mout->errorOut(e, "Engine", "getCommand");
246                 exit(1);
247         }
248 }
249 /***********************************************************************/
250 //This function opens the batchfile to be used by BatchEngine::getInput.
251 BatchEngine::BatchEngine(string path, string batchFileName){
252         try {
253                 globaldata = GlobalData::getInstance();
254         
255                 openedBatch = mout->openInputFile(batchFileName, inputBatchFile);
256                 
257                 string temppath = path.substr(0, (path.find_last_of("othur")-5));
258         
259                 //this will happen if you set the path variable to contain mothur's exe location
260                 if (temppath == "") { path = findMothursPath(); }
261                 
262                 globaldata->argv = path;
263                                 
264         }
265         catch(exception& e) {
266                 mout->errorOut(e, "BatchEngine", "BatchEngine");
267                 exit(1);
268         }
269 }
270
271 /***********************************************************************/
272
273 BatchEngine::~BatchEngine(){    }
274
275 /***********************************************************************/
276 //This Function allows the user to run a batchfile containing several commands on Dotur
277 bool BatchEngine::getInput(){
278         try {
279                 //check if this is a valid batchfile
280                 if (openedBatch == 1) {  
281                         mout->mothurOut("unable to open batchfile");  
282                         mout->mothurOutEndLine();
283                         return 1; 
284                 }
285         
286                 string input = "";
287                 string commandName = "";
288                 string options = "";
289                 
290                 //CommandFactory cFactory;
291                 int quitCommandCalled = 0;
292             int count = 0;
293                 while(quitCommandCalled != 1){
294                         
295                         #ifdef USE_MPI
296                                 int pid, processors;
297                                 MPI_Status status;
298                                 MPI_Comm_rank(MPI_COMM_WORLD, &pid); 
299                                 MPI_Comm_size(MPI_COMM_WORLD, &processors);
300                                 
301                                 if (pid == 0) {
302                                 
303                         #endif
304                         
305                         input = getNextCommand(inputBatchFile);
306                         count++;
307                         
308                         #ifdef USE_MPI
309                                 //send commandName
310                                 for(int i = 1; i < processors; i++) { 
311                                                 int length = input.length();
312                                                 MPI_Send(&length, 1, MPI_INT, i, 2001, MPI_COMM_WORLD);
313                                                 MPI_Send(&input[0], length, MPI_CHAR, i, 2001, MPI_COMM_WORLD);
314         
315                                         }
316                                 }else {
317                                         int length;
318                                         MPI_Recv(&length, 1, MPI_INT, 0, 2001, MPI_COMM_WORLD, &status);
319                                         //recieve container
320                                         char* tempBuf = new char[length];
321                                         MPI_Recv(&tempBuf[0], length, MPI_CHAR, 0, 2001, MPI_COMM_WORLD, &status);
322                                         
323                                         input = tempBuf;
324                                         if (input.length() > length) { input = input.substr(0, length);  }
325                                         delete tempBuf; 
326                                 }
327
328                         
329                         #endif
330
331                         
332                         
333                         if (input[0] != '#') {
334                                 
335                                 mout->mothurOutEndLine();
336                                 mout->mothurOut("mothur > " + input);
337                                 mout->mothurOutEndLine();
338                                                         
339                                 if (mout->control_pressed) { input = "quit()"; }
340                                 
341                                 //allow user to omit the () on the quit command
342                                 if (input == "quit") { input = "quit()"; }
343
344                                 CommandOptionParser parser(input);
345                                 commandName = parser.getCommandString();
346                                 options = parser.getOptionString();
347                                                                                 
348                                 if (commandName != "") {
349                                         mout->executing = true;
350                                         #ifdef USE_MPI
351                                                 int pid;
352                                                 MPI_Comm_rank(MPI_COMM_WORLD, &pid); 
353                                                 
354 //cout << pid << " is here " << commandName << '\t' << count << endl;
355                                                 if ((cFactory->MPIEnabled(commandName)) || (pid == 0)) {
356                                         #endif
357                                         //executes valid command
358                                         Command* command = cFactory->getCommand(commandName, options);
359                                         quitCommandCalled = command->execute();
360                                                         
361                                         //if we aborted command
362                                         if (quitCommandCalled == 2) {  mout->mothurOut("[ERROR]: did not complete " + commandName + "."); mout->mothurOutEndLine(); }
363
364                                         mout->control_pressed = 0;
365                                         mout->executing = false;
366                                                                                 
367                                         #ifdef USE_MPI
368                                                 }
369                                         #endif
370                                 }else {         
371                                         mout->mothurOut("Invalid."); 
372                                         mout->mothurOutEndLine();
373                                 }
374                                 
375                         }
376                         mout->gobble(inputBatchFile);
377                 }
378                 
379                 inputBatchFile.close();
380                 return 1;
381         }
382         catch(exception& e) {
383                 mout->errorOut(e, "BatchEngine", "getInput");
384                 exit(1);
385         }
386 }
387 /***********************************************************************/
388 string BatchEngine::getNextCommand(ifstream& inputBatchFile) {
389         try {
390                 
391                 string nextcommand = "";
392                 
393                 if (inputBatchFile.eof()) { nextcommand = "quit()"; }
394                 else { nextcommand = mout->getline(inputBatchFile); }
395                 
396                 return nextcommand;
397         }
398         catch(exception& e) {
399                 mout->errorOut(e, "BatchEngine", "getNextCommand");
400                 exit(1);
401         }
402 }
403
404 /***********************************************************************/
405 /***********************************************************************/
406 //This function opens the batchfile to be used by BatchEngine::getInput.
407 ScriptEngine::ScriptEngine(string path, string commandString){
408         try {
409                 globaldata = GlobalData::getInstance();
410                 
411                 //remove quotes
412                 listOfCommands = commandString.substr(1, (commandString.length()-1));
413                 
414                 string temppath = path.substr(0, (path.find_last_of("othur")-5));
415
416                 //this will happen if you set the path variable to contain mothur's exe location
417                 if (temppath == "") { path = findMothursPath(); }
418                 
419                 globaldata->argv = path;
420                                 
421         }
422         catch(exception& e) {
423                 mout->errorOut(e, "ScriptEngine", "ScriptEngine");
424                 exit(1);
425         }
426 }
427
428 /***********************************************************************/
429
430 ScriptEngine::~ScriptEngine(){  }
431
432 /***********************************************************************/
433 //This Function allows the user to run a batchfile containing several commands on mothur
434 bool ScriptEngine::getInput(){
435         try {
436                         
437                 string input = "";
438                 string commandName = "";
439                 string options = "";
440                 
441                 
442                 //CommandFactory cFactory;
443                 int quitCommandCalled = 0;
444         
445                 while(quitCommandCalled != 1){
446                         
447                         #ifdef USE_MPI
448                                 int pid, processors;
449                                 MPI_Status status;
450                                 MPI_Comm_rank(MPI_COMM_WORLD, &pid); 
451                                 MPI_Comm_size(MPI_COMM_WORLD, &processors);
452                                 
453                                 if (pid == 0) {
454                                 
455                         #endif
456                         
457                         input = getNextCommand(listOfCommands); 
458                         
459                         if (input == "") { input = "quit()"; }
460                         
461                         mout->mothurOutEndLine();
462                         mout->mothurOut("mothur > " + input);
463                         mout->mothurOutEndLine();
464                         
465                         #ifdef USE_MPI
466                                 //send commandName
467                                 for(int i = 1; i < processors; i++) { 
468                                                 int length = input.length();
469                                                 MPI_Send(&length, 1, MPI_INT, i, 2001, MPI_COMM_WORLD);
470                                                 MPI_Send(&input[0], length, MPI_CHAR, i, 2001, MPI_COMM_WORLD);
471         
472                                         }
473                                 }else {
474                                         int length;
475                                         MPI_Recv(&length, 1, MPI_INT, 0, 2001, MPI_COMM_WORLD, &status);
476                                         //recieve container
477                                         char* tempBuf = new char[length];
478                                         MPI_Recv(&tempBuf[0], length, MPI_CHAR, 0, 2001, MPI_COMM_WORLD, &status);
479                                         
480                                         input = tempBuf;
481                                         if (input.length() > length) { input = input.substr(0, length);  }
482                                         delete tempBuf; 
483                                 }
484
485                         
486                         #endif
487                         
488                         
489                         if (mout->control_pressed) { input = "quit()"; }
490                                 
491                         //allow user to omit the () on the quit command
492                         if (input == "quit") { input = "quit()"; }
493
494                         CommandOptionParser parser(input);
495                         commandName = parser.getCommandString();
496                         options = parser.getOptionString();
497                                                                                 
498                         if (commandName != "") {
499                                         mout->executing = true;
500                                         #ifdef USE_MPI
501                                                 int pid, numProcesses;
502                                                 
503                                                 MPI_Comm_rank(MPI_COMM_WORLD, &pid); 
504                                                 MPI_Comm_size(MPI_COMM_WORLD, &numProcesses); 
505                                         
506 //cout << pid << " is here " << commandName  << endl;
507                                                 if ((cFactory->MPIEnabled(commandName)) || (pid == 0)) {
508                                                         //cout << pid << " is in execute" << endl;      
509                                         #endif
510                                         //executes valid command
511                                         Command* command = cFactory->getCommand(commandName, options);
512                                         quitCommandCalled = command->execute();
513                                         
514                                         //if we aborted command
515                                         if (quitCommandCalled == 2) {  mout->mothurOut("[ERROR]: did not complete " + commandName + "."); mout->mothurOutEndLine(); }
516                                                         
517                                         mout->control_pressed = 0;
518                                         mout->executing = false;
519                                                                         
520                                         #ifdef USE_MPI
521                                         //cout << pid << " is done in execute" << endl;
522                                                 }
523                                         #endif
524                                 }else {         
525                                         mout->mothurOut("Invalid."); 
526                                         mout->mothurOutEndLine();
527                                 }
528
529                         
530                 }
531                 
532                 return 1;
533         }
534         catch(exception& e) {
535                 mout->errorOut(e, "ScriptEngine", "getInput");
536                 exit(1);
537         }
538 }
539 /***********************************************************************/
540 string ScriptEngine::getNextCommand(string& commandString) {
541         try {
542                 
543                 string nextcommand = "";
544                 int count = 0;
545                 bool ignoreSemiColons = false;
546                 
547                 //go through string until you reach ; or end
548                 while (count < commandString.length()) { 
549                         
550                          //you want to ignore any ; until you reach the next '
551                         if ((commandString[count] == '\'') && (!ignoreSemiColons)) {  ignoreSemiColons = true;  } 
552                         else if ((commandString[count] == '\'') && (ignoreSemiColons)) {  ignoreSemiColons = false;  } 
553                                 
554                         if ((commandString[count] == ';') && (!ignoreSemiColons)) {  break;   }
555                         else {          nextcommand += commandString[count];    }
556                         
557                         count++;
558                 }
559                 
560                 //if you are not at the end
561                 if (count != commandString.length())  {   commandString = commandString.substr(count+1, commandString.length());  }
562                 else { commandString = ""; }
563                                 
564                 
565                 //get rid of spaces in between commands if any
566                 if (commandString.length() > 0) {
567                         while (commandString[0] == ' ') {  
568                                 commandString = commandString.substr(1,commandString.length());
569                                 if (commandString.length() == 0) {  break;  }
570                         }
571                 }
572                 
573                 return nextcommand;
574         }
575         catch(exception& e) {
576                 mout->errorOut(e, "ScriptEngine", "getNextCommand");
577                 exit(1);
578         }
579 }
580 /***********************************************************************/