5 * Created by Pat Schloss on 8/15/08.
6 * Copyright 2008 Patrick D. Schloss. All rights reserved.
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.
17 /***********************************************************************/
20 cFactory = CommandFactory::getInstance();
21 mout = MothurOut::getInstance();
24 mout->errorOut(e, "Engine", "Engine");
28 /***********************************************************************/
29 string Engine::findMothursPath(){
32 string envPath = getenv("PATH");
33 string mothurPath = "";
35 //delimiting path char
37 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
43 //break apart path variable by ':'
45 mout->splitAtChar(envPath, dirs, delim);
47 if (mout->debug) { mout->mothurOut("[DEBUG]: dir's in path: \n"); }
49 //get path related to mothur
50 for (int i = 0; i < dirs.size(); i++) {
52 if (mout->debug) { mout->mothurOut("[DEBUG]: " + dirs[i] + "\n"); }
54 //to lower so we can find it
55 string tempLower = "";
56 for (int j = 0; j < dirs[i].length(); j++) { tempLower += tolower(dirs[i][j]); }
58 //is this mothurs path?
59 if (tempLower.find("mothur") != -1) { mothurPath = dirs[i]; break; }
62 if (mout->debug) { mout->mothurOut("[DEBUG]: mothurPath = " + mothurPath + "\n"); }
64 if (mothurPath != "") {
65 //add mothur so it looks like what argv would look like
66 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
67 mothurPath += "/mothur";
69 mothurPath += "\\mothur";
72 //okay mothur is not in the path, so the folder mothur is in must be in the path
73 //lets find out which one
75 //get path related to mothur
76 for (int i = 0; i < dirs.size(); i++) {
78 //is this mothurs path?
80 string tempIn = dirs[i];
81 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
86 mout->openInputFile(tempIn, in, "");
89 if (in) { in.close(); mothurPath = tempIn; break; if (mout->debug) { mout->mothurOut("[DEBUG]: found it, mothurPath = " + mothurPath + "\n"); } }
97 mout->errorOut(e, "Engine", "findMothursPath");
101 /***********************************************************************/
103 InteractEngine::InteractEngine(string path){
106 string temppath = path.substr(0, (path.find_last_of("othur")-5));
108 //this will happen if you set the path variable to contain mothur's exe location
109 if (temppath == "") { path = findMothursPath(); }
114 /***********************************************************************/
116 InteractEngine::~InteractEngine(){}
118 /***********************************************************************/
119 //This function allows the user to input commands one line at a time until they quit.
120 //If the command is garbage it does nothing.
121 bool InteractEngine::getInput(){
124 string commandName = "";
126 int quitCommandCalled = 0;
128 while(quitCommandCalled != 1){
133 MPI_Comm_rank(MPI_COMM_WORLD, &pid);
134 MPI_Comm_size(MPI_COMM_WORLD, &processors);
140 mout->mothurOutEndLine();
142 input = getCommand();
143 mout->mothurOutEndLine();
145 if (mout->control_pressed) { input = "quit()"; }
147 //allow user to omit the () on the quit command
148 if (input == "quit") { input = "quit()"; }
153 for(int i = 1; i < processors; i++) {
154 int length = input.length();
155 MPI_Send(&length, 1, MPI_INT, i, 2001, MPI_COMM_WORLD);
156 MPI_Send(&input[0], length, MPI_CHAR, i, 2001, MPI_COMM_WORLD);
161 MPI_Recv(&length, 1, MPI_INT, 0, 2001, MPI_COMM_WORLD, &status);
163 char* tempBuf = new char[length];
164 MPI_Recv(&tempBuf[0], length, MPI_CHAR, 0, 2001, MPI_COMM_WORLD, &status);
167 if (input.length() > length) { input = input.substr(0, length); }
174 CommandOptionParser parser(input);
175 commandName = parser.getCommandString();
177 options = parser.getOptionString();
179 if (commandName != "") {
180 mout->executing = true;
183 MPI_Comm_rank(MPI_COMM_WORLD, &pid);
185 if ((cFactory->MPIEnabled(commandName)) || (pid == 0)) {
186 //cout << pid << " is in execute " << commandName << endl;
188 //executes valid command
189 mout->runParse = true;
191 mout->clearAllGroups();
192 mout->Treenames.clear();
193 mout->saveNextLabel = "";
194 mout->printedHeaders = false;
195 mout->commandInputsConvertError = false;
196 mout->currentBinLabels.clear();
197 mout->binLabelsInFile.clear();
199 Command* command = cFactory->getCommand(commandName, options);
200 if (mout->commandInputsConvertError) { quitCommandCalled = 2; }
201 else { quitCommandCalled = command->execute(); }
203 //if we aborted command
204 if (quitCommandCalled == 2) { mout->mothurOut("[ERROR]: did not complete " + commandName + "."); mout->mothurOutEndLine(); }
206 mout->control_pressed = 0;
207 mout->executing = false;
213 mout->mothurOut("Invalid.");
214 mout->mothurOutEndLine();
219 catch(exception& e) {
220 mout->errorOut(e, "InteractEngine", "getInput");
224 /***********************************************************************/
225 string Engine::getCommand() {
228 #if defined (__APPLE__) || (__MACH__) || (linux) || (__linux) || (__linux__) || (__unix__) || (__unix)
230 char* nextCommand = NULL;
231 nextCommand = readline("mothur > ");
233 if(nextCommand != NULL) { add_history(nextCommand); }
234 else{ //^D causes null string and we want it to quit mothur
235 nextCommand = strdup("quit");
236 mout->mothurOut(nextCommand);
239 mout->mothurOutJustToLog("mothur > " + toString(nextCommand));
242 string nextCommand = "";
243 mout->mothurOut("mothur > ");
244 getline(cin, nextCommand);
245 mout->mothurOutJustToLog("mothur > " + toString(nextCommand));
250 string nextCommand = "";
252 mout->mothurOut("mothur > ");
253 getline(cin, nextCommand);
254 mout->mothurOutJustToLog(toString(nextCommand));
261 catch(exception& e) {
262 mout->errorOut(e, "Engine", "getCommand");
266 /***********************************************************************/
267 //This function opens the batchfile to be used by BatchEngine::getInput.
268 BatchEngine::BatchEngine(string path, string batchFileName){
271 openedBatch = mout->openInputFile(batchFileName, inputBatchFile);
273 string temppath = path.substr(0, (path.find_last_of("othur")-5));
275 //this will happen if you set the path variable to contain mothur's exe location
276 if (temppath == "") { path = findMothursPath(); }
281 catch(exception& e) {
282 mout->errorOut(e, "BatchEngine", "BatchEngine");
287 /***********************************************************************/
289 BatchEngine::~BatchEngine(){ }
291 /***********************************************************************/
292 //This Function allows the user to run a batchfile containing several commands on Dotur
293 bool BatchEngine::getInput(){
295 //check if this is a valid batchfile
296 if (openedBatch == 1) {
297 mout->mothurOut("unable to open batchfile");
298 mout->mothurOutEndLine();
303 string commandName = "";
306 //CommandFactory cFactory;
307 int quitCommandCalled = 0;
309 while(quitCommandCalled != 1){
314 MPI_Comm_rank(MPI_COMM_WORLD, &pid);
315 MPI_Comm_size(MPI_COMM_WORLD, &processors);
321 input = getNextCommand(inputBatchFile);
326 for(int i = 1; i < processors; i++) {
327 int length = input.length();
328 MPI_Send(&length, 1, MPI_INT, i, 2001, MPI_COMM_WORLD);
329 MPI_Send(&input[0], length, MPI_CHAR, i, 2001, MPI_COMM_WORLD);
334 MPI_Recv(&length, 1, MPI_INT, 0, 2001, MPI_COMM_WORLD, &status);
336 char* tempBuf = new char[length];
337 MPI_Recv(&tempBuf[0], length, MPI_CHAR, 0, 2001, MPI_COMM_WORLD, &status);
340 if (input.length() > length) { input = input.substr(0, length); }
349 if (input[0] != '#') {
351 mout->mothurOutEndLine();
352 mout->mothurOut("mothur > " + input);
353 mout->mothurOutEndLine();
355 if (mout->control_pressed) { input = "quit()"; }
357 //allow user to omit the () on the quit command
358 if (input == "quit") { input = "quit()"; }
360 CommandOptionParser parser(input);
361 commandName = parser.getCommandString();
362 options = parser.getOptionString();
364 if (commandName != "") {
365 mout->executing = true;
368 MPI_Comm_rank(MPI_COMM_WORLD, &pid);
370 //cout << pid << " is here " << commandName << '\t' << count << endl;
371 if ((cFactory->MPIEnabled(commandName)) || (pid == 0)) {
373 //executes valid command
374 mout->runParse = true;
376 mout->clearAllGroups();
377 mout->Treenames.clear();
378 mout->saveNextLabel = "";
379 mout->printedHeaders = false;
380 mout->commandInputsConvertError = false;
381 mout->currentBinLabels.clear();
382 mout->binLabelsInFile.clear();
385 Command* command = cFactory->getCommand(commandName, options);
386 if (mout->commandInputsConvertError) { quitCommandCalled = 2; }
387 else { quitCommandCalled = command->execute(); }
389 //if we aborted command
390 if (quitCommandCalled == 2) { mout->mothurOut("[ERROR]: did not complete " + commandName + "."); mout->mothurOutEndLine(); }
392 mout->control_pressed = 0;
393 mout->executing = false;
399 mout->mothurOut("Invalid.");
400 mout->mothurOutEndLine();
404 mout->gobble(inputBatchFile);
407 inputBatchFile.close();
410 catch(exception& e) {
411 mout->errorOut(e, "BatchEngine", "getInput");
415 /***********************************************************************/
416 string BatchEngine::getNextCommand(ifstream& inputBatchFile) {
419 string nextcommand = "";
421 if (inputBatchFile.eof()) { nextcommand = "quit()"; }
422 else { nextcommand = mout->getline(inputBatchFile); }
426 catch(exception& e) {
427 mout->errorOut(e, "BatchEngine", "getNextCommand");
432 /***********************************************************************/
433 /***********************************************************************/
434 //This function opens the batchfile to be used by BatchEngine::getInput.
435 ScriptEngine::ScriptEngine(string path, string commandString){
439 listOfCommands = commandString.substr(1, (commandString.length()-1));
441 string temppath = path.substr(0, (path.find_last_of("othur")-5));
443 //this will happen if you set the path variable to contain mothur's exe location
444 if (temppath == "") { path = findMothursPath(); }
449 catch(exception& e) {
450 mout->errorOut(e, "ScriptEngine", "ScriptEngine");
455 /***********************************************************************/
457 ScriptEngine::~ScriptEngine(){ }
459 /***********************************************************************/
460 //This Function allows the user to run a batchfile containing several commands on mothur
461 bool ScriptEngine::getInput(){
465 string commandName = "";
469 //CommandFactory cFactory;
470 int quitCommandCalled = 0;
472 while(quitCommandCalled != 1){
477 MPI_Comm_rank(MPI_COMM_WORLD, &pid);
478 MPI_Comm_size(MPI_COMM_WORLD, &processors);
484 input = getNextCommand(listOfCommands);
486 if (input == "") { input = "quit()"; }
489 if ((input.find("quit") != string::npos) || (input.find("set.logfile") != string::npos)) {}
490 else if ((input.find("get.current") != string::npos) && (!mout->hasCurrentFiles())) {}
491 else { mout->mothurOutEndLine(); mout->mothurOut("mothur > " + input); mout->mothurOutEndLine(); }
493 mout->mothurOutEndLine(); mout->mothurOut("mothur > " + input); mout->mothurOutEndLine();
498 for(int i = 1; i < processors; i++) {
499 int length = input.length();
500 MPI_Send(&length, 1, MPI_INT, i, 2001, MPI_COMM_WORLD);
501 MPI_Send(&input[0], length, MPI_CHAR, i, 2001, MPI_COMM_WORLD);
506 MPI_Recv(&length, 1, MPI_INT, 0, 2001, MPI_COMM_WORLD, &status);
508 char* tempBuf = new char[length];
509 MPI_Recv(&tempBuf[0], length, MPI_CHAR, 0, 2001, MPI_COMM_WORLD, &status);
512 if (input.length() > length) { input = input.substr(0, length); }
520 if (mout->control_pressed) { input = "quit()"; }
522 //allow user to omit the () on the quit command
523 if (input == "quit") { input = "quit()"; }
525 CommandOptionParser parser(input);
526 commandName = parser.getCommandString();
527 options = parser.getOptionString();
529 if (commandName != "") {
530 mout->executing = true;
532 int pid, numProcesses;
534 MPI_Comm_rank(MPI_COMM_WORLD, &pid);
535 MPI_Comm_size(MPI_COMM_WORLD, &numProcesses);
537 //cout << pid << " is here " << commandName << endl;
538 if ((cFactory->MPIEnabled(commandName)) || (pid == 0)) {
539 //cout << pid << " is in execute" << endl;
541 //executes valid command
542 mout->runParse = true;
544 mout->clearAllGroups();
545 mout->Treenames.clear();
546 mout->saveNextLabel = "";
547 mout->printedHeaders = false;
548 mout->commandInputsConvertError = false;
549 mout->currentBinLabels.clear();
550 mout->binLabelsInFile.clear();
552 Command* command = cFactory->getCommand(commandName, options);
553 if (mout->commandInputsConvertError) { quitCommandCalled = 2; }
554 else { quitCommandCalled = command->execute(); }
556 //if we aborted command
557 if (quitCommandCalled == 2) { mout->mothurOut("[ERROR]: did not complete " + commandName + "."); mout->mothurOutEndLine(); }
559 mout->control_pressed = 0;
560 mout->executing = false;
563 //cout << pid << " is done in execute" << endl;
567 mout->mothurOut("Invalid.");
568 mout->mothurOutEndLine();
576 catch(exception& e) {
577 mout->errorOut(e, "ScriptEngine", "getInput");
581 /***********************************************************************/
582 string ScriptEngine::getNextCommand(string& commandString) {
585 string nextcommand = "";
587 bool ignoreSemiColons = false;
589 //go through string until you reach ; or end
590 while (count < commandString.length()) {
592 //you want to ignore any ; until you reach the next '
593 if ((commandString[count] == '\'') && (!ignoreSemiColons)) { ignoreSemiColons = true; }
594 else if ((commandString[count] == '\'') && (ignoreSemiColons)) { ignoreSemiColons = false; }
596 if ((commandString[count] == ';') && (!ignoreSemiColons)) { break; }
597 else { nextcommand += commandString[count]; }
602 //if you are not at the end
603 if (count != commandString.length()) { commandString = commandString.substr(count+1, commandString.length()); }
604 else { commandString = ""; }
607 //get rid of spaces in between commands if any
608 if (commandString.length() > 0) {
609 while (commandString[0] == ' ') {
610 commandString = commandString.substr(1,commandString.length());
611 if (commandString.length() == 0) { break; }
617 catch(exception& e) {
618 mout->errorOut(e, "ScriptEngine", "getNextCommand");
622 /***********************************************************************/