1 /*=========================================================================
4 Module: $RCSfile: bbtkInterpreter.cxx,v $ $
6 Date: $Date: 2008/01/22 16:55:04 $
7 Version: $Revision: 1.2 $
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
38 Interpreter* Interpreter::mGlobalInterpreter = NULL;
40 //=======================================================================
44 Interpreter::Interpreter()
46 mCommandLine(false), verbose(false)
48 bbtk::MessageManager::RegisterMessageType("Echo","Level>0 : Prints the 'echo' commands of the user.\n\tLevel>1 : Prints the command being interpreted",1);
49 bbtk::MessageManager::RegisterMessageType("Interpreter","Messages of the interpreter",0);
50 bbtkDebugMessageInc("Interpreter",9,"Interpreter::Interpreter()" <<std::endl);
52 mGlobalInterpreter = this;
54 // mFactory = new bbtk::Factory();
55 mExecuter = new bbtk::Executer();
56 //mExecuter->SetFactory(mFactory);
58 // Builds the commands dict
65 info.syntax = "new <type> <name>";
66 info.help = "Creates a new black box of type <type> with name <name>";
67 mCommandDict[info.keyword] = info;
69 info.keyword = "delete";
73 info.syntax = "delete <box>";
74 info.help = "Deletes the black box of name <box>";
75 mCommandDict[info.keyword] = info;
77 info.keyword = "connect";
81 info.syntax = "connect <box1.output> <box2.input>";
82 info.help = "Connects the ouput <output> of black box <box1> to the input <input> of black box <box2>";
83 mCommandDict[info.keyword] = info;
85 info.keyword = "print";
89 info.syntax = "print <string>";
90 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').";
91 mCommandDict[info.keyword] = info;
93 info.keyword = "exec";
97 info.syntax = "exec <box | 'freeze' | 'unfreeze' >";
98 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.";
99 mCommandDict[info.keyword] = info;
101 info.keyword = "define";
105 info.syntax = "define <type> [<package>]";
106 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.";
107 mCommandDict[info.keyword] = info;
109 info.keyword = "endefine";
112 info.code = cEndDefine;
113 info.syntax = "endefine";
114 info.help = "Ends the definition of a new type of complex black box";
115 mCommandDict[info.keyword] = info;
117 info.keyword = "input";
121 info.syntax = "input <name> <box.input> <help>";
122 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";
123 mCommandDict[info.keyword] = info;
125 info.keyword = "output";
129 info.syntax = "output <name> <box.output> <help>";
130 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";
131 mCommandDict[info.keyword] = info;
133 info.keyword = "set";
137 info.syntax = "set <box.input> <value>";
138 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";
139 mCommandDict[info.keyword] = info;
141 info.keyword = "config"; // JPR
145 info.syntax = "config [<verbose>|<v>]";
146 info.help = "Prints the value of all configuration parameters";
147 mCommandDict[info.keyword] = info;
149 info.keyword = "reset"; //EED
153 info.syntax = "reset";
154 info.help = "Deletes all boxes and unloads all packages (bbi is reset to its start state)";
155 mCommandDict[info.keyword] = info;
157 info.keyword = "author";
161 info.syntax = "author <string>";
162 info.help = "Adds the string <string> to the author information of the black box being defined";
163 mCommandDict[info.keyword] = info;
165 info.keyword = "description";
168 info.code = cDescription;
169 info.syntax = "description <string>";
170 info.help = "Adds the string <string> to the descriptive information of the black box being defined";
171 mCommandDict[info.keyword] = info;
173 info.keyword = "help";
177 info.syntax = "help";
178 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>";
179 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.";
180 mCommandDict[info.keyword] = info;
182 info.keyword = "message";
185 info.code = cMessage;
186 info.syntax = "message <category> <level>";
187 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.";
188 mCommandDict[info.keyword] = info;
190 info.keyword = "include";
193 info.code = cInclude;
194 info.syntax = "include <filename>";
195 info.help = "Includes the file <filename>";
196 mCommandDict[info.keyword] = info;
198 info.keyword = "quit";
202 info.syntax = "quit";
203 info.help = "Quits the program (during script execution it stops the complete execution)";
204 mCommandDict[info.keyword] = info;
206 info.keyword = "load";
210 info.syntax = "load <packagename>";
211 info.help = "Loads the black box package <packagename>";
212 mCommandDict[info.keyword] = info;
214 info.keyword = "unload";
218 info.syntax = "unload <packagename>";
219 info.help = "Unloads the black box package <packagename>";
220 mCommandDict[info.keyword] = info;
222 info.keyword = "graph";
226 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 ]]]]]]";
227 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')";
228 mCommandDict[info.keyword] = info;
231 info.keyword = "workspace";
234 info.code = cWorkspace;
235 info.syntax = "workspace < ( freeze | unfreeze ) | ( rename <newname> ) >";
236 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.";
237 mCommandDict[info.keyword] = info;
240 bbtkDebugDecTab("Interpreter",9);
243 //=======================================================================
247 //=======================================================================
251 Interpreter::~Interpreter()
253 bbtkDebugMessageInc("Interpreter",9,"Interpreter::~Interpreter()" <<std::endl);
257 // std::cout <<"EO Interpreter::~Interpreter()"<<std::endl;
258 bbtkDebugDecTab("Interpreter",9);
260 //=======================================================================
263 //=======================================================================
267 void Interpreter::InterpretFile( const std::string& filename, bool use_configuration_file, bool verbose)
269 bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretFile(\""<<filename<<"\")"<<std::endl);
271 bool exm = mCommandLine;
272 mCommandLine = false;
276 SwitchToFile(filename, use_configuration_file, verbose);
277 bool insideComment = false; // for multiline comment
278 while (mFile.size()>0)
280 while ((mFile.size()>0) &&
281 (!mFile.back()->eof()))
285 mFile.back()->getline(buf,500);
287 std::string str(buf);
288 int size=str.length();
289 if ( str[ size-1 ]==13 )
294 InterpretLine(str, insideComment);
296 //if (mFile.size()>0)
300 catch (QuitException e)
303 catch (bbtk::Exception e)
305 std::cerr << "* ERROR : "<<e.GetMessage()<<std::endl;
306 if (mFileName.size()) {
307 std::cerr << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
308 std::cerr << "* LINE : "<<mLine.back()<<std::endl;
311 catch (std::exception& e)
313 std::cerr << "* ERROR : "<<e.what()<<" (not in bbtk)"<<std::endl;
314 if (mFileName.size()) {
315 std::cerr << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
316 std::cerr << "* LINE : "<<mLine.back()<<std::endl;
321 std::cout << "* UNDEFINED ERROR (not a bbtk nor a std exception)"<<std::endl;
322 if (mFileName.size()) {
323 std::cout << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
324 std::cout << "* LINE : "<<mLine.back()<<std::endl;
329 bbtkDebugMessage("Interpreter",9,"EO Interpreter::InterpretFile(\""<<filename<<"\")"<<std::endl);
330 bbtkDecTab("Interpreter",9);
334 //=======================================================================
338 //=======================================================================
342 void Interpreter::InterpretLine( const std::string& line, bool &insideComment )
345 bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretLine(\""<<line<<"\")"<<std::endl);
346 bbtkMessage("Echo",2,"\""<<line<<"\""<<std::endl);
348 std::vector<std::string> words;
349 SplitLine(line,words);
354 bbtkDebugDecTab("Interpreter",9);
358 // Single line comment : # or //
359 if ( words[0][0]=='#' || (words[0][0]=='/' && words[0][1]=='/') )
361 bbtkDebugDecTab("Interpreter",9);
362 bbtkMessage("Interpreter",9,"Comment"<<std::endl);
366 // Multi line comment ( /* ... */ ) -delimiters on different lines !-
368 if (words[0][0]=='/' && words[0][1]=='*')
370 bbtkDebugDecTab("Interpreter",9);
371 bbtkMessage("Interpreter",9,"In multiline comment"<<std::endl);
372 insideComment = true;
376 if (words[0][0]=='*' && words[0][1]=='/')
378 bbtkDebugDecTab("Interpreter",9);
379 bbtkMessage("Interpreter",9,"Out multiline comment"<<std::endl);
380 if ( !insideComment ) {
381 bbtkDebugDecTab("Interpreter",9);
382 bbtkMessage("Interpreter",9,"Comment mismatch : '*/' with no matching '/*'"<<std::endl);
384 insideComment = false;
390 bbtkDebugDecTab("Interpreter",9);
391 bbtkMessage("Interpreter",9,"Multiline Comment"<<std::endl);
396 CommandInfoType command;
397 InterpretCommand(words,command);
399 bbtkDebugMessage("Interpreter",9,
400 "Command '"<<command.keyword
401 <<" code="<<command.code<<std::endl);
403 std::string left,right,left2,right2;
404 std::string filename;
405 switch (command.code)
408 mExecuter->Create(words[1],words[2]);
413 // mExecuter->Remove(words[1]);
417 Utilities::SplitAroundFirstDot(words[1],left,right);
418 Utilities::SplitAroundFirstDot(words[2],left2,right2);
419 mExecuter->Connect(left,right,left2,right2);
423 if (mFileName.size()>0)
425 filename = Utilities::get_file_name(mFileName.back());
429 mExecuter->Define(words[1],"user",filename);
433 mExecuter->Define(words[1],words[2],filename);
438 mExecuter->EndDefine();
442 Print(words[1]); /// \todo use mExecuter
446 if (words[1]=="freeze")
447 mExecuter->SetNoExecMode(true);
448 else if (words[1]=="unfreeze")
449 mExecuter->SetNoExecMode(false);
451 mExecuter->Update(words[1]);
455 Utilities::SplitAroundFirstDot(words[2],left,right);
456 mExecuter->DefineInput(words[1],left,right,words[3]);
460 Utilities::SplitAroundFirstDot(words[2],left,right);
461 mExecuter->DefineOutput(words[1],left,right,words[3]);
465 Utilities::SplitAroundFirstDot(words[1],left,right);
466 mExecuter->Set(left,right,words[2]);
470 mExecuter->Author(words[1]);
474 mExecuter->Description(words[1]);
484 bbtk::MessageManager::PrintInfo();
488 sscanf(words[2].c_str(),"%d",&level);
489 bbtk::MessageManager::SetMessageLevel(words[1],level);
498 if (words.size()>1) // any param for config means verbose = true
506 this->mExecuter->Reset();
512 InterpretFile(words[1], true, verbose); // true : better pass use_config_file
516 SwitchToFile(words[1], true, verbose); // true : better pass use_config_file
521 LoadPackage(words[1], true, verbose); // true : better pass use_config_file
525 UnLoadPackage(words[1]);
529 throw QuitException();
533 if (words.size() == 2)
535 if (words[1]=="freeze") mExecuter->SetNoExecMode(true);
536 else if (words[1]=="unfreeze") mExecuter->SetNoExecMode(false);
540 mExecuter->SetWorkspaceName(words[2]);
545 bbtkInternalError("should not reach here !!!");
548 bbtkDecTab("Interpreter",9);
550 //=======================================================================
554 //=======================================================================
555 void SplitString ( const std::string& str, const std::string& delimiters,
556 std::vector<std::string>& tokens)
558 // Skip delimiters at beginning.
559 std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
560 // Find first delimiter.
561 std::string::size_type pos = str.find_first_of(delimiters, lastPos);
563 while (std::string::npos != pos || std::string::npos != lastPos)
565 // Found a token, add it to the vector.
566 tokens.push_back(str.substr(lastPos, pos - lastPos));
567 // Skip delimiters. Note the "not_of"
568 lastPos = str.find_first_not_of(delimiters, pos);
569 // Find next delimiter
570 pos = str.find_first_of(delimiters, lastPos);
574 //=======================================================================
578 //=======================================================================
582 void Interpreter::SplitLine ( const std::string& str, std::vector<std::string>& tokens)
584 bbtkDebugMessageInc("Interpreter",9,"Interpreter::SplitLine(\""<<str<<"\")"<<std::endl);
586 std::string delimiters = "\"";
587 std::vector<std::string> quote;
588 SplitString(str,delimiters,quote);
591 std::vector<std::string>::iterator i;
592 for (i=quote.begin(); i!=quote.end(); )
594 SplitString(*i,delimiters,tokens);
598 // bbtkDebugMessage("Interpreter",0,"\""<<*i<<"\""<<std::endl);
599 tokens.push_back(*i);
604 for (i=tokens.begin(); i!=tokens.end(); ++i)
606 bbtkDebugMessage("Interpreter",9,"["<<*i<<"] ");
608 bbtkDebugMessageCont("Interpreter",9,std::endl);
610 bbtkDebugDecTab("Interpreter",9);
612 //=======================================================================
615 //=======================================================================
616 // Replaces substrings "\\n" by a real carriage return "\n"
617 void SubsBackslashN ( std::string& s )
619 // std::cout << "BEFORE=["<<s<<"]"<<std::endl;
620 std::string ss("\\n");
621 std::string::size_type pos = 0;
624 while ( pos != std::string::npos )
626 // std::cout << "*** find one "<<std::endl;
627 s.replace(pos,2,cr,1);
628 pos = s.find(ss, pos-1);
630 // std::cout << "AFTER=["<<s<<"]"<<std::endl;
632 //=======================================================================
635 //=======================================================================
639 void Interpreter::Print( const std::string& str)
641 if (mExecuter->GetNoExecMode()) return;
643 bbtkDebugMessageInc("Interpreter",9,"Interpreter::SplitLine(\""<<str<<"\")"<<std::endl);
645 std::vector<std::string> chains;
646 std::string delimiters("$");
648 // Skip delimiters at beginning.
649 std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
651 if (lastPos>0) is_text = false;
653 // Find first delimiter.
654 std::string::size_type pos = str.find_first_of(delimiters, lastPos);
656 while (std::string::npos != pos || std::string::npos != lastPos)
660 // Found a text token, add it to the vector.
661 chains.push_back(str.substr(lastPos, pos - lastPos));
662 // std::cout << "text='"<<chains.back()<<"'"<<std::endl;
666 // is an output (between $$) : decode
667 std::string tok,box,output;
668 tok = str.substr(lastPos, pos - lastPos);
669 Utilities::SplitAroundFirstDot(tok,box,output);
670 chains.push_back( mExecuter->Get(box,output) );
671 // std::cout << "outp='"<<chains.back()<<"'"<<std::endl;
673 // Skip delimiters. Note the "not_of"
674 lastPos = str.find_first_not_of(delimiters, pos);
675 // Find next delimiter
676 pos = str.find_first_of(delimiters, lastPos);
680 // std::cout << "nb="<<chains.size()<<std::endl;
681 std::vector<std::string>::iterator i;
682 for (i= chains.begin(); i!=chains.end(); ++i)
684 // bbtkMessage("Echo",1,*i);
688 std::cout << std::endl;
689 bbtkDebugDecTab("Interpreter",9);
692 //=======================================================================
697 // ===================================================================================
700 void Interpreter::SwitchToFile( const std::string& name,
701 bool use_configuration_file, bool verbose)
703 bbtkDebugMessageInc("Interpreter",9,"Interpreter::SwitchToFile( \""
704 <<name<<"\")"<<std::endl);
706 std::vector<std::string> script_paths;
707 std::string libname; // full path library name
708 std::string pkgname; // e.g. <scriptname>.bbs
710 pkgname = Utilities::ExtractScriptName(name);
712 if (use_configuration_file)
715 std::cout << "look for : [" << name << "] (use_configuration_file == TRUE)" << std::endl;
716 script_paths = ConfigurationFile::GetInstance().Get_bbs_paths();
719 bool fullnameGiven = false;
720 bool foundFile = false;
721 std::string::size_type slash_position = name.find_last_of("/\\");
723 if (slash_position != std::string::npos)
725 fullnameGiven = true;
726 libname = Utilities::ExpandLibName(name, verbose);
728 if ( Utilities::FileExists(libname))
734 else // ----------------------- iterate on the paths
737 std::vector<std::string>::iterator i;
738 for (i=script_paths.begin();i!=script_paths.end();++i)
742 // we *really* want '.' to be the current working directory
744 char buf[2048]; // for getcwd
745 char * currentDir = getcwd(buf, 2048);
746 std::string cwd(currentDir);
750 libname = Utilities::MakePkgnameFromPath(path, pkgname);
752 // Check if library exists
753 if ( ! Utilities::FileExists(libname) )
756 std::cout <<" [" <<libname <<"] : doesn't exist" <<std::endl;
757 continue; // try next path
760 break; // a script was found; we stop iterating
762 } //------------------ // end for ( package_paths.begin();i!=package_paths.end() )
771 bbtkError("Path \""<<name<<"\" doesn't exist");
773 bbtkError("Script \""<<libname<<"\" not found");
775 bbtkError("No \""<<pkgname<<".bbs\" script found");
779 bbtkMessage("Interpreter",1,pkgname<<" loaded"<<std::endl);
781 s = new std::ifstream;
782 s->open(libname.c_str());
785 bbtkError("Could not open file \""<<libname<<"\"");
790 std::cout << " -->[" << libname << "] found" << std::endl;
793 mFileName.push_back(libname);
798 //=======================================================================
801 //=======================================================================
805 void Interpreter::CloseCurrentFile()
807 bbtkDebugMessage("Interpreter",9,"Interpreter::CloseCurrentFile()"
812 bbtkDebugMessage("Interpreter",9," -> no file left open"<<std::endl);
816 mFile.back()->close();
819 bbtkDebugMessage("Interpreter",9,
820 " Closing file '"<<mFileName.back()<<"'"<<std::endl);
822 mFileName.pop_back();
824 bbtkDebugMessage("Interpreter",9," Remains "
826 <<" open"<<std::endl);
827 bbtkDebugMessage("Interpreter",9,"EO Interpreter::CloseCurrentFile()"
830 //=======================================================================
832 //=======================================================================
836 void Interpreter::CloseAllFiles()
838 bbtkDebugMessage("Interpreter",9,"Interpreter::CloseAllFiles()"
841 while (mFile.size() != 0)
843 mFile.back()->close();
846 bbtkDebugMessage("Interpreter",9,
847 " Closing file '"<<mFileName.back()<<"'"<<std::endl);
848 mFileName.pop_back();
851 bbtkDebugMessage("Interpreter",9,"EO Interpreter::CloseAllFiles()"
854 //=======================================================================
858 //=======================================================================
862 void Interpreter::InterpretCommand( const std::vector<std::string>& words,
863 CommandInfoType& info )
865 bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretCommand(...)"<<std::endl);
867 // searches the command keyword
868 CommandDictType::iterator c;
869 c = mCommandDict.find(words[0]);
870 if ( c == mCommandDict.end() ) {
871 bbtkError(words[0]<<" : unknown command");
874 // tests the number of args
875 if ( ( words.size()-1 < c->second.argmin ) ||
876 ( words.size()-1 > c->second.argmax ) )
878 HelpCommand(words[0]);
879 bbtkError(words[0]<<" : wrong number of arguments");
883 bbtkDecTab("Interpreter",9);
885 //=======================================================================
888 //=======================================================================
889 /// Displays help on all the commands
890 void Interpreter::Help(const std::vector<std::string>& words)
892 unsigned int nbarg = words.size()-1;
900 if (words[1]=="packages")
907 HelpCommand(words[1]);
909 catch (bbtk::Exception e)
913 HelpPackage(words[1]);
915 catch (bbtk::Exception f)
919 HelpBlackBox(words[1]);
921 catch (bbtk::Exception g)
925 this->mExecuter->ShowRelations(words[1],"0","9999");
927 catch (bbtk::Exception h){
928 bbtkError("\""<<words[1].c_str()
929 <<"\" is not a known command, package, black box type or black box name");
939 if ( words[1]=="packages" )
941 PrintPackages(true,true);
946 HelpPackage(words[1],true);
948 catch (bbtk::Exception f)
954 HelpCommand(words[0]);
955 bbtkError(words[0]<<" : syntax error");
960 bbtkError("Should not reach here !!!");
963 //=======================================================================
965 //===================================================================
966 /// Displays the Configuration
967 void Interpreter::Config( bool verbose ) const
969 bbtkDebugMessageInc("Core",9,"Factory::Config"<<std::endl);
971 ConfigurationFile cf = ConfigurationFile::GetInstance();
973 const std::string config_xml_full_path = cf.Get_config_xml_full_path();
974 const std::string description = cf.Get_description();
975 const std::string url = cf.Get_url();
976 const std::string data_path = cf.Get_data_path();
977 const std::string default_doc_tmp = cf.Get_default_doc_tmp();
978 const std::string file_separator = cf.Get_file_separator();
979 const std::vector<std::string>bbs_paths = cf.Get_bbs_paths();
980 const std::vector<std::string>package_paths = cf.Get_package_paths();
982 bbtkMessage("Help",1, "=============" << std::endl);
983 bbtkMessage("Help",1, "Configuration" << std::endl);
984 bbtkMessage("Help",1, "=============" << std::endl);
985 bbtkMessage("Help",1, "bbtk_config.xml : [" << config_xml_full_path << "]" << std::endl);
986 bbtkMessage("Help",1, "Documentation Url : [" << url << "]" << std::endl);
987 bbtkMessage("Help",1, "Data Path : [" << data_path << "]" << std::endl);
988 bbtkMessage("Help",1, "Default Doc_tmp : [" << default_doc_tmp << "]" << std::endl);
989 bbtkMessage("Help",1, "File Separator : [" << file_separator << "]" << std::endl);
991 std::vector<std::string>::const_iterator i;
993 bbtkMessage("Help",1, "BBS Paths " << std::endl);
994 for (i = bbs_paths.begin(); i!=bbs_paths.end(); ++i )
996 bbtkMessage("Help",1,"--- ["<<*i<<"]"<<std::endl);
999 bbtkMessage("Help",1, "PACKAGE Paths : " << std::endl);
1000 for (i = package_paths.begin(); i!=package_paths.end(); ++i )
1002 bbtkMessage("Help",1,"--- ["<<*i<<"]"<<std::endl);
1005 bbtkDebugDecTab("Core",9);
1008 //=======================================================================
1009 /// Displays help on all the commands
1010 void Interpreter::HelpCommands()
1012 std::cout << "Available commands :" << std::endl;
1013 CommandDictType::iterator i;
1014 for ( i = mCommandDict.begin();
1015 i != mCommandDict.end();
1017 std::cout << " " << i->first << std::endl;
1018 // std::cout << " usage : " << i->second.syntax << std::endl;
1019 // std::cout << " " << i->second.help << std::endl;
1023 //=======================================================================
1026 //=======================================================================
1027 /// Displays help on a particular commands
1028 void Interpreter::HelpCommand(const std::string& s)
1030 CommandDictType::iterator c;
1031 c = mCommandDict.find(s);
1032 if ( c == mCommandDict.end() ) {
1033 bbtkError(s<<" : Unknown command");
1035 // std::cout << " " << s << " : "<< std::endl;
1036 // CommandParamDictType::iterator i;
1037 // for ( i = c->second.begin();
1038 // i != c->second.end();
1040 std::cout << " usage : " << c->second.syntax << std::endl;
1041 std::cout << " " << c->second.help << std::endl;
1044 //=======================================================================
1047 //=======================================================================
1048 /// Fills the vector commands with the commands which
1049 /// have the first n chars of buf for prefix
1050 /// TODO : skip initial spaces in buf and also return the position of first
1051 /// non blank char in buf
1052 void Interpreter::FindCommandsWithPrefix( char* buf,
1054 std::vector<std::string>& commands )
1056 CommandDictType::const_iterator i;
1057 for (i=mCommandDict.begin(); i!=mCommandDict.end(); ++i)
1059 if ((i->first).find(buf,0,n) == 0)
1060 commands.push_back(i->first);
1063 //=======================================================================
1067 //=======================================================================
1068 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1070 inline void PrintChar(char c) { write(STDOUT_FILENO,&c,1); }
1071 inline void BackSpace() { write(STDOUT_FILENO,"\b \b",3); }
1073 // LG : KEYBOARD CODES AS SCANNED ON MY TTY : UNIVERSAL ?
1074 // IF NOT THE USER SHOULD BE ABLE TO CONFIGURE IT
1075 // E.G. STORE THIS IN bbtk_config.xml
1076 #define BBTK_UP_ARROW_KBCODE 0x00415B1B
1077 #define BBTK_DOWN_ARROW_KBCODE 0x00425B1B
1078 #define BBTK_RIGHT_ARROW_KBCODE 0x00435B1B
1079 #define BBTK_LEFT_ARROW_KBCODE 0x00445B1B
1080 #define BBTK_BACKSPACE_KBCODE 0x00000008
1081 #define BBTK_DEL_KBCODE 0x0000007F
1082 #define BBTK_SPACE_KBCODE 0x00000020
1084 //=======================================================================
1085 void Interpreter::GetLineFromPrompt(std::string& s)
1090 int MAX_LINE_SIZE = 160;
1091 int MAX_HISTORY_SIZE = 100;
1093 char* newline = new char[MAX_LINE_SIZE];
1094 memset(newline,0,MAX_LINE_SIZE);
1095 char* histline = new char[MAX_LINE_SIZE];
1096 memset(histline,0,MAX_LINE_SIZE);
1098 char* line = newline;
1099 int hist = mHistory.size();
1106 read ( STDIN_FILENO, &c, 4) ;
1108 bbtkDebugMessage("Debug",9,"[0x"<<std::hex<<c<<"]\n");
1110 // Printable character
1111 if ( (ind<MAX_LINE_SIZE-1) &&
1112 ( c >= BBTK_SPACE_KBCODE ) &&
1113 ( c < BBTK_DEL_KBCODE ))
1121 // delete the unused line
1127 // empty lines are not stored in from history
1130 // if history too long : delete oldest command
1131 if (mHistory.size()>MAX_HISTORY_SIZE)
1133 delete mHistory.front();
1134 mHistory.pop_front();
1136 mHistory.push_back(line);
1142 else if ( (ind>0) &&
1143 ((c == BBTK_BACKSPACE_KBCODE) ||
1144 (c == BBTK_DEL_KBCODE)) )
1152 // TODO : Command completion
1153 std::vector<std::string> commands;
1154 FindCommandsWithPrefix( line,ind,commands);
1155 if (commands.size()==1)
1157 std::string com = *commands.begin();
1158 for (; ind<com.size(); ++ind)
1160 PrintChar(com[ind]);
1166 else if (commands.size()>1)
1168 std::vector<std::string>::iterator i;
1170 for (i=commands.begin();i!=commands.end();++i)
1172 write(STDOUT_FILENO,(*i).c_str(),strlen((*i).c_str()));
1175 write(STDOUT_FILENO,"\n> ",3);
1176 //for (int j=0;j<ind;++j)
1178 write(STDOUT_FILENO,line,ind);
1182 // Arrow up : back in history
1183 else if (c==BBTK_UP_ARROW_KBCODE)
1187 // erase current line
1188 while (ind--) BackSpace();
1192 strcpy(histline,mHistory[hist]);
1196 write(STDOUT_FILENO,line,ind);
1199 // Arrow down : down in history
1200 else if (c==BBTK_DOWN_ARROW_KBCODE)
1202 if (hist<mHistory.size()-1)
1204 // erase current line
1205 while (ind--) BackSpace();
1209 strcpy(histline,mHistory[hist]);
1213 write(STDOUT_FILENO,line,ind);
1215 // end of history : switch back to newline
1216 else if (hist==mHistory.size()-1)
1218 // erase current line
1219 while (ind--) BackSpace();
1226 write(STDOUT_FILENO,line,ind);
1230 else if (line[ind]!=0 && c==BBTK_RIGHT_ARROW_KBCODE)
1232 PrintChar(line[ind]);
1237 else if (ind>0 && c==BBTK_LEFT_ARROW_KBCODE)
1245 write(STDOUT_FILENO,"\n\r",2);
1253 //=======================================================================
1254 void Interpreter::GetLineFromPrompt(std::string& s)
1280 //=======================================================================
1286 //=======================================================================
1287 void Interpreter::CommandLineInterpreter()
1289 bbtkDebugMessageInc("Interpreter",9,
1290 "Interpreter::CommandLineInterpreter()"<<std::endl);
1292 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1293 // Initialise the tty in non canonical mode with no echo
1294 // oter remembers the previous settings to restore them after
1295 struct termios ter,oter;
1298 ter.c_lflag &= ~ECHO;
1299 ter.c_lflag &= ~ICANON;
1302 tcsetattr(0,TCSANOW,&ter);
1305 mCommandLine = true;
1307 bool insideComment = false; // for multiline comment
1313 GetLineFromPrompt(line);
1314 InterpretLine(line, insideComment);
1316 catch (QuitException e)
1320 catch (bbtk::Exception e)
1324 catch (std::exception& e)
1326 std::cerr << "* ERROR : "<<e.what()<<" (not in bbtk)"<<std::endl;
1330 std::cerr << "* UNDEFINED ERROR (not a bbtk nor a std exception)"<<std::endl;
1335 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1336 tcsetattr(0,TCSANOW,&oter);
1339 std::cout << "Good bye !" << std::endl;
1341 bbtkDebugDecTab("Interpreter",9);
1344 //=======================================================================
1345 void Interpreter::Graph(const std::vector<std::string>& words)
1348 bool system_display = true;
1350 #ifdef _USE_WXWIDGETS_
1351 if ( WxConsole::GetInstance() != 0 ) system_display = false;
1354 if (words.size()==1)
1356 page = mExecuter->ShowGraph(".","0","0","","","",system_display);
1358 else if (words.size()==2)
1360 page = mExecuter->ShowGraph(words[1],"0","0","","","",system_display);
1362 else if (words.size()==3)
1364 page = mExecuter->ShowGraph(words[1],words[2],"0","","","",system_display);
1366 else if (words.size()==4)
1368 page = mExecuter->ShowGraph(words[1],words[2],words[3],"","","",system_display);
1370 else if (words.size()==5)
1372 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],"","",system_display);
1374 else if (words.size()==6)
1376 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],"",system_display);
1378 else if (words.size()==7)
1380 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],words[6],system_display);
1383 #ifdef _USE_WXWIDGETS_
1384 if ( WxConsole::GetInstance() != 0 )
1385 WxConsole::GetInstance()->ShowHtmlPage(page);
1388 //=======================================================================