1 /*=========================================================================
4 Module: $RCSfile: bbtkInterpreter.cxx,v $ $
6 Date: $Date: 2008/01/29 13:54:47 $
7 Version: $Revision: 1.10 $
9 Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
10 l'Image). All rights reserved. See Doc/License.txt or
11 http://www.creatis.insa-lyon.fr/Public/bbtk/License.html for details.
13 This software is distributed WITHOUT ANY WARRANTY; without even
14 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 PURPOSE. See the above copyright notices for more information.
17 =========================================================================*/
20 * \brief class Interpreter :
23 #include "bbtkInterpreter.h"
24 #include "bbtkMessageManager.h"
25 #include "bbtkConfigurationFile.h"
26 #include "bbtkWxConsole.h"
27 #include "bbtkUtilities.h"
29 #ifdef CMAKE_HAVE_TERMIOS_H
31 #define BBTK_USE_TERMIOS_BASED_PROMPT
39 Interpreter* Interpreter::mGlobalInterpreter = NULL;
41 //=======================================================================
45 Interpreter::Interpreter()
47 mCommandLine(false), verbose(false)
49 bbtk::MessageManager::RegisterMessageType("Echo","Level>0 : Prints the 'echo' commands of the user.\n\tLevel>1 : Prints the command being interpreted",1);
50 bbtk::MessageManager::RegisterMessageType("Interpreter","Messages of the interpreter",0);
51 bbtkDebugMessageInc("Interpreter",9,"Interpreter::Interpreter()" <<std::endl);
53 mGlobalInterpreter = this;
55 // mFactory = new bbtk::Factory();
56 mExecuter = new bbtk::Executer();
57 //mExecuter->SetFactory(mFactory);
59 // Builds the commands dict
66 info.syntax = "new <type> <name>";
67 info.help = "Creates a new black box of type <type> with name <name>";
68 mCommandDict[info.keyword] = info;
70 info.keyword = "delete";
74 info.syntax = "delete <box>";
75 info.help = "Deletes the black box of name <box>";
76 mCommandDict[info.keyword] = info;
78 info.keyword = "connect";
82 info.syntax = "connect <box1.output> <box2.input>";
83 info.help = "Connects the ouput <output> of black box <box1> to the input <input> of black box <box2>";
84 mCommandDict[info.keyword] = info;
86 info.keyword = "print";
90 info.syntax = "print <string>";
91 info.help = "Prints the string. Substitutes any token of the form '$box.output$' by the string adaptation of the output of the box (requires the right adaptor). No carriage return is issued at the end, use '\\n' to add carriage returns. The level of 'Echo' messages must be greater than 1 (see the command 'message').";
92 mCommandDict[info.keyword] = info;
94 info.keyword = "exec";
98 info.syntax = "exec <box | 'freeze' | 'unfreeze' >";
99 info.help = "Executes the black box of name <box> (and connected boxes if needed). If the special keyword 'freeze' is given then freezes any further execution command. 'unfreeze' reverts to normal execution mode.";
100 mCommandDict[info.keyword] = info;
102 info.keyword = "package";
105 info.code = cPackage;
106 info.syntax = "package <name>";
107 info.help = "Begins the definition of a package.";
108 mCommandDict[info.keyword] = info;
110 info.keyword = "endpackage";
113 info.code = cEndPackage;
114 info.syntax = "endpackage";
115 info.help = "Ends the definition of a package.";
116 mCommandDict[info.keyword] = info;
118 info.keyword = "define";
122 info.syntax = "define <type> [<package>]";
123 info.help = "Begins the definition of a new type of complex black box called <type>. If <package> if provided will create it in the given package.";
124 mCommandDict[info.keyword] = info;
126 info.keyword = "endefine";
129 info.code = cEndDefine;
130 info.syntax = "endefine";
131 info.help = "Ends the definition of a new type of complex black box";
132 mCommandDict[info.keyword] = info;
134 info.keyword = "input";
138 info.syntax = "input <name> <box.input> <help>";
139 info.help = "Defines the input <name> of the current working black box as being an alias for the input <input> of the black box <box>. <help> defines the help string for the newly created input";
140 mCommandDict[info.keyword] = info;
142 info.keyword = "output";
146 info.syntax = "output <name> <box.output> <help>";
147 info.help = "Defines the output <name> of the current working black box as being an alias for the output <output> of the black box <box>. <help> defines the help string for the newly created output";
148 mCommandDict[info.keyword] = info;
150 info.keyword = "set";
154 info.syntax = "set <box.input> <value>";
155 info.help = "Sets the value of the input <input> of the black box <box> to <value>. There must exist a string to the value type adaptor";
156 mCommandDict[info.keyword] = info;
158 info.keyword = "config"; // JPR
162 info.syntax = "config [<verbose>|<v>]";
163 info.help = "Prints the value of all configuration parameters";
164 mCommandDict[info.keyword] = info;
166 info.keyword = "reset"; //EED
170 info.syntax = "reset";
171 info.help = "Deletes all boxes and unloads all packages (bbi is reset to its start state)";
172 mCommandDict[info.keyword] = info;
174 info.keyword = "author";
178 info.syntax = "author <string>";
179 info.help = "Adds the string <string> to the author information of the black box being defined";
180 mCommandDict[info.keyword] = info;
182 info.keyword = "description";
185 info.code = cDescription;
186 info.syntax = "description <string>";
187 info.help = "Adds the string <string> to the descriptive information of the black box being defined";
188 mCommandDict[info.keyword] = info;
190 info.keyword = "help";
194 info.syntax = "help";
195 info.syntax = "\n (1) help \n (2) help <command name> \n (3) help packages [all]\n (4) help <package name> [all]\n (5) help <black box type> \n (6) help <black box name>";
196 info.help = "Effect :\n (1) Lists all available commands;\n (2) Prints help on a particular command; \n (3) Lists the packages loaded and their black boxes.\n Add 'all' to list adaptors; \n (4) Prints short help on the black boxes of a package.\n Add 'all' to include adaptors; \n (5) Prints full help on a black box type; \n (6) Prints information on the inputs, outputs and connections of a black box instance.";
197 mCommandDict[info.keyword] = info;
199 info.keyword = "message";
202 info.code = cMessage;
203 info.syntax = "message <category> <level>";
204 info.help = "Sets the level of the category of messages <category> to <level>.\n If category='All' then sets the level for all categories. If no category nor level is passed then prints info on available categories of messages and their current level.";
205 mCommandDict[info.keyword] = info;
207 info.keyword = "include";
210 info.code = cInclude;
211 info.syntax = "include <filename>";
212 info.help = "Includes the file <filename>";
213 mCommandDict[info.keyword] = info;
215 info.keyword = "quit";
219 info.syntax = "quit";
220 info.help = "Quits the program (during script execution it stops the complete execution)";
221 mCommandDict[info.keyword] = info;
223 info.keyword = "load";
227 info.syntax = "load <packagename>";
228 info.help = "Loads the black box package <packagename>";
229 mCommandDict[info.keyword] = info;
231 info.keyword = "unload";
235 info.syntax = "unload <packagename>";
236 info.help = "Unloads the black box package <packagename>";
237 mCommandDict[info.keyword] = info;
239 info.keyword = "graph";
243 info.syntax = "graph [ BlackBoxName [ Detail 0..1 [ Level 0..99999 [ Output html file [ Custom header [ Custom title ]]]]]] \n graph [ BlackBoxNameType [ Detail 0..1 [ Level 0..99999 [ Output html file [ Custom header [ Custom title ]]]]]]";
244 info.help = "Shows a graphical view of a bbtk pipeline.\n- BlackBoxName : name of the box to view. Default '.' : current box.\n- BlackBoxNameType : name of the type of box to view, ex : 'workspace')";
245 mCommandDict[info.keyword] = info;
248 info.keyword = "workspace";
251 info.code = cWorkspace;
252 info.syntax = "workspace < ( freeze | unfreeze ) | ( rename <newname> ) >";
253 info.help = "Configures the workspace.\n 'freeze' allow to block execution commands while keeping definition commands active. 'unfreeze' turns back the worspace in 'normal' mode.\n 'rename' allow to set a new name to the workspace.";
254 mCommandDict[info.keyword] = info;
257 bbtkDebugDecTab("Interpreter",9);
260 //=======================================================================
264 //=======================================================================
268 Interpreter::~Interpreter()
270 bbtkDebugMessageInc("Interpreter",9,"Interpreter::~Interpreter()" <<std::endl);
274 // std::cout <<"EO Interpreter::~Interpreter()"<<std::endl;
275 bbtkDebugDecTab("Interpreter",9);
277 //=======================================================================
280 //=======================================================================
284 void Interpreter::InterpretFile( const std::string& filename, bool use_configuration_file, bool verbose)
286 bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretFile(\""<<filename<<"\")"<<std::endl);
288 bool exm = mCommandLine;
289 mCommandLine = false;
293 SwitchToFile(filename, use_configuration_file, verbose);
294 bool insideComment = false; // for multiline comment
295 while (mFile.size()>0)
297 while ((mFile.size()>0) &&
298 (!mFile.back()->eof()))
302 mFile.back()->getline(buf,500);
304 std::string str(buf);
305 int size=str.length();
306 if ( str[ size-1 ]==13 )
311 InterpretLine(str, insideComment);
313 //if (mFile.size()>0)
317 catch (QuitException e)
320 catch (bbtk::Exception e)
322 std::cerr << "* ERROR : "<<e.GetMessage()<<std::endl;
323 if (mFileName.size()) {
324 std::cerr << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
325 std::cerr << "* LINE : "<<mLine.back()<<std::endl;
328 catch (std::exception& e)
330 std::cerr << "* ERROR : "<<e.what()<<" (not in bbtk)"<<std::endl;
331 if (mFileName.size()) {
332 std::cerr << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
333 std::cerr << "* LINE : "<<mLine.back()<<std::endl;
338 std::cout << "* UNDEFINED ERROR (not a bbtk nor a std exception)"<<std::endl;
339 if (mFileName.size()) {
340 std::cout << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
341 std::cout << "* LINE : "<<mLine.back()<<std::endl;
346 bbtkDebugMessage("Interpreter",9,"EO Interpreter::InterpretFile(\""<<filename<<"\")"<<std::endl);
347 bbtkDecTab("Interpreter",9);
351 //=======================================================================
355 //=======================================================================
359 void Interpreter::InterpretLine( const std::string& line, bool &insideComment )
362 bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretLine(\""<<line<<"\")"<<std::endl);
363 bbtkMessage("Echo",2,"\""<<line<<"\""<<std::endl);
365 std::vector<std::string> words;
366 SplitLine(line,words);
371 bbtkDebugDecTab("Interpreter",9);
375 // Single line comment : # or //
376 if ( words[0][0]=='#' || (words[0][0]=='/' && words[0][1]=='/') )
378 bbtkDebugDecTab("Interpreter",9);
379 bbtkMessage("Interpreter",9,"Comment"<<std::endl);
383 // Multi line comment ( /* ... */ ) -delimiters on different lines !-
385 if (words[0][0]=='/' && words[0][1]=='*')
387 bbtkDebugDecTab("Interpreter",9);
388 bbtkMessage("Interpreter",9,"In multiline comment"<<std::endl);
389 insideComment = true;
393 if (words[0][0]=='*' && words[0][1]=='/')
395 bbtkDebugDecTab("Interpreter",9);
396 bbtkMessage("Interpreter",9,"Out multiline comment"<<std::endl);
397 if ( !insideComment ) {
398 bbtkDebugDecTab("Interpreter",9);
399 bbtkMessage("Interpreter",9,"Comment mismatch : '*/' with no matching '/*'"<<std::endl);
401 insideComment = false;
407 bbtkDebugDecTab("Interpreter",9);
408 bbtkMessage("Interpreter",9,"Multiline Comment"<<std::endl);
413 CommandInfoType command;
414 InterpretCommand(words,command);
416 bbtkDebugMessage("Interpreter",9,
417 "Command='"<<command.keyword
418 <<"' code="<<command.code<<std::endl);
420 std::string left,right,left2,right2;
421 std::string filename;
422 switch (command.code)
425 mExecuter->Create(words[1],words[2]);
430 // mExecuter->Remove(words[1]);
434 Utilities::SplitAroundFirstDot(words[1],left,right);
435 Utilities::SplitAroundFirstDot(words[2],left2,right2);
436 mExecuter->Connect(left,right,left2,right2);
440 mExecuter->BeginPackage(words[1]);
444 mExecuter->EndPackage();
448 if (mFileName.size()>0)
450 filename = Utilities::get_file_name(mFileName.back());
454 mExecuter->Define(words[1],"",filename);
458 mExecuter->Define(words[1],words[2],filename);
463 mExecuter->EndDefine();
467 Print(words[1]); /// \todo use mExecuter
471 if (words[1]=="freeze")
472 mExecuter->SetNoExecMode(true);
473 else if (words[1]=="unfreeze")
474 mExecuter->SetNoExecMode(false);
476 mExecuter->Update(words[1]);
480 Utilities::SplitAroundFirstDot(words[2],left,right);
481 mExecuter->DefineInput(words[1],left,right,words[3]);
485 Utilities::SplitAroundFirstDot(words[2],left,right);
486 mExecuter->DefineOutput(words[1],left,right,words[3]);
490 Utilities::SplitAroundFirstDot(words[1],left,right);
491 mExecuter->Set(left,right,words[2]);
495 mExecuter->Author(words[1]);
499 mExecuter->Description(words[1]);
509 bbtk::MessageManager::PrintInfo();
513 sscanf(words[2].c_str(),"%d",&level);
514 bbtk::MessageManager::SetMessageLevel(words[1],level);
523 if (words.size()>1) // any param for config means verbose = true
531 this->mExecuter->Reset();
537 InterpretFile(words[1], true, verbose); // true : better pass use_config_file
541 SwitchToFile(words[1], true, verbose); // true : better pass use_config_file
546 LoadPackage(words[1], true, verbose); // true : better pass use_config_file
550 UnLoadPackage(words[1]);
554 throw QuitException();
558 if (words.size() == 2)
560 if (words[1]=="freeze") mExecuter->SetNoExecMode(true);
561 else if (words[1]=="unfreeze") mExecuter->SetNoExecMode(false);
565 mExecuter->SetWorkspaceName(words[2]);
570 bbtkInternalError("should not reach here !!!");
573 bbtkDecTab("Interpreter",9);
575 //=======================================================================
579 //=======================================================================
580 void SplitString ( const std::string& str, const std::string& delimiters,
581 std::vector<std::string>& tokens)
583 // Skip delimiters at beginning.
584 std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
585 // Find first delimiter.
586 std::string::size_type pos = str.find_first_of(delimiters, lastPos);
588 while (std::string::npos != pos || std::string::npos != lastPos)
590 // Found a token, add it to the vector.
591 tokens.push_back(str.substr(lastPos, pos - lastPos));
592 // Skip delimiters. Note the "not_of"
593 lastPos = str.find_first_not_of(delimiters, pos);
594 // Find next delimiter
595 pos = str.find_first_of(delimiters, lastPos);
599 //=======================================================================
603 //=======================================================================
607 void Interpreter::SplitLine ( const std::string& str, std::vector<std::string>& tokens)
609 bbtkDebugMessageInc("Interpreter",9,"Interpreter::SplitLine(\""<<str<<"\")"<<std::endl);
611 std::string delimiters = "\"";
612 std::vector<std::string> quote;
613 SplitString(str,delimiters,quote);
616 std::vector<std::string>::iterator i;
617 for (i=quote.begin(); i!=quote.end(); )
619 SplitString(*i,delimiters,tokens);
623 // bbtkDebugMessage("Interpreter",0,"\""<<*i<<"\""<<std::endl);
624 tokens.push_back(*i);
629 for (i=tokens.begin(); i!=tokens.end(); ++i)
631 bbtkDebugMessage("Interpreter",9,"["<<*i<<"] ");
633 bbtkDebugMessageCont("Interpreter",9,std::endl);
635 bbtkDebugDecTab("Interpreter",9);
637 //=======================================================================
640 //=======================================================================
641 // Replaces substrings "\\n" by a real carriage return "\n"
642 void SubsBackslashN ( std::string& s )
644 // std::cout << "BEFORE=["<<s<<"]"<<std::endl;
645 std::string ss("\\n");
646 std::string::size_type pos = 0;
649 while ( pos != std::string::npos )
651 // std::cout << "*** find one "<<std::endl;
652 s.replace(pos,2,cr,1);
653 pos = s.find(ss, pos-1);
655 // std::cout << "AFTER=["<<s<<"]"<<std::endl;
657 //=======================================================================
660 //=======================================================================
664 void Interpreter::Print( const std::string& str)
666 if (mExecuter->GetNoExecMode()) return;
668 bbtkDebugMessageInc("Interpreter",9,"Interpreter::SplitLine(\""<<str<<"\")"<<std::endl);
670 std::vector<std::string> chains;
671 std::string delimiters("$");
673 // Skip delimiters at beginning.
674 std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
676 if (lastPos>0) is_text = false;
678 // Find first delimiter.
679 std::string::size_type pos = str.find_first_of(delimiters, lastPos);
681 while (std::string::npos != pos || std::string::npos != lastPos)
685 // Found a text token, add it to the vector.
686 chains.push_back(str.substr(lastPos, pos - lastPos));
687 // std::cout << "text='"<<chains.back()<<"'"<<std::endl;
691 // is an output (between $$) : decode
692 std::string tok,box,output;
693 tok = str.substr(lastPos, pos - lastPos);
694 Utilities::SplitAroundFirstDot(tok,box,output);
695 chains.push_back( mExecuter->Get(box,output) );
696 // std::cout << "outp='"<<chains.back()<<"'"<<std::endl;
698 // Skip delimiters. Note the "not_of"
699 lastPos = str.find_first_not_of(delimiters, pos);
700 // Find next delimiter
701 pos = str.find_first_of(delimiters, lastPos);
705 // std::cout << "nb="<<chains.size()<<std::endl;
706 std::vector<std::string>::iterator i;
707 for (i= chains.begin(); i!=chains.end(); ++i)
709 // bbtkMessage("Echo",1,*i);
713 std::cout << std::endl;
714 bbtkDebugDecTab("Interpreter",9);
717 //=======================================================================
722 // ===================================================================================
724 void Interpreter::SwitchToFile( const std::string& name,
725 bool use_configuration_file, bool verbose)
727 // Note : in the following :
728 // name : the user supplied name
729 // - abreviated name e.g. scr scr.bbs
730 // - relative full name e.g. ./scr.bbs ../../scr.bbs
731 // - absolute full name e.g. /home/usrname/proj/dir/scr.bbs
732 // same for Windows, with c:, d: ...
734 // expression like directory/subdir/scrname.bbs is FORBIDDEN (*)
735 // use ./directory/subdir/scrname.bbs
737 // (*) except when using packagename/boxes/*
739 bbtkDebugMessageInc("Interpreter",9,"Interpreter::SwitchToFile( \""
740 <<name<<"\")"<<std::endl);
742 // to be remove in final version
745 std::vector<std::string> script_paths;
746 std::string fullPathScriptName; // full path script name
747 std::string pkgname; // e.g. <scriptname>.bbs
749 if (use_configuration_file)
751 // The following is *NOT* a debug time message :
752 // It's a user intended message.
753 // Please don't remove it.
755 std::cout << "look for : [" << name << "] (use_configuration_file == TRUE)" << std::endl;
756 script_paths = ConfigurationFile::GetInstance().Get_bbs_paths();
759 pkgname = Utilities::ExtractScriptName(name,upath);
761 bool fullnameGiven = false;
762 bool foundFile = false;
764 if(pkgname == "*") // =========================================== load all boxes (e.g. std/boxes/*)
767 std::vector<std::string>::iterator i;
768 std::string fullDirectoryName;
769 for (i=script_paths.begin();i!=script_paths.end();++i)
773 // we *really* want '.' to be the current working directory
775 char buf[2048]; // for getcwd
776 char * currentDir = getcwd(buf, 2048);
777 std::string cwd(currentDir);
781 fullDirectoryName = Utilities::MakePkgnameFromPath(path, upath, false);
782 //std::cout <<"fullpath [" << fullDirectoryName << "]" <<std::endl;
783 // Check if library exists
784 if ( ! Utilities::IsDirectory(fullDirectoryName) )
786 // The following is *NOT* a debug time message :
787 // It's a user intended message.
788 // Please don't remove it.
790 std::cout <<" [" <<fullDirectoryName <<"] : doesn't exist" <<std::endl;
791 continue; // try next path
795 std::cout << "recherche tous les .bbs du directory" << std::endl;
796 std::cout << "pour chacun, LoadScript" << std::endl;
798 std::vector<std::string> Filenames;
799 int nbFiles = Utilities::Explore(fullDirectoryName, false, Filenames);
800 // std::cout << "=================nbFiles " << nbFiles << std::endl;
802 for (std::vector<std::string>::iterator i = Filenames.begin(); i!=Filenames.end(); ++i)
804 if ((*i).substr((*i).size()-4, 4) != ".bbs")
805 continue; // ignore non .bbs files
811 std::cout << "WARNING : No '.bbs' file found in [" << fullDirectoryName << "]" << std::endl;
813 break; // a directory was found; we stop iterating
818 std::string::size_type slash_position = name.find_last_of("/\\");
820 // if name contains a slash (anywhere), user is assumed to have passed a relative/absolute name
821 // (not only a plain script name)
822 // we trust him, and try to explade the directory name
823 // WARNING : starting from current local directory : ./whatYouWant (./ mandatory!)
825 // if (slash_position != std::string::npos)
826 if (name[0]=='/' || name[1] == ':')
829 // ===========================================================check user supplied location
830 fullnameGiven = true;
832 fullPathScriptName = Utilities::ExpandLibName(name, verbose);
834 // allow user to always forget ".bbs"
835 int l = fullPathScriptName.size();
840 if (fullPathScriptName.substr(l-4, 4) != ".bbs")
842 fullPathScriptName = fullPathScriptName + ".bbs";
847 fullPathScriptName = fullPathScriptName + ".bbs";
850 //if (fullPathScriptName != "") {
851 if ( Utilities::FileExists(fullPathScriptName))
860 // =============================================================== iterate on the paths
862 std::cout << "iterate"<<std::endl;
864 std::vector<std::string>::iterator i;
865 for (i=script_paths.begin();i!=script_paths.end();++i)
869 std::cout << "CUR=["<<path<<"]"<<std::endl;
870 // we *really* want '.' to be the current working directory
872 std::cout << "PATH IS CURRENT"<<std::endl;
873 char buf[2048]; // for getcwd
874 char * currentDir = getcwd(buf, 2048);
875 std::string cwd(currentDir);
879 // fullPathScriptName = Utilities::MakePkgnameFromPath(path, name, true); //pkgname);
881 fullPathScriptName = Utilities::MakePkgnameFromPath(path, /*pkgnam*/ name, true);
882 std::cout << "FULL PATH = "<<fullPathScriptName<<std::endl;
884 // Check if library exists
885 if ( ! Utilities::FileExists(fullPathScriptName) )
887 // The following is *NOT* a debug time message :
888 // It's a user intended message.
889 // Please don't remove it.
891 std::cout <<" [" <<fullPathScriptName <<"] : doesn't exist" <<std::endl;
892 continue; // try next path
895 break; // a script was found; we stop iterating
897 } //------------------ // end for ( package_paths.begin();i!=package_paths.end() )
903 if(fullPathScriptName == "")
904 bbtkError("Path ["<<upath<<"] doesn't exist");
906 bbtkError("Script ["<<fullPathScriptName<<"] not found");
908 bbtkError("No ["<<pkgname<<".bbs] script found");
912 LoadScript(fullPathScriptName);
918 //=======================================================================
920 void Interpreter::LoadScript( std::string fullPathScriptName)
922 bbtkMessage("Interpreter",1,fullPathScriptName<<" found"<<std::endl);
925 s = new std::ifstream;
926 s->open(fullPathScriptName.c_str());
929 bbtkError("Could not open file ["<<fullPathScriptName<<"]");
934 std::cout << " -->[" << fullPathScriptName << "] found" << std::endl;
937 mFileName.push_back(fullPathScriptName);
942 //=======================================================================
946 void Interpreter::CloseCurrentFile()
948 bbtkDebugMessage("Interpreter",9,"Interpreter::CloseCurrentFile()"
953 bbtkDebugMessage("Interpreter",9," -> no file left open"<<std::endl);
957 mFile.back()->close();
960 bbtkDebugMessage("Interpreter",9,
961 " Closing file '"<<mFileName.back()<<"'"<<std::endl);
963 mFileName.pop_back();
965 bbtkDebugMessage("Interpreter",9," Remains "
967 <<" open"<<std::endl);
968 bbtkDebugMessage("Interpreter",9,"EO Interpreter::CloseCurrentFile()"
971 //=======================================================================
973 //=======================================================================
977 void Interpreter::CloseAllFiles()
979 bbtkDebugMessage("Interpreter",9,"Interpreter::CloseAllFiles()"
982 while (mFile.size() != 0)
984 mFile.back()->close();
987 bbtkDebugMessage("Interpreter",9,
988 " Closing file '"<<mFileName.back()<<"'"<<std::endl);
989 mFileName.pop_back();
992 bbtkDebugMessage("Interpreter",9,"EO Interpreter::CloseAllFiles()"
995 //=======================================================================
999 //=======================================================================
1003 void Interpreter::InterpretCommand( const std::vector<std::string>& words,
1004 CommandInfoType& info )
1006 bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretCommand(...)"<<std::endl);
1008 // searches the command keyword
1009 CommandDictType::iterator c;
1010 c = mCommandDict.find(words[0]);
1011 if ( c == mCommandDict.end() ) {
1012 bbtkError(words[0]<<" : unknown command");
1015 // tests the number of args
1016 if ( ( words.size()-1 < c->second.argmin ) ||
1017 ( words.size()-1 > c->second.argmax ) )
1019 HelpCommand(words[0]);
1020 bbtkError(words[0]<<" : wrong number of arguments");
1024 bbtkDecTab("Interpreter",9);
1026 //=======================================================================
1029 //=======================================================================
1030 /// Displays help on all the commands
1031 void Interpreter::Help(const std::vector<std::string>& words)
1033 unsigned int nbarg = words.size()-1;
1041 if (words[1]=="packages")
1043 PrintPackages(true);
1048 HelpCommand(words[1]);
1050 catch (bbtk::Exception e)
1054 HelpPackage(words[1]);
1056 catch (bbtk::Exception f)
1060 HelpBlackBox(words[1]);
1062 catch (bbtk::Exception g)
1066 this->mExecuter->ShowRelations(words[1],"0","9999");
1068 catch (bbtk::Exception h){
1069 bbtkError("\""<<words[1].c_str()
1070 <<"\" is not a known command, package, black box type or black box name");
1078 if (words[2]=="all")
1080 if ( words[1]=="packages" )
1082 PrintPackages(true,true);
1087 HelpPackage(words[1],true);
1089 catch (bbtk::Exception f)
1095 HelpCommand(words[0]);
1096 bbtkError(words[0]<<" : syntax error");
1101 bbtkError("Should not reach here !!!");
1104 //=======================================================================
1106 //===================================================================
1107 /// Displays the Configuration
1108 void Interpreter::Config( bool verbose ) const
1110 bbtkDebugMessageInc("Core",9,"Factory::Config"<<std::endl);
1112 ConfigurationFile cf = ConfigurationFile::GetInstance();
1114 const std::string config_xml_full_path = cf.Get_config_xml_full_path();
1115 const std::string description = cf.Get_description();
1116 const std::string url = cf.Get_url();
1117 const std::string data_path = cf.Get_data_path();
1118 const std::string default_doc_tmp = cf.Get_default_doc_tmp();
1119 const std::string file_separator = cf.Get_file_separator();
1120 const std::vector<std::string>bbs_paths = cf.Get_bbs_paths();
1121 const std::vector<std::string>package_paths = cf.Get_package_paths();
1123 bbtkMessage("Help",1, "=============" << std::endl);
1124 bbtkMessage("Help",1, "Configuration" << std::endl);
1125 bbtkMessage("Help",1, "=============" << std::endl);
1126 bbtkMessage("Help",1, "bbtk_config.xml : [" << config_xml_full_path << "]" << std::endl);
1127 bbtkMessage("Help",1, "Documentation Url : [" << url << "]" << std::endl);
1128 bbtkMessage("Help",1, "Data Path : [" << data_path << "]" << std::endl);
1129 bbtkMessage("Help",1, "Default Doc_tmp : [" << default_doc_tmp << "]" << std::endl);
1130 bbtkMessage("Help",1, "File Separator : [" << file_separator << "]" << std::endl);
1132 std::vector<std::string>::const_iterator i;
1134 bbtkMessage("Help",1, "BBS Paths " << std::endl);
1135 for (i = bbs_paths.begin(); i!=bbs_paths.end(); ++i )
1137 bbtkMessage("Help",1,"--- ["<<*i<<"]"<<std::endl);
1140 bbtkMessage("Help",1, "PACKAGE Paths : " << std::endl);
1141 for (i = package_paths.begin(); i!=package_paths.end(); ++i )
1143 bbtkMessage("Help",1,"--- ["<<*i<<"]"<<std::endl);
1146 bbtkDebugDecTab("Core",9);
1149 //=======================================================================
1150 /// Displays help on all the commands
1151 void Interpreter::HelpCommands()
1153 std::cout << "Available commands :" << std::endl;
1154 CommandDictType::iterator i;
1155 for ( i = mCommandDict.begin();
1156 i != mCommandDict.end();
1158 std::cout << " " << i->first << std::endl;
1159 // std::cout << " usage : " << i->second.syntax << std::endl;
1160 // std::cout << " " << i->second.help << std::endl;
1164 //=======================================================================
1167 //=======================================================================
1168 /// Displays help on a particular commands
1169 void Interpreter::HelpCommand(const std::string& s)
1171 CommandDictType::iterator c;
1172 c = mCommandDict.find(s);
1173 if ( c == mCommandDict.end() ) {
1174 bbtkError(s<<" : Unknown command");
1176 // std::cout << " " << s << " : "<< std::endl;
1177 // CommandParamDictType::iterator i;
1178 // for ( i = c->second.begin();
1179 // i != c->second.end();
1181 std::cout << " usage : " << c->second.syntax << std::endl;
1182 std::cout << " " << c->second.help << std::endl;
1185 //=======================================================================
1188 //=======================================================================
1189 /// Fills the vector commands with the commands which
1190 /// have the first n chars of buf for prefix
1191 /// TODO : skip initial spaces in buf and also return the position of first
1192 /// non blank char in buf
1193 void Interpreter::FindCommandsWithPrefix( char* buf,
1195 std::vector<std::string>& commands )
1197 CommandDictType::const_iterator i;
1198 for (i=mCommandDict.begin(); i!=mCommandDict.end(); ++i)
1200 if ((i->first).find(buf,0,n) == 0)
1201 commands.push_back(i->first);
1204 //=======================================================================
1208 //=======================================================================
1209 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1211 inline void PrintChar(char c) { write(STDOUT_FILENO,&c,1); }
1212 inline void BackSpace() { write(STDOUT_FILENO,"\b \b",3); }
1214 // LG : KEYBOARD CODES AS SCANNED ON MY TTY : UNIVERSAL ?
1215 // IF NOT THE USER SHOULD BE ABLE TO CONFIGURE IT
1216 // E.G. STORE THIS IN bbtk_config.xml
1217 #define BBTK_UP_ARROW_KBCODE 0x00415B1B
1218 #define BBTK_DOWN_ARROW_KBCODE 0x00425B1B
1219 #define BBTK_RIGHT_ARROW_KBCODE 0x00435B1B
1220 #define BBTK_LEFT_ARROW_KBCODE 0x00445B1B
1221 #define BBTK_BACKSPACE_KBCODE 0x00000008
1222 #define BBTK_DEL_KBCODE 0x0000007F
1223 #define BBTK_SPACE_KBCODE 0x00000020
1225 //=======================================================================
1226 void Interpreter::GetLineFromPrompt(std::string& s)
1231 int MAX_LINE_SIZE = 160;
1232 int MAX_HISTORY_SIZE = 100;
1234 char* newline = new char[MAX_LINE_SIZE];
1235 memset(newline,0,MAX_LINE_SIZE);
1236 char* histline = new char[MAX_LINE_SIZE];
1237 memset(histline,0,MAX_LINE_SIZE);
1239 char* line = newline;
1240 int hist = mHistory.size();
1247 read ( STDIN_FILENO, &c, 4) ;
1249 bbtkDebugMessage("Debug",9,"[0x"<<std::hex<<c<<"]\n");
1251 // Printable character
1252 if ( (ind<MAX_LINE_SIZE-1) &&
1253 ( c >= BBTK_SPACE_KBCODE ) &&
1254 ( c < BBTK_DEL_KBCODE ))
1262 // delete the unused line
1268 // empty lines are not stored in from history
1271 // if history too long : delete oldest command
1272 if (mHistory.size()>MAX_HISTORY_SIZE)
1274 delete mHistory.front();
1275 mHistory.pop_front();
1277 mHistory.push_back(line);
1282 else if ( (ind>0) &&
1283 ((c == BBTK_BACKSPACE_KBCODE) ||
1284 (c == BBTK_DEL_KBCODE)) )
1292 // TODO : Command completion
1293 std::vector<std::string> commands;
1294 FindCommandsWithPrefix( line,ind,commands);
1295 if (commands.size()==1)
1297 std::string com = *commands.begin();
1298 for (; ind<com.size(); ++ind)
1300 PrintChar(com[ind]);
1306 else if (commands.size()>1)
1308 std::vector<std::string>::iterator i;
1310 for (i=commands.begin();i!=commands.end();++i)
1312 write(STDOUT_FILENO,(*i).c_str(),strlen((*i).c_str()));
1315 write(STDOUT_FILENO,"\n> ",3);
1316 //for (int j=0;j<ind;++j)
1318 write(STDOUT_FILENO,line,ind);
1322 // Arrow up : back in history
1323 else if (c==BBTK_UP_ARROW_KBCODE)
1327 // erase current line
1328 while (ind--) BackSpace();
1332 strcpy(histline,mHistory[hist]);
1336 write(STDOUT_FILENO,line,ind);
1339 // Arrow down : down in history
1340 else if (c==BBTK_DOWN_ARROW_KBCODE)
1342 if (hist<mHistory.size()-1)
1344 // erase current line
1345 while (ind--) BackSpace();
1349 strcpy(histline,mHistory[hist]);
1353 write(STDOUT_FILENO,line,ind);
1355 // end of history : switch back to newline
1356 else if (hist==mHistory.size()-1)
1358 // erase current line
1359 while (ind--) BackSpace();
1366 write(STDOUT_FILENO,line,ind);
1370 else if (line[ind]!=0 && c==BBTK_RIGHT_ARROW_KBCODE)
1372 PrintChar(line[ind]);
1377 else if (ind>0 && c==BBTK_LEFT_ARROW_KBCODE)
1385 write(STDOUT_FILENO,"\n\r",2);
1393 //=======================================================================
1394 void Interpreter::GetLineFromPrompt(std::string& s)
1420 //=======================================================================
1426 //=======================================================================
1427 void Interpreter::CommandLineInterpreter()
1429 bbtkDebugMessageInc("Interpreter",9,
1430 "Interpreter::CommandLineInterpreter()"<<std::endl);
1432 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1433 // Initialise the tty in non canonical mode with no echo
1434 // oter remembers the previous settings to restore them after
1435 struct termios ter,oter;
1438 ter.c_lflag &= ~ECHO;
1439 ter.c_lflag &= ~ICANON;
1442 tcsetattr(0,TCSANOW,&ter);
1445 mCommandLine = true;
1447 bool insideComment = false; // for multiline comment
1453 GetLineFromPrompt(line);
1454 InterpretLine(line, insideComment);
1456 catch (QuitException e)
1460 catch (bbtk::Exception e)
1464 catch (std::exception& e)
1466 std::cerr << "* ERROR :: "<<e.what()<<" (not in bbtk)"<<std::endl;
1470 std::cerr << "* UNDEFINED ERROR (not a bbtk nor a std exception)"<<std::endl;
1475 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1476 tcsetattr(0,TCSANOW,&oter);
1479 std::cout << "Good bye !" << std::endl;
1481 bbtkDebugDecTab("Interpreter",9);
1484 //=======================================================================
1485 void Interpreter::Graph(const std::vector<std::string>& words)
1488 bool system_display = true;
1490 #ifdef _USE_WXWIDGETS_
1491 if ( WxConsole::GetInstance() != 0 ) system_display = false;
1494 if (words.size()==1)
1496 page = mExecuter->ShowGraph(".","0","0","","","",system_display);
1498 else if (words.size()==2)
1500 page = mExecuter->ShowGraph(words[1],"0","0","","","",system_display);
1502 else if (words.size()==3)
1504 page = mExecuter->ShowGraph(words[1],words[2],"0","","","",system_display);
1506 else if (words.size()==4)
1508 page = mExecuter->ShowGraph(words[1],words[2],words[3],"","","",system_display);
1510 else if (words.size()==5)
1512 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],"","",system_display);
1514 else if (words.size()==6)
1516 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],"",system_display);
1518 else if (words.size()==7)
1520 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],words[6],system_display);
1523 #ifdef _USE_WXWIDGETS_
1524 if ( WxConsole::GetInstance() != 0 )
1525 WxConsole::GetInstance()->ShowHtmlPage(page);
1528 //=======================================================================