1 /*=========================================================================
4 Module: $RCSfile: bbtkInterpreter.cxx,v $ $
6 Date: $Date: 2008/01/28 10:50:54 $
7 Version: $Revision: 1.5 $
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 = "define";
106 info.syntax = "define <type> [<package>]";
107 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.";
108 mCommandDict[info.keyword] = info;
110 info.keyword = "endefine";
113 info.code = cEndDefine;
114 info.syntax = "endefine";
115 info.help = "Ends the definition of a new type of complex black box";
116 mCommandDict[info.keyword] = info;
118 info.keyword = "input";
122 info.syntax = "input <name> <box.input> <help>";
123 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";
124 mCommandDict[info.keyword] = info;
126 info.keyword = "output";
130 info.syntax = "output <name> <box.output> <help>";
131 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";
132 mCommandDict[info.keyword] = info;
134 info.keyword = "set";
138 info.syntax = "set <box.input> <value>";
139 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";
140 mCommandDict[info.keyword] = info;
142 info.keyword = "config"; // JPR
146 info.syntax = "config [<verbose>|<v>]";
147 info.help = "Prints the value of all configuration parameters";
148 mCommandDict[info.keyword] = info;
150 info.keyword = "reset"; //EED
154 info.syntax = "reset";
155 info.help = "Deletes all boxes and unloads all packages (bbi is reset to its start state)";
156 mCommandDict[info.keyword] = info;
158 info.keyword = "author";
162 info.syntax = "author <string>";
163 info.help = "Adds the string <string> to the author information of the black box being defined";
164 mCommandDict[info.keyword] = info;
166 info.keyword = "description";
169 info.code = cDescription;
170 info.syntax = "description <string>";
171 info.help = "Adds the string <string> to the descriptive information of the black box being defined";
172 mCommandDict[info.keyword] = info;
174 info.keyword = "help";
178 info.syntax = "help";
179 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>";
180 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.";
181 mCommandDict[info.keyword] = info;
183 info.keyword = "message";
186 info.code = cMessage;
187 info.syntax = "message <category> <level>";
188 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.";
189 mCommandDict[info.keyword] = info;
191 info.keyword = "include";
194 info.code = cInclude;
195 info.syntax = "include <filename>";
196 info.help = "Includes the file <filename>";
197 mCommandDict[info.keyword] = info;
199 info.keyword = "quit";
203 info.syntax = "quit";
204 info.help = "Quits the program (during script execution it stops the complete execution)";
205 mCommandDict[info.keyword] = info;
207 info.keyword = "load";
211 info.syntax = "load <packagename>";
212 info.help = "Loads the black box package <packagename>";
213 mCommandDict[info.keyword] = info;
215 info.keyword = "unload";
219 info.syntax = "unload <packagename>";
220 info.help = "Unloads the black box package <packagename>";
221 mCommandDict[info.keyword] = info;
223 info.keyword = "graph";
227 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 ]]]]]]";
228 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')";
229 mCommandDict[info.keyword] = info;
232 info.keyword = "workspace";
235 info.code = cWorkspace;
236 info.syntax = "workspace < ( freeze | unfreeze ) | ( rename <newname> ) >";
237 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.";
238 mCommandDict[info.keyword] = info;
241 bbtkDebugDecTab("Interpreter",9);
244 //=======================================================================
248 //=======================================================================
252 Interpreter::~Interpreter()
254 bbtkDebugMessageInc("Interpreter",9,"Interpreter::~Interpreter()" <<std::endl);
258 // std::cout <<"EO Interpreter::~Interpreter()"<<std::endl;
259 bbtkDebugDecTab("Interpreter",9);
261 //=======================================================================
264 //=======================================================================
268 void Interpreter::InterpretFile( const std::string& filename, bool use_configuration_file, bool verbose)
270 bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretFile(\""<<filename<<"\")"<<std::endl);
272 bool exm = mCommandLine;
273 mCommandLine = false;
277 SwitchToFile(filename, use_configuration_file, verbose);
278 bool insideComment = false; // for multiline comment
279 while (mFile.size()>0)
281 while ((mFile.size()>0) &&
282 (!mFile.back()->eof()))
286 mFile.back()->getline(buf,500);
288 std::string str(buf);
289 int size=str.length();
290 if ( str[ size-1 ]==13 )
295 InterpretLine(str, insideComment);
297 //if (mFile.size()>0)
301 catch (QuitException e)
304 catch (bbtk::Exception e)
306 std::cerr << "* ERROR : "<<e.GetMessage()<<std::endl;
307 if (mFileName.size()) {
308 std::cerr << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
309 std::cerr << "* LINE : "<<mLine.back()<<std::endl;
312 catch (std::exception& e)
314 std::cerr << "* ERROR : "<<e.what()<<" (not in bbtk)"<<std::endl;
315 if (mFileName.size()) {
316 std::cerr << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
317 std::cerr << "* LINE : "<<mLine.back()<<std::endl;
322 std::cout << "* UNDEFINED ERROR (not a bbtk nor a std exception)"<<std::endl;
323 if (mFileName.size()) {
324 std::cout << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
325 std::cout << "* LINE : "<<mLine.back()<<std::endl;
330 bbtkDebugMessage("Interpreter",9,"EO Interpreter::InterpretFile(\""<<filename<<"\")"<<std::endl);
331 bbtkDecTab("Interpreter",9);
335 //=======================================================================
339 //=======================================================================
343 void Interpreter::InterpretLine( const std::string& line, bool &insideComment )
346 bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretLine(\""<<line<<"\")"<<std::endl);
347 bbtkMessage("Echo",2,"\""<<line<<"\""<<std::endl);
349 std::vector<std::string> words;
350 SplitLine(line,words);
355 bbtkDebugDecTab("Interpreter",9);
359 // Single line comment : # or //
360 if ( words[0][0]=='#' || (words[0][0]=='/' && words[0][1]=='/') )
362 bbtkDebugDecTab("Interpreter",9);
363 bbtkMessage("Interpreter",9,"Comment"<<std::endl);
367 // Multi line comment ( /* ... */ ) -delimiters on different lines !-
369 if (words[0][0]=='/' && words[0][1]=='*')
371 bbtkDebugDecTab("Interpreter",9);
372 bbtkMessage("Interpreter",9,"In multiline comment"<<std::endl);
373 insideComment = true;
377 if (words[0][0]=='*' && words[0][1]=='/')
379 bbtkDebugDecTab("Interpreter",9);
380 bbtkMessage("Interpreter",9,"Out multiline comment"<<std::endl);
381 if ( !insideComment ) {
382 bbtkDebugDecTab("Interpreter",9);
383 bbtkMessage("Interpreter",9,"Comment mismatch : '*/' with no matching '/*'"<<std::endl);
385 insideComment = false;
391 bbtkDebugDecTab("Interpreter",9);
392 bbtkMessage("Interpreter",9,"Multiline Comment"<<std::endl);
397 CommandInfoType command;
398 InterpretCommand(words,command);
400 bbtkDebugMessage("Interpreter",9,
401 "Command='"<<command.keyword
402 <<"' code="<<command.code<<std::endl);
404 std::string left,right,left2,right2;
405 std::string filename;
406 switch (command.code)
409 mExecuter->Create(words[1],words[2]);
414 // mExecuter->Remove(words[1]);
418 Utilities::SplitAroundFirstDot(words[1],left,right);
419 Utilities::SplitAroundFirstDot(words[2],left2,right2);
420 mExecuter->Connect(left,right,left2,right2);
424 if (mFileName.size()>0)
426 filename = Utilities::get_file_name(mFileName.back());
430 mExecuter->Define(words[1],"user",filename);
434 mExecuter->Define(words[1],words[2],filename);
439 mExecuter->EndDefine();
443 Print(words[1]); /// \todo use mExecuter
447 if (words[1]=="freeze")
448 mExecuter->SetNoExecMode(true);
449 else if (words[1]=="unfreeze")
450 mExecuter->SetNoExecMode(false);
452 mExecuter->Update(words[1]);
456 Utilities::SplitAroundFirstDot(words[2],left,right);
457 mExecuter->DefineInput(words[1],left,right,words[3]);
461 Utilities::SplitAroundFirstDot(words[2],left,right);
462 mExecuter->DefineOutput(words[1],left,right,words[3]);
466 Utilities::SplitAroundFirstDot(words[1],left,right);
467 mExecuter->Set(left,right,words[2]);
471 mExecuter->Author(words[1]);
475 mExecuter->Description(words[1]);
485 bbtk::MessageManager::PrintInfo();
489 sscanf(words[2].c_str(),"%d",&level);
490 bbtk::MessageManager::SetMessageLevel(words[1],level);
499 if (words.size()>1) // any param for config means verbose = true
507 this->mExecuter->Reset();
513 InterpretFile(words[1], true, verbose); // true : better pass use_config_file
517 SwitchToFile(words[1], true, verbose); // true : better pass use_config_file
522 LoadPackage(words[1], true, verbose); // true : better pass use_config_file
526 UnLoadPackage(words[1]);
530 throw QuitException();
534 if (words.size() == 2)
536 if (words[1]=="freeze") mExecuter->SetNoExecMode(true);
537 else if (words[1]=="unfreeze") mExecuter->SetNoExecMode(false);
541 mExecuter->SetWorkspaceName(words[2]);
546 bbtkInternalError("should not reach here !!!");
549 bbtkDecTab("Interpreter",9);
551 //=======================================================================
555 //=======================================================================
556 void SplitString ( const std::string& str, const std::string& delimiters,
557 std::vector<std::string>& tokens)
559 // Skip delimiters at beginning.
560 std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
561 // Find first delimiter.
562 std::string::size_type pos = str.find_first_of(delimiters, lastPos);
564 while (std::string::npos != pos || std::string::npos != lastPos)
566 // Found a token, add it to the vector.
567 tokens.push_back(str.substr(lastPos, pos - lastPos));
568 // Skip delimiters. Note the "not_of"
569 lastPos = str.find_first_not_of(delimiters, pos);
570 // Find next delimiter
571 pos = str.find_first_of(delimiters, lastPos);
575 //=======================================================================
579 //=======================================================================
583 void Interpreter::SplitLine ( const std::string& str, std::vector<std::string>& tokens)
585 bbtkDebugMessageInc("Interpreter",9,"Interpreter::SplitLine(\""<<str<<"\")"<<std::endl);
587 std::string delimiters = "\"";
588 std::vector<std::string> quote;
589 SplitString(str,delimiters,quote);
592 std::vector<std::string>::iterator i;
593 for (i=quote.begin(); i!=quote.end(); )
595 SplitString(*i,delimiters,tokens);
599 // bbtkDebugMessage("Interpreter",0,"\""<<*i<<"\""<<std::endl);
600 tokens.push_back(*i);
605 for (i=tokens.begin(); i!=tokens.end(); ++i)
607 bbtkDebugMessage("Interpreter",9,"["<<*i<<"] ");
609 bbtkDebugMessageCont("Interpreter",9,std::endl);
611 bbtkDebugDecTab("Interpreter",9);
613 //=======================================================================
616 //=======================================================================
617 // Replaces substrings "\\n" by a real carriage return "\n"
618 void SubsBackslashN ( std::string& s )
620 // std::cout << "BEFORE=["<<s<<"]"<<std::endl;
621 std::string ss("\\n");
622 std::string::size_type pos = 0;
625 while ( pos != std::string::npos )
627 // std::cout << "*** find one "<<std::endl;
628 s.replace(pos,2,cr,1);
629 pos = s.find(ss, pos-1);
631 // std::cout << "AFTER=["<<s<<"]"<<std::endl;
633 //=======================================================================
636 //=======================================================================
640 void Interpreter::Print( const std::string& str)
642 if (mExecuter->GetNoExecMode()) return;
644 bbtkDebugMessageInc("Interpreter",9,"Interpreter::SplitLine(\""<<str<<"\")"<<std::endl);
646 std::vector<std::string> chains;
647 std::string delimiters("$");
649 // Skip delimiters at beginning.
650 std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
652 if (lastPos>0) is_text = false;
654 // Find first delimiter.
655 std::string::size_type pos = str.find_first_of(delimiters, lastPos);
657 while (std::string::npos != pos || std::string::npos != lastPos)
661 // Found a text token, add it to the vector.
662 chains.push_back(str.substr(lastPos, pos - lastPos));
663 // std::cout << "text='"<<chains.back()<<"'"<<std::endl;
667 // is an output (between $$) : decode
668 std::string tok,box,output;
669 tok = str.substr(lastPos, pos - lastPos);
670 Utilities::SplitAroundFirstDot(tok,box,output);
671 chains.push_back( mExecuter->Get(box,output) );
672 // std::cout << "outp='"<<chains.back()<<"'"<<std::endl;
674 // Skip delimiters. Note the "not_of"
675 lastPos = str.find_first_not_of(delimiters, pos);
676 // Find next delimiter
677 pos = str.find_first_of(delimiters, lastPos);
681 // std::cout << "nb="<<chains.size()<<std::endl;
682 std::vector<std::string>::iterator i;
683 for (i= chains.begin(); i!=chains.end(); ++i)
685 // bbtkMessage("Echo",1,*i);
689 std::cout << std::endl;
690 bbtkDebugDecTab("Interpreter",9);
693 //=======================================================================
698 // ===================================================================================
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 if (use_configuration_file)
721 std::cout << "look for : [" << name << "] (use_configuration_file == TRUE)" << std::endl;
722 script_paths = ConfigurationFile::GetInstance().Get_bbs_paths();
725 bool fullnameGiven = false;
726 bool foundFile = false;
727 std::string::size_type slash_position = name.find_last_of("/\\");
729 if (slash_position != std::string::npos)
730 { // ------------------------------------- check user supplied location
731 fullnameGiven = true;
732 libname = Utilities::ExpandLibName(name, verbose);
734 // allow user to always forget ".bbs"
735 int l = libname.size();
738 if (libname.substr(l-4, 4) != ".bbs")
740 libname = libname + ".bbs";
745 libname = libname + ".bbs";
749 if ( Utilities::FileExists(libname))
755 else // ------------------------------------- iterate on the paths
758 std::vector<std::string>::iterator i;
759 for (i=script_paths.begin();i!=script_paths.end();++i)
763 // we *really* want '.' to be the current working directory
765 char buf[2048]; // for getcwd
766 char * currentDir = getcwd(buf, 2048);
767 std::string cwd(currentDir);
771 libname = Utilities::MakePkgnameFromPath(path, pkgname);
772 // Check if library exists
773 if ( ! Utilities::FileExists(libname) )
775 // The following is *NOT* a debug time message :
776 // It's a user intended message.
777 // Please don't remove it.
779 std::cout <<" [" <<libname <<"] : doesn't exist" <<std::endl;
780 continue; // try next path
783 break; // a script was found; we stop iterating
785 } //------------------ // end for ( package_paths.begin();i!=package_paths.end() )
794 bbtkError("Path ["<<name<<"] doesn't exist");
796 bbtkError("Script ["<<libname<<"] not found");
798 bbtkError("No ["<<pkgname<<".bbs] script found");
802 bbtkMessage("Interpreter",1,pkgname<<" loaded"<<std::endl);
804 s = new std::ifstream;
805 s->open(libname.c_str());
808 bbtkError("Could not open file ["<<libname<<"]");
813 std::cout << " -->[" << libname << "] found" << std::endl;
816 mFileName.push_back(libname);
821 //=======================================================================
824 //=======================================================================
828 void Interpreter::CloseCurrentFile()
830 bbtkDebugMessage("Interpreter",9,"Interpreter::CloseCurrentFile()"
835 bbtkDebugMessage("Interpreter",9," -> no file left open"<<std::endl);
839 mFile.back()->close();
842 bbtkDebugMessage("Interpreter",9,
843 " Closing file '"<<mFileName.back()<<"'"<<std::endl);
845 mFileName.pop_back();
847 bbtkDebugMessage("Interpreter",9," Remains "
849 <<" open"<<std::endl);
850 bbtkDebugMessage("Interpreter",9,"EO Interpreter::CloseCurrentFile()"
853 //=======================================================================
855 //=======================================================================
859 void Interpreter::CloseAllFiles()
861 bbtkDebugMessage("Interpreter",9,"Interpreter::CloseAllFiles()"
864 while (mFile.size() != 0)
866 mFile.back()->close();
869 bbtkDebugMessage("Interpreter",9,
870 " Closing file '"<<mFileName.back()<<"'"<<std::endl);
871 mFileName.pop_back();
874 bbtkDebugMessage("Interpreter",9,"EO Interpreter::CloseAllFiles()"
877 //=======================================================================
881 //=======================================================================
885 void Interpreter::InterpretCommand( const std::vector<std::string>& words,
886 CommandInfoType& info )
888 bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretCommand(...)"<<std::endl);
890 // searches the command keyword
891 CommandDictType::iterator c;
892 c = mCommandDict.find(words[0]);
893 if ( c == mCommandDict.end() ) {
894 bbtkError(words[0]<<" : unknown command");
897 // tests the number of args
898 if ( ( words.size()-1 < c->second.argmin ) ||
899 ( words.size()-1 > c->second.argmax ) )
901 HelpCommand(words[0]);
902 bbtkError(words[0]<<" : wrong number of arguments");
906 bbtkDecTab("Interpreter",9);
908 //=======================================================================
911 //=======================================================================
912 /// Displays help on all the commands
913 void Interpreter::Help(const std::vector<std::string>& words)
915 unsigned int nbarg = words.size()-1;
923 if (words[1]=="packages")
930 HelpCommand(words[1]);
932 catch (bbtk::Exception e)
936 HelpPackage(words[1]);
938 catch (bbtk::Exception f)
942 HelpBlackBox(words[1]);
944 catch (bbtk::Exception g)
948 this->mExecuter->ShowRelations(words[1],"0","9999");
950 catch (bbtk::Exception h){
951 bbtkError("\""<<words[1].c_str()
952 <<"\" is not a known command, package, black box type or black box name");
962 if ( words[1]=="packages" )
964 PrintPackages(true,true);
969 HelpPackage(words[1],true);
971 catch (bbtk::Exception f)
977 HelpCommand(words[0]);
978 bbtkError(words[0]<<" : syntax error");
983 bbtkError("Should not reach here !!!");
986 //=======================================================================
988 //===================================================================
989 /// Displays the Configuration
990 void Interpreter::Config( bool verbose ) const
992 bbtkDebugMessageInc("Core",9,"Factory::Config"<<std::endl);
994 ConfigurationFile cf = ConfigurationFile::GetInstance();
996 const std::string config_xml_full_path = cf.Get_config_xml_full_path();
997 const std::string description = cf.Get_description();
998 const std::string url = cf.Get_url();
999 const std::string data_path = cf.Get_data_path();
1000 const std::string default_doc_tmp = cf.Get_default_doc_tmp();
1001 const std::string file_separator = cf.Get_file_separator();
1002 const std::vector<std::string>bbs_paths = cf.Get_bbs_paths();
1003 const std::vector<std::string>package_paths = cf.Get_package_paths();
1005 bbtkMessage("Help",1, "=============" << std::endl);
1006 bbtkMessage("Help",1, "Configuration" << std::endl);
1007 bbtkMessage("Help",1, "=============" << std::endl);
1008 bbtkMessage("Help",1, "bbtk_config.xml : [" << config_xml_full_path << "]" << std::endl);
1009 bbtkMessage("Help",1, "Documentation Url : [" << url << "]" << std::endl);
1010 bbtkMessage("Help",1, "Data Path : [" << data_path << "]" << std::endl);
1011 bbtkMessage("Help",1, "Default Doc_tmp : [" << default_doc_tmp << "]" << std::endl);
1012 bbtkMessage("Help",1, "File Separator : [" << file_separator << "]" << std::endl);
1014 std::vector<std::string>::const_iterator i;
1016 bbtkMessage("Help",1, "BBS Paths " << std::endl);
1017 for (i = bbs_paths.begin(); i!=bbs_paths.end(); ++i )
1019 bbtkMessage("Help",1,"--- ["<<*i<<"]"<<std::endl);
1022 bbtkMessage("Help",1, "PACKAGE Paths : " << std::endl);
1023 for (i = package_paths.begin(); i!=package_paths.end(); ++i )
1025 bbtkMessage("Help",1,"--- ["<<*i<<"]"<<std::endl);
1028 bbtkDebugDecTab("Core",9);
1031 //=======================================================================
1032 /// Displays help on all the commands
1033 void Interpreter::HelpCommands()
1035 std::cout << "Available commands :" << std::endl;
1036 CommandDictType::iterator i;
1037 for ( i = mCommandDict.begin();
1038 i != mCommandDict.end();
1040 std::cout << " " << i->first << std::endl;
1041 // std::cout << " usage : " << i->second.syntax << std::endl;
1042 // std::cout << " " << i->second.help << std::endl;
1046 //=======================================================================
1049 //=======================================================================
1050 /// Displays help on a particular commands
1051 void Interpreter::HelpCommand(const std::string& s)
1053 CommandDictType::iterator c;
1054 c = mCommandDict.find(s);
1055 if ( c == mCommandDict.end() ) {
1056 bbtkError(s<<" : Unknown command");
1058 // std::cout << " " << s << " : "<< std::endl;
1059 // CommandParamDictType::iterator i;
1060 // for ( i = c->second.begin();
1061 // i != c->second.end();
1063 std::cout << " usage : " << c->second.syntax << std::endl;
1064 std::cout << " " << c->second.help << std::endl;
1067 //=======================================================================
1070 //=======================================================================
1071 /// Fills the vector commands with the commands which
1072 /// have the first n chars of buf for prefix
1073 /// TODO : skip initial spaces in buf and also return the position of first
1074 /// non blank char in buf
1075 void Interpreter::FindCommandsWithPrefix( char* buf,
1077 std::vector<std::string>& commands )
1079 CommandDictType::const_iterator i;
1080 for (i=mCommandDict.begin(); i!=mCommandDict.end(); ++i)
1082 if ((i->first).find(buf,0,n) == 0)
1083 commands.push_back(i->first);
1086 //=======================================================================
1090 //=======================================================================
1091 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1093 inline void PrintChar(char c) { write(STDOUT_FILENO,&c,1); }
1094 inline void BackSpace() { write(STDOUT_FILENO,"\b \b",3); }
1096 // LG : KEYBOARD CODES AS SCANNED ON MY TTY : UNIVERSAL ?
1097 // IF NOT THE USER SHOULD BE ABLE TO CONFIGURE IT
1098 // E.G. STORE THIS IN bbtk_config.xml
1099 #define BBTK_UP_ARROW_KBCODE 0x00415B1B
1100 #define BBTK_DOWN_ARROW_KBCODE 0x00425B1B
1101 #define BBTK_RIGHT_ARROW_KBCODE 0x00435B1B
1102 #define BBTK_LEFT_ARROW_KBCODE 0x00445B1B
1103 #define BBTK_BACKSPACE_KBCODE 0x00000008
1104 #define BBTK_DEL_KBCODE 0x0000007F
1105 #define BBTK_SPACE_KBCODE 0x00000020
1107 //=======================================================================
1108 void Interpreter::GetLineFromPrompt(std::string& s)
1113 int MAX_LINE_SIZE = 160;
1114 int MAX_HISTORY_SIZE = 100;
1116 char* newline = new char[MAX_LINE_SIZE];
1117 memset(newline,0,MAX_LINE_SIZE);
1118 char* histline = new char[MAX_LINE_SIZE];
1119 memset(histline,0,MAX_LINE_SIZE);
1121 char* line = newline;
1122 int hist = mHistory.size();
1129 read ( STDIN_FILENO, &c, 4) ;
1131 bbtkDebugMessage("Debug",9,"[0x"<<std::hex<<c<<"]\n");
1133 // Printable character
1134 if ( (ind<MAX_LINE_SIZE-1) &&
1135 ( c >= BBTK_SPACE_KBCODE ) &&
1136 ( c < BBTK_DEL_KBCODE ))
1144 // delete the unused line
1150 // empty lines are not stored in from history
1153 // if history too long : delete oldest command
1154 if (mHistory.size()>MAX_HISTORY_SIZE)
1156 delete mHistory.front();
1157 mHistory.pop_front();
1159 mHistory.push_back(line);
1165 else if ( (ind>0) &&
1166 ((c == BBTK_BACKSPACE_KBCODE) ||
1167 (c == BBTK_DEL_KBCODE)) )
1175 // TODO : Command completion
1176 std::vector<std::string> commands;
1177 FindCommandsWithPrefix( line,ind,commands);
1178 if (commands.size()==1)
1180 std::string com = *commands.begin();
1181 for (; ind<com.size(); ++ind)
1183 PrintChar(com[ind]);
1189 else if (commands.size()>1)
1191 std::vector<std::string>::iterator i;
1193 for (i=commands.begin();i!=commands.end();++i)
1195 write(STDOUT_FILENO,(*i).c_str(),strlen((*i).c_str()));
1198 write(STDOUT_FILENO,"\n> ",3);
1199 //for (int j=0;j<ind;++j)
1201 write(STDOUT_FILENO,line,ind);
1205 // Arrow up : back in history
1206 else if (c==BBTK_UP_ARROW_KBCODE)
1210 // erase current line
1211 while (ind--) BackSpace();
1215 strcpy(histline,mHistory[hist]);
1219 write(STDOUT_FILENO,line,ind);
1222 // Arrow down : down in history
1223 else if (c==BBTK_DOWN_ARROW_KBCODE)
1225 if (hist<mHistory.size()-1)
1227 // erase current line
1228 while (ind--) BackSpace();
1232 strcpy(histline,mHistory[hist]);
1236 write(STDOUT_FILENO,line,ind);
1238 // end of history : switch back to newline
1239 else if (hist==mHistory.size()-1)
1241 // erase current line
1242 while (ind--) BackSpace();
1249 write(STDOUT_FILENO,line,ind);
1253 else if (line[ind]!=0 && c==BBTK_RIGHT_ARROW_KBCODE)
1255 PrintChar(line[ind]);
1260 else if (ind>0 && c==BBTK_LEFT_ARROW_KBCODE)
1268 write(STDOUT_FILENO,"\n\r",2);
1276 //=======================================================================
1277 void Interpreter::GetLineFromPrompt(std::string& s)
1303 //=======================================================================
1309 //=======================================================================
1310 void Interpreter::CommandLineInterpreter()
1312 bbtkDebugMessageInc("Interpreter",9,
1313 "Interpreter::CommandLineInterpreter()"<<std::endl);
1315 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1316 // Initialise the tty in non canonical mode with no echo
1317 // oter remembers the previous settings to restore them after
1318 struct termios ter,oter;
1321 ter.c_lflag &= ~ECHO;
1322 ter.c_lflag &= ~ICANON;
1325 tcsetattr(0,TCSANOW,&ter);
1328 mCommandLine = true;
1330 bool insideComment = false; // for multiline comment
1336 GetLineFromPrompt(line);
1337 InterpretLine(line, insideComment);
1339 catch (QuitException e)
1343 catch (bbtk::Exception e)
1347 catch (std::exception& e)
1349 std::cerr << "* ERROR :: "<<e.what()<<" (not in bbtk)"<<std::endl;
1353 std::cerr << "* UNDEFINED ERROR (not a bbtk nor a std exception)"<<std::endl;
1358 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1359 tcsetattr(0,TCSANOW,&oter);
1362 std::cout << "Good bye !" << std::endl;
1364 bbtkDebugDecTab("Interpreter",9);
1367 //=======================================================================
1368 void Interpreter::Graph(const std::vector<std::string>& words)
1371 bool system_display = true;
1373 #ifdef _USE_WXWIDGETS_
1374 if ( WxConsole::GetInstance() != 0 ) system_display = false;
1377 if (words.size()==1)
1379 page = mExecuter->ShowGraph(".","0","0","","","",system_display);
1381 else if (words.size()==2)
1383 page = mExecuter->ShowGraph(words[1],"0","0","","","",system_display);
1385 else if (words.size()==3)
1387 page = mExecuter->ShowGraph(words[1],words[2],"0","","","",system_display);
1389 else if (words.size()==4)
1391 page = mExecuter->ShowGraph(words[1],words[2],words[3],"","","",system_display);
1393 else if (words.size()==5)
1395 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],"","",system_display);
1397 else if (words.size()==6)
1399 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],"",system_display);
1401 else if (words.size()==7)
1403 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],words[6],system_display);
1406 #ifdef _USE_WXWIDGETS_
1407 if ( WxConsole::GetInstance() != 0 )
1408 WxConsole::GetInstance()->ShowHtmlPage(page);
1411 //=======================================================================