1 /*=========================================================================
4 Module: $RCSfile: bbtkInterpreter.cxx,v $ $
6 Date: $Date: 2008/01/28 09:12:49 $
7 Version: $Revision: 1.4 $
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 // Note : in the following :
704 // name : the user supplied name
705 // - abreviated name e.g. scr scr.bbs
706 // - relative full name e.g. ./scr.bbs ../../scr.bbs
707 // - absolute full name e.g. /home/usrname/proj/dir/scr.bbs
708 // same for Windows, with c:, d: ...
710 bbtkDebugMessageInc("Interpreter",9,"Interpreter::SwitchToFile( \""
711 <<name<<"\")"<<std::endl);
713 std::vector<std::string> script_paths;
714 std::string libname; // full path library name
715 std::string pkgname; // e.g. <scriptname>.bbs
717 pkgname = Utilities::ExtractScriptName(name);
718 std::cout << "pkgname [" << pkgname << "] name [" << name << "]" << std::endl;
719 if (use_configuration_file)
722 std::cout << "look for : [" << name << "] (use_configuration_file == TRUE)" << std::endl;
723 script_paths = ConfigurationFile::GetInstance().Get_bbs_paths();
726 bool fullnameGiven = false;
727 bool foundFile = false;
728 std::string::size_type slash_position = name.find_last_of("/\\");
730 if (slash_position != std::string::npos)
731 { // ------------------------------------- check user supplied location
732 fullnameGiven = true;
733 libname = Utilities::ExpandLibName(name, verbose);
735 if ( Utilities::FileExists(libname))
741 else // ------------------------------------- iterate on the paths
744 std::vector<std::string>::iterator i;
745 for (i=script_paths.begin();i!=script_paths.end();++i)
749 // we *really* want '.' to be the current working directory
751 char buf[2048]; // for getcwd
752 char * currentDir = getcwd(buf, 2048);
753 std::string cwd(currentDir);
757 libname = Utilities::MakePkgnameFromPath(path, pkgname);
759 // Check if library exists
760 if ( ! Utilities::FileExists(libname) )
762 // The following is *NOT* a debug time message :
763 // It's a user intended message.
764 // Please don't remove it.
766 std::cout <<" [" <<libname <<"] : doesn't exist" <<std::endl;
767 continue; // try next path
770 break; // a script was found; we stop iterating
772 } //------------------ // end for ( package_paths.begin();i!=package_paths.end() )
781 bbtkError("Path ["<<name<<"] doesn't exist");
783 bbtkError("Script ["<<libname<<"] not found");
785 bbtkError("No ["<<pkgname<<".bbs] script found");
789 bbtkMessage("Interpreter",1,pkgname<<" loaded"<<std::endl);
791 s = new std::ifstream;
792 s->open(libname.c_str());
795 bbtkError("Could not open file ["<<libname<<"]");
800 std::cout << " -->[" << libname << "] found" << std::endl;
803 mFileName.push_back(libname);
808 //=======================================================================
811 //=======================================================================
815 void Interpreter::CloseCurrentFile()
817 bbtkDebugMessage("Interpreter",9,"Interpreter::CloseCurrentFile()"
822 bbtkDebugMessage("Interpreter",9," -> no file left open"<<std::endl);
826 mFile.back()->close();
829 bbtkDebugMessage("Interpreter",9,
830 " Closing file '"<<mFileName.back()<<"'"<<std::endl);
832 mFileName.pop_back();
834 bbtkDebugMessage("Interpreter",9," Remains "
836 <<" open"<<std::endl);
837 bbtkDebugMessage("Interpreter",9,"EO Interpreter::CloseCurrentFile()"
840 //=======================================================================
842 //=======================================================================
846 void Interpreter::CloseAllFiles()
848 bbtkDebugMessage("Interpreter",9,"Interpreter::CloseAllFiles()"
851 while (mFile.size() != 0)
853 mFile.back()->close();
856 bbtkDebugMessage("Interpreter",9,
857 " Closing file '"<<mFileName.back()<<"'"<<std::endl);
858 mFileName.pop_back();
861 bbtkDebugMessage("Interpreter",9,"EO Interpreter::CloseAllFiles()"
864 //=======================================================================
868 //=======================================================================
872 void Interpreter::InterpretCommand( const std::vector<std::string>& words,
873 CommandInfoType& info )
875 bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretCommand(...)"<<std::endl);
877 // searches the command keyword
878 CommandDictType::iterator c;
879 c = mCommandDict.find(words[0]);
880 if ( c == mCommandDict.end() ) {
881 bbtkError(words[0]<<" : unknown command");
884 // tests the number of args
885 if ( ( words.size()-1 < c->second.argmin ) ||
886 ( words.size()-1 > c->second.argmax ) )
888 HelpCommand(words[0]);
889 bbtkError(words[0]<<" : wrong number of arguments");
893 bbtkDecTab("Interpreter",9);
895 //=======================================================================
898 //=======================================================================
899 /// Displays help on all the commands
900 void Interpreter::Help(const std::vector<std::string>& words)
902 unsigned int nbarg = words.size()-1;
910 if (words[1]=="packages")
917 HelpCommand(words[1]);
919 catch (bbtk::Exception e)
923 HelpPackage(words[1]);
925 catch (bbtk::Exception f)
929 HelpBlackBox(words[1]);
931 catch (bbtk::Exception g)
935 this->mExecuter->ShowRelations(words[1],"0","9999");
937 catch (bbtk::Exception h){
938 bbtkError("\""<<words[1].c_str()
939 <<"\" is not a known command, package, black box type or black box name");
949 if ( words[1]=="packages" )
951 PrintPackages(true,true);
956 HelpPackage(words[1],true);
958 catch (bbtk::Exception f)
964 HelpCommand(words[0]);
965 bbtkError(words[0]<<" : syntax error");
970 bbtkError("Should not reach here !!!");
973 //=======================================================================
975 //===================================================================
976 /// Displays the Configuration
977 void Interpreter::Config( bool verbose ) const
979 bbtkDebugMessageInc("Core",9,"Factory::Config"<<std::endl);
981 ConfigurationFile cf = ConfigurationFile::GetInstance();
983 const std::string config_xml_full_path = cf.Get_config_xml_full_path();
984 const std::string description = cf.Get_description();
985 const std::string url = cf.Get_url();
986 const std::string data_path = cf.Get_data_path();
987 const std::string default_doc_tmp = cf.Get_default_doc_tmp();
988 const std::string file_separator = cf.Get_file_separator();
989 const std::vector<std::string>bbs_paths = cf.Get_bbs_paths();
990 const std::vector<std::string>package_paths = cf.Get_package_paths();
992 bbtkMessage("Help",1, "=============" << std::endl);
993 bbtkMessage("Help",1, "Configuration" << std::endl);
994 bbtkMessage("Help",1, "=============" << std::endl);
995 bbtkMessage("Help",1, "bbtk_config.xml : [" << config_xml_full_path << "]" << std::endl);
996 bbtkMessage("Help",1, "Documentation Url : [" << url << "]" << std::endl);
997 bbtkMessage("Help",1, "Data Path : [" << data_path << "]" << std::endl);
998 bbtkMessage("Help",1, "Default Doc_tmp : [" << default_doc_tmp << "]" << std::endl);
999 bbtkMessage("Help",1, "File Separator : [" << file_separator << "]" << std::endl);
1001 std::vector<std::string>::const_iterator i;
1003 bbtkMessage("Help",1, "BBS Paths " << std::endl);
1004 for (i = bbs_paths.begin(); i!=bbs_paths.end(); ++i )
1006 bbtkMessage("Help",1,"--- ["<<*i<<"]"<<std::endl);
1009 bbtkMessage("Help",1, "PACKAGE Paths : " << std::endl);
1010 for (i = package_paths.begin(); i!=package_paths.end(); ++i )
1012 bbtkMessage("Help",1,"--- ["<<*i<<"]"<<std::endl);
1015 bbtkDebugDecTab("Core",9);
1018 //=======================================================================
1019 /// Displays help on all the commands
1020 void Interpreter::HelpCommands()
1022 std::cout << "Available commands :" << std::endl;
1023 CommandDictType::iterator i;
1024 for ( i = mCommandDict.begin();
1025 i != mCommandDict.end();
1027 std::cout << " " << i->first << std::endl;
1028 // std::cout << " usage : " << i->second.syntax << std::endl;
1029 // std::cout << " " << i->second.help << std::endl;
1033 //=======================================================================
1036 //=======================================================================
1037 /// Displays help on a particular commands
1038 void Interpreter::HelpCommand(const std::string& s)
1040 CommandDictType::iterator c;
1041 c = mCommandDict.find(s);
1042 if ( c == mCommandDict.end() ) {
1043 bbtkError(s<<" : Unknown command");
1045 // std::cout << " " << s << " : "<< std::endl;
1046 // CommandParamDictType::iterator i;
1047 // for ( i = c->second.begin();
1048 // i != c->second.end();
1050 std::cout << " usage : " << c->second.syntax << std::endl;
1051 std::cout << " " << c->second.help << std::endl;
1054 //=======================================================================
1057 //=======================================================================
1058 /// Fills the vector commands with the commands which
1059 /// have the first n chars of buf for prefix
1060 /// TODO : skip initial spaces in buf and also return the position of first
1061 /// non blank char in buf
1062 void Interpreter::FindCommandsWithPrefix( char* buf,
1064 std::vector<std::string>& commands )
1066 CommandDictType::const_iterator i;
1067 for (i=mCommandDict.begin(); i!=mCommandDict.end(); ++i)
1069 if ((i->first).find(buf,0,n) == 0)
1070 commands.push_back(i->first);
1073 //=======================================================================
1077 //=======================================================================
1078 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1080 inline void PrintChar(char c) { write(STDOUT_FILENO,&c,1); }
1081 inline void BackSpace() { write(STDOUT_FILENO,"\b \b",3); }
1083 // LG : KEYBOARD CODES AS SCANNED ON MY TTY : UNIVERSAL ?
1084 // IF NOT THE USER SHOULD BE ABLE TO CONFIGURE IT
1085 // E.G. STORE THIS IN bbtk_config.xml
1086 #define BBTK_UP_ARROW_KBCODE 0x00415B1B
1087 #define BBTK_DOWN_ARROW_KBCODE 0x00425B1B
1088 #define BBTK_RIGHT_ARROW_KBCODE 0x00435B1B
1089 #define BBTK_LEFT_ARROW_KBCODE 0x00445B1B
1090 #define BBTK_BACKSPACE_KBCODE 0x00000008
1091 #define BBTK_DEL_KBCODE 0x0000007F
1092 #define BBTK_SPACE_KBCODE 0x00000020
1094 //=======================================================================
1095 void Interpreter::GetLineFromPrompt(std::string& s)
1100 int MAX_LINE_SIZE = 160;
1101 int MAX_HISTORY_SIZE = 100;
1103 char* newline = new char[MAX_LINE_SIZE];
1104 memset(newline,0,MAX_LINE_SIZE);
1105 char* histline = new char[MAX_LINE_SIZE];
1106 memset(histline,0,MAX_LINE_SIZE);
1108 char* line = newline;
1109 int hist = mHistory.size();
1116 read ( STDIN_FILENO, &c, 4) ;
1118 bbtkDebugMessage("Debug",9,"[0x"<<std::hex<<c<<"]\n");
1120 // Printable character
1121 if ( (ind<MAX_LINE_SIZE-1) &&
1122 ( c >= BBTK_SPACE_KBCODE ) &&
1123 ( c < BBTK_DEL_KBCODE ))
1131 // delete the unused line
1137 // empty lines are not stored in from history
1140 // if history too long : delete oldest command
1141 if (mHistory.size()>MAX_HISTORY_SIZE)
1143 delete mHistory.front();
1144 mHistory.pop_front();
1146 mHistory.push_back(line);
1152 else if ( (ind>0) &&
1153 ((c == BBTK_BACKSPACE_KBCODE) ||
1154 (c == BBTK_DEL_KBCODE)) )
1162 // TODO : Command completion
1163 std::vector<std::string> commands;
1164 FindCommandsWithPrefix( line,ind,commands);
1165 if (commands.size()==1)
1167 std::string com = *commands.begin();
1168 for (; ind<com.size(); ++ind)
1170 PrintChar(com[ind]);
1176 else if (commands.size()>1)
1178 std::vector<std::string>::iterator i;
1180 for (i=commands.begin();i!=commands.end();++i)
1182 write(STDOUT_FILENO,(*i).c_str(),strlen((*i).c_str()));
1185 write(STDOUT_FILENO,"\n> ",3);
1186 //for (int j=0;j<ind;++j)
1188 write(STDOUT_FILENO,line,ind);
1192 // Arrow up : back in history
1193 else if (c==BBTK_UP_ARROW_KBCODE)
1197 // erase current line
1198 while (ind--) BackSpace();
1202 strcpy(histline,mHistory[hist]);
1206 write(STDOUT_FILENO,line,ind);
1209 // Arrow down : down in history
1210 else if (c==BBTK_DOWN_ARROW_KBCODE)
1212 if (hist<mHistory.size()-1)
1214 // erase current line
1215 while (ind--) BackSpace();
1219 strcpy(histline,mHistory[hist]);
1223 write(STDOUT_FILENO,line,ind);
1225 // end of history : switch back to newline
1226 else if (hist==mHistory.size()-1)
1228 // erase current line
1229 while (ind--) BackSpace();
1236 write(STDOUT_FILENO,line,ind);
1240 else if (line[ind]!=0 && c==BBTK_RIGHT_ARROW_KBCODE)
1242 PrintChar(line[ind]);
1247 else if (ind>0 && c==BBTK_LEFT_ARROW_KBCODE)
1255 write(STDOUT_FILENO,"\n\r",2);
1263 //=======================================================================
1264 void Interpreter::GetLineFromPrompt(std::string& s)
1290 //=======================================================================
1296 //=======================================================================
1297 void Interpreter::CommandLineInterpreter()
1299 bbtkDebugMessageInc("Interpreter",9,
1300 "Interpreter::CommandLineInterpreter()"<<std::endl);
1302 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1303 // Initialise the tty in non canonical mode with no echo
1304 // oter remembers the previous settings to restore them after
1305 struct termios ter,oter;
1308 ter.c_lflag &= ~ECHO;
1309 ter.c_lflag &= ~ICANON;
1312 tcsetattr(0,TCSANOW,&ter);
1315 mCommandLine = true;
1317 bool insideComment = false; // for multiline comment
1323 GetLineFromPrompt(line);
1324 InterpretLine(line, insideComment);
1326 catch (QuitException e)
1330 catch (bbtk::Exception e)
1334 catch (std::exception& e)
1336 std::cerr << "* ERROR :: "<<e.what()<<" (not in bbtk)"<<std::endl;
1340 std::cerr << "* UNDEFINED ERROR (not a bbtk nor a std exception)"<<std::endl;
1345 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1346 tcsetattr(0,TCSANOW,&oter);
1349 std::cout << "Good bye !" << std::endl;
1351 bbtkDebugDecTab("Interpreter",9);
1354 //=======================================================================
1355 void Interpreter::Graph(const std::vector<std::string>& words)
1358 bool system_display = true;
1360 #ifdef _USE_WXWIDGETS_
1361 if ( WxConsole::GetInstance() != 0 ) system_display = false;
1364 if (words.size()==1)
1366 page = mExecuter->ShowGraph(".","0","0","","","",system_display);
1368 else if (words.size()==2)
1370 page = mExecuter->ShowGraph(words[1],"0","0","","","",system_display);
1372 else if (words.size()==3)
1374 page = mExecuter->ShowGraph(words[1],words[2],"0","","","",system_display);
1376 else if (words.size()==4)
1378 page = mExecuter->ShowGraph(words[1],words[2],words[3],"","","",system_display);
1380 else if (words.size()==5)
1382 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],"","",system_display);
1384 else if (words.size()==6)
1386 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],"",system_display);
1388 else if (words.size()==7)
1390 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],words[6],system_display);
1393 #ifdef _USE_WXWIDGETS_
1394 if ( WxConsole::GetInstance() != 0 )
1395 WxConsole::GetInstance()->ShowHtmlPage(page);
1398 //=======================================================================