1 /*=========================================================================
4 Module: $RCSfile: bbtkInterpreter.cxx,v $ $
6 Date: $Date: 2008/02/05 08:25:22 $
7 Version: $Revision: 1.20 $
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()
49 bbtk::MessageManager::RegisterMessageType("Echo","Level>0 : Prints the 'echo' commands of the user.\n\tLevel>1 : Prints the command being interpreted",1);
50 bbtk::MessageManager::RegisterMessageType("Interpreter","Messages of the interpreter",0);
51 bbtkDebugMessageInc("Interpreter",9,"Interpreter::Interpreter()" <<std::endl);
53 mGlobalInterpreter = this;
55 // mFactory = new bbtk::Factory();
56 mExecuter = new bbtk::Executer();
57 //mExecuter->SetFactory(mFactory);
59 // Builds the commands dict
66 info.syntax = "new <type> <name>";
67 info.help = "Creates a new black box of type <type> with name <name>";
68 mCommandDict[info.keyword] = info;
70 info.keyword = "delete";
74 info.syntax = "delete <box>";
75 info.help = "Deletes the black box of name <box>";
76 mCommandDict[info.keyword] = info;
78 info.keyword = "connect";
82 info.syntax = "connect <box1.output> <box2.input>";
83 info.help = "Connects the ouput <output> of black box <box1> to the input <input> of black box <box2>";
84 mCommandDict[info.keyword] = info;
86 info.keyword = "print";
90 info.syntax = "print <string>";
91 info.help = "Prints the string. Substitutes any token of the form '$box.output$' by the string adaptation of the output of the box (requires the right adaptor). No carriage return is issued at the end, use '\\n' to add carriage returns. The level of 'Echo' messages must be greater than 1 (see the command 'message').";
92 mCommandDict[info.keyword] = info;
94 info.keyword = "exec";
98 info.syntax = "exec <box | 'freeze' | 'unfreeze' >";
99 info.help = "Executes the black box of name <box> (and connected boxes if needed). If the special keyword 'freeze' is given then freezes any further execution command. 'unfreeze' reverts to normal execution mode.";
100 mCommandDict[info.keyword] = info;
102 info.keyword = "package";
105 info.code = cPackage;
106 info.syntax = "package <name>";
107 info.help = "Begins the definition of a package.";
108 mCommandDict[info.keyword] = info;
110 info.keyword = "endpackage";
113 info.code = cEndPackage;
114 info.syntax = "endpackage";
115 info.help = "Ends the definition of a package.";
116 mCommandDict[info.keyword] = info;
118 info.keyword = "define";
122 info.syntax = "define <type> [<package>]";
123 info.help = "Begins the definition of a new type of complex black box called <type>. If <package> if provided will create it in the given package.";
124 mCommandDict[info.keyword] = info;
126 info.keyword = "endefine";
129 info.code = cEndDefine;
130 info.syntax = "endefine";
131 info.help = "Ends the definition of a new type of complex black box";
132 mCommandDict[info.keyword] = info;
134 info.keyword = "input";
138 info.syntax = "input <name> <box.input> <help>";
139 info.help = "Defines the input <name> of the current working black box as being an alias for the input <input> of the black box <box>. <help> defines the help string for the newly created input";
140 mCommandDict[info.keyword] = info;
142 info.keyword = "output";
146 info.syntax = "output <name> <box.output> <help>";
147 info.help = "Defines the output <name> of the current working black box as being an alias for the output <output> of the black box <box>. <help> defines the help string for the newly created output";
148 mCommandDict[info.keyword] = info;
150 info.keyword = "set";
154 info.syntax = "set <box.input> <value>";
155 info.help = "Sets the value of the input <input> of the black box <box> to <value>. There must exist a string to the value type adaptor";
156 mCommandDict[info.keyword] = info;
158 info.keyword = "config"; // JPR
162 info.syntax = "config";
163 info.help = "Prints the value of all configuration parameters";
164 mCommandDict[info.keyword] = info;
166 info.keyword = "index"; // LG
170 info.syntax = "index [<filename> ['Initials'(default)|'Packages'|'Keywords']]";
171 info.help = "Creates an html index of known boxes. If filename is provided then save it to the file 'filename'. The default index entries are the initial letters of the names of the boxes. If 'Packages' or 'Keywords' is provided then the entries are either the package names or the keywords";
172 mCommandDict[info.keyword] = info;
174 info.keyword = "reset"; //EED
178 info.syntax = "reset";
179 info.help = "Deletes all boxes and unloads all packages (bbi is reset to its start state)";
180 mCommandDict[info.keyword] = info;
182 info.keyword = "author";
186 info.syntax = "author <string>";
187 info.help = "Adds the string <string> to the author information of the black box being defined";
188 mCommandDict[info.keyword] = info;
190 info.keyword = "keyword"; //JP
193 info.code = cKeyword;
194 info.syntax = "keyword <list of items, separated by ;>";
195 info.help = "Adds the string <string> to the keyword information of the black box being defined";
196 mCommandDict[info.keyword] = info;
198 info.keyword = "description";
201 info.code = cDescription;
202 info.syntax = "description <string>";
203 info.help = "Adds the string <string> to the descriptive information of the black box being defined";
204 mCommandDict[info.keyword] = info;
206 info.keyword = "help";
210 info.syntax = "help";
211 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>";
212 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.";
213 mCommandDict[info.keyword] = info;
215 info.keyword = "message";
218 info.code = cMessage;
219 info.syntax = "message <category> <level>";
220 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.";
221 mCommandDict[info.keyword] = info;
223 info.keyword = "include";
226 info.code = cInclude;
227 info.syntax = "include <filename>";
228 info.help = "Includes the file <filename>";
229 mCommandDict[info.keyword] = info;
231 info.keyword = "quit";
235 info.syntax = "quit";
236 info.help = "Quits the program (during script execution it stops the complete execution)";
237 mCommandDict[info.keyword] = info;
239 info.keyword = "load";
243 info.syntax = "load <packagename>";
244 info.help = "Loads the black box package <packagename>";
245 mCommandDict[info.keyword] = info;
247 info.keyword = "unload";
251 info.syntax = "unload <packagename>";
252 info.help = "Unloads the black box package <packagename>";
253 mCommandDict[info.keyword] = info;
255 info.keyword = "graph";
259 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 ]]]]]]";
260 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')";
261 mCommandDict[info.keyword] = info;
264 info.keyword = "workspace";
267 info.code = cWorkspace;
268 info.syntax = "workspace < ( freeze | unfreeze ) | ( rename <newname> ) >";
269 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.";
270 mCommandDict[info.keyword] = info;
273 bbtkDebugDecTab("Interpreter",9);
276 //=======================================================================
280 //=======================================================================
284 Interpreter::~Interpreter()
286 bbtkDebugMessageInc("Interpreter",9,"Interpreter::~Interpreter()" <<std::endl);
290 bbtkDebugDecTab("Interpreter",9);
292 //=======================================================================
295 //=======================================================================
299 void Interpreter::InterpretFile( const std::string& filename,
300 bool use_configuration_file)
302 bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretFile(\""<<filename<<"\")"<<std::endl);
304 bool exm = mCommandLine;
305 mCommandLine = false;
309 SwitchToFile(filename, use_configuration_file);
310 bool insideComment = false; // for multiline comment
311 while (mFile.size()>0)
313 while ((mFile.size()>0) &&
314 (!mFile.back()->eof()))
318 mFile.back()->getline(buf,500);
320 std::string str(buf);
321 int size=str.length();
322 if ( str[ size-1 ]==13 )
327 InterpretLine(str, insideComment);
329 //if (mFile.size()>0)
333 catch (QuitException e)
336 catch (bbtk::Exception e)
338 std::cerr << "* ERROR : "<<e.GetMessage()<<std::endl;
339 if (mFileName.size()) {
340 std::cerr << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
341 std::cerr << "* LINE : "<<mLine.back()<<std::endl;
344 catch (std::exception& e)
346 std::cerr << "* ERROR : "<<e.what()<<" (not in bbtk)"<<std::endl;
347 if (mFileName.size()) {
348 std::cerr << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
349 std::cerr << "* LINE : "<<mLine.back()<<std::endl;
354 std::cout << "* UNDEFINED ERROR (not a bbtk nor a std exception)"<<std::endl;
355 if (mFileName.size()) {
356 std::cout << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
357 std::cout << "* LINE : "<<mLine.back()<<std::endl;
362 bbtkDebugMessage("Interpreter",9,"EO Interpreter::InterpretFile(\""<<filename<<"\")"<<std::endl);
363 bbtkDecTab("Interpreter",9);
367 //=======================================================================
371 //=======================================================================
375 void Interpreter::InterpretLine( const std::string& line, bool &insideComment )
378 bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretLine(\""<<line<<"\")"<<std::endl);
379 bbtkMessage("Echo",2,"\""<<line<<"\""<<std::endl);
381 std::vector<std::string> words;
382 SplitLine(line,words);
387 bbtkDebugDecTab("Interpreter",9);
391 // Single line comment : # or //
392 if ( words[0][0]=='#' || (words[0][0]=='/' && words[0][1]=='/') )
394 bbtkDebugDecTab("Interpreter",9);
395 bbtkMessage("Interpreter",9,"Comment"<<std::endl);
399 // Multi line comment ( /* ... */ ) -delimiters on different lines !-
401 if (words[0][0]=='/' && words[0][1]=='*')
403 bbtkDebugDecTab("Interpreter",9);
404 bbtkMessage("Interpreter",9,"In multiline comment"<<std::endl);
405 insideComment = true;
409 if (words[0][0]=='*' && words[0][1]=='/')
411 bbtkDebugDecTab("Interpreter",9);
412 bbtkMessage("Interpreter",9,"Out multiline comment"<<std::endl);
413 if ( !insideComment ) {
414 bbtkDebugDecTab("Interpreter",9);
415 bbtkMessage("Interpreter",9,"Comment mismatch : '*/' with no matching '/*'"<<std::endl);
417 insideComment = false;
423 bbtkDebugDecTab("Interpreter",9);
424 bbtkMessage("Interpreter",9,"Multiline Comment"<<std::endl);
429 CommandInfoType command;
430 InterpretCommand(words,command);
432 bbtkDebugMessage("Interpreter",9,
433 "Command='"<<command.keyword
434 <<"' code="<<command.code<<std::endl);
436 std::string left,right,left2,right2;
437 std::string filename;
438 switch (command.code)
441 mExecuter->Create(words[1],words[2]);
446 // mExecuter->Remove(words[1]);
450 Utilities::SplitAroundFirstDot(words[1],left,right);
451 Utilities::SplitAroundFirstDot(words[2],left2,right2);
452 mExecuter->Connect(left,right,left2,right2);
456 mExecuter->BeginPackage(words[1]);
460 mExecuter->EndPackage();
464 if (mFileName.size()>0)
466 filename = Utilities::get_file_name(mFileName.back());
470 mExecuter->Define(words[1],"",filename);
474 mExecuter->Define(words[1],words[2],filename);
479 mExecuter->EndDefine();
483 Print(words[1]); /// \todo use mExecuter
487 if (words[1]=="freeze")
488 mExecuter->SetNoExecMode(true);
489 else if (words[1]=="unfreeze")
490 mExecuter->SetNoExecMode(false);
492 mExecuter->Update(words[1]);
496 Utilities::SplitAroundFirstDot(words[2],left,right);
497 mExecuter->DefineInput(words[1],left,right,words[3]);
501 Utilities::SplitAroundFirstDot(words[2],left,right);
502 mExecuter->DefineOutput(words[1],left,right,words[3]);
506 Utilities::SplitAroundFirstDot(words[1],left,right);
507 mExecuter->Set(left,right,words[2]);
511 mExecuter->Author(words[1]);
515 mExecuter->Keyword(words[1]);
520 Index("tmp_index.html");
521 else if (words.size()==2)
523 else if (words.size()==3)
524 Index(words[1],words[2]);
527 mExecuter->Description(words[1]);
537 bbtk::MessageManager::PrintInfo();
541 sscanf(words[2].c_str(),"%d",&level);
542 bbtk::MessageManager::SetMessageLevel(words[1],level);
555 this->mExecuter->Reset();
561 InterpretFile(words[1], true ); // true : better pass use_config_file
565 SwitchToFile(words[1], true ); // true : better pass use_config_file
570 LoadPackage(words[1], true ); // true : better pass use_config_file
574 UnLoadPackage(words[1]);
578 throw QuitException();
582 if (words.size() == 2)
584 if (words[1]=="freeze") mExecuter->SetNoExecMode(true);
585 else if (words[1]=="unfreeze") mExecuter->SetNoExecMode(false);
589 mExecuter->SetWorkspaceName(words[2]);
594 bbtkInternalError("should not reach here !!!");
597 bbtkDecTab("Interpreter",9);
599 //=======================================================================
605 //=======================================================================
609 void Interpreter::SplitLine ( const std::string& str, std::vector<std::string>& tokens)
611 bbtkDebugMessageInc("Interpreter",9,"Interpreter::SplitLine(\""<<str<<"\")"<<std::endl);
613 std::string delimiters = "\"";
614 std::vector<std::string> quote;
615 Utilities::SplitString(str,delimiters,quote);
618 std::vector<std::string>::iterator i;
619 for (i=quote.begin(); i!=quote.end(); )
621 Utilities::SplitString(*i,delimiters,tokens);
625 // bbtkDebugMessage("Interpreter",0,"\""<<*i<<"\""<<std::endl);
626 tokens.push_back(*i);
631 for (i=tokens.begin(); i!=tokens.end(); ++i)
633 bbtkDebugMessage("Interpreter",9,"["<<*i<<"] ");
635 bbtkDebugMessageCont("Interpreter",9,std::endl);
637 bbtkDebugDecTab("Interpreter",9);
639 //=======================================================================
642 //=======================================================================
643 // Replaces substrings "\\n" by a real carriage return "\n"
644 void SubsBackslashN ( std::string& s )
646 std::string ss("\\n");
647 std::string::size_type pos = 0;
650 while ( pos != std::string::npos )
652 s.replace(pos,2,cr,1);
653 pos = s.find(ss, pos-1);
656 //=======================================================================
659 //=======================================================================
663 void Interpreter::Print( const std::string& str)
665 if (mExecuter->GetNoExecMode()) return;
667 bbtkDebugMessageInc("Interpreter",9,"Interpreter::SplitLine(\""<<str<<"\")"<<std::endl);
669 std::vector<std::string> chains;
670 std::string delimiters("$");
672 // Skip delimiters at beginning.
673 std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
675 if (lastPos>0) is_text = false;
677 // Find first delimiter.
678 std::string::size_type pos = str.find_first_of(delimiters, lastPos);
680 while (std::string::npos != pos || std::string::npos != lastPos)
684 // Found a text token, add it to the vector.
685 chains.push_back(str.substr(lastPos, pos - lastPos));
689 // is an output (between $$) : decode
690 std::string tok,box,output;
691 tok = str.substr(lastPos, pos - lastPos);
692 Utilities::SplitAroundFirstDot(tok,box,output);
693 chains.push_back( mExecuter->Get(box,output) );
695 // Skip delimiters. Note the "not_of"
696 lastPos = str.find_first_not_of(delimiters, pos);
697 // Find next delimiter
698 pos = str.find_first_of(delimiters, lastPos);
702 std::vector<std::string>::iterator i;
703 for (i= chains.begin(); i!=chains.end(); ++i)
705 // bbtkMessage("Echo",1,*i);
709 std::cout << std::endl;
710 bbtkDebugDecTab("Interpreter",9);
713 //=======================================================================
718 // ===================================================================================
720 void Interpreter::SwitchToFile( const std::string& name,
721 bool use_configuration_file )
723 // Note : in the following :
724 // name : the user supplied name
725 // - abreviated name e.g. scr scr.bbs
726 // - relative full name e.g. ./scr.bbs ../../scr.bbs
727 // - absolute full name e.g. /home/usrname/proj/dir/scr.bbs
728 // same for Windows, with c:, d: ...
730 // use ./directory/subdir/scrname.bbs
733 bbtkDebugMessageInc("Interpreter",9,"Interpreter::SwitchToFile( \""
734 <<name<<"\")"<<std::endl);
736 std::vector<std::string> script_paths;
737 std::string fullPathScriptName; // full path script name
738 std::string pkgname; // e.g. <scriptname>.bbs
739 std::vector<std::string> Filenames;
741 if (use_configuration_file)
743 // The following is *NOT* a debug time message :
744 // It's a user intended message.
745 // Please don't remove it.
746 bbtkMessage("Interpreter",1,
747 "look for : [" << name
748 << "] (use_configuration_file == TRUE)" << std::endl);
749 script_paths = ConfigurationFile::GetInstance().Get_bbs_paths();
752 pkgname = Utilities::ExtractScriptName(name,upath);
754 bool fullnameGiven = false;
755 bool foundFile = false;
757 if(pkgname == "*") // =========================================== load all boxes (e.g. std/boxes/*)
761 if (upath[0]=='/' || upath[1] == ':' ) // ==== absolute name, load all .bbs files
763 int nbFiles = Utilities::Explore(upath, false, Filenames);
765 for (std::vector<std::string>::iterator i = Filenames.begin(); i!= Filenames.end(); ++i)
767 if ((*i).substr((*i).size()-4, 4) != ".bbs")
768 continue; // ignore non .bbs files
773 bbtkMessage("Interpreter",2,
774 "WARNING : No '.bbs' file found in ["
775 << upath << "]" << std::endl);
782 std::vector<std::string>::iterator i;
783 std::string fullDirectoryName;
784 for (i=script_paths.begin();i!=script_paths.end();++i)// ==== relative name, iterate + load all .bbs files
788 // we *really* want '.' to be the current working directory
790 char buf[2048]; // for getcwd
791 char * currentDir = getcwd(buf, 2048);
792 std::string cwd(currentDir);
796 fullDirectoryName = Utilities::MakePkgnameFromPath(path, upath, false);
798 // Check if library exists
799 if ( ! Utilities::IsDirectory(fullDirectoryName) )
801 // The following is *NOT* a debug time message :
802 // It's a user intended message.
803 // Please don't remove it.
804 bbtkMessage("Interpreter",1," [" <<fullDirectoryName
805 <<"] : doesn't exist" <<std::endl);
806 continue; // try next path
811 int nbFiles = Utilities::Explore(fullDirectoryName, false, Filenames);
814 for (std::vector<std::string>::iterator i = Filenames.begin(); i!= Filenames.end(); ++i)
817 if ((*i).substr((*i).size()-4, 4) != ".bbs")
818 continue; // ignore non .bbs files
823 bbtkMessage("Interpreter",1,
824 "WARNING : No '.bbs' file found in ["
825 << fullDirectoryName << "]" << std::endl);
827 //break; // a directory was found; we stop iterating
828 // LG : No! We want all files included !
833 //std::string::size_type slash_position = name.find_last_of("/\\");
835 // if name starts with a / or a . or contains : user is assumed to have passed a relative/absolute name
836 // (not only a plain script name)
837 // we trust him, and try to expland the directory name
838 // WARNING : starting from current local directory : ./whatYouWant (./ mandatory!)
840 if (name[0]=='/' || name[1] == ':' || name[0]=='.') // absolute path (linux/windows) or relative path
843 // ===========================================================check user supplied location
844 fullnameGiven = true;
847 fullPathScriptName = Utilities::ExpandLibName(name, false);
849 // allow user to always forget ".bbs"
850 int l = fullPathScriptName.size();
856 if (fullPathScriptName.substr(l-4, 4) != ".bbs")
858 fullPathScriptName = fullPathScriptName + ".bbs";
863 fullPathScriptName = fullPathScriptName + ".bbs";
866 if ( Utilities::FileExists(fullPathScriptName))
874 // =============================================================== iterate on the paths
877 std::vector<std::string>::iterator i;
878 for (i=script_paths.begin();i!=script_paths.end();++i)
882 // we *really* want '.' to be the current working directory
884 char buf[2048]; // for getcwd
885 char * currentDir = getcwd(buf, 2048);
886 std::string cwd(currentDir);
890 // fullPathScriptName = Utilities::MakePkgnameFromPath(path, name, true); //pkgname);
892 fullPathScriptName = Utilities::MakePkgnameFromPath(path, name, true);
895 // Check if library exists
896 if ( ! Utilities::FileExists(fullPathScriptName) )
898 // The following is *NOT* a debug time message :
899 // It's a user intended message.
900 // Please don't remove it.
901 bbtkMessage("Interpreter",1,
902 " [" <<fullPathScriptName <<"] : doesn't exist"
904 continue; // try next path
906 bbtkMessage("Interpreter",1,
907 " [" <<fullPathScriptName
908 <<"] : found" <<std::endl);
910 break; // a script was found; we stop iterating
912 } //------------------ // end for ( package_paths.begin();i!=package_paths.end() )
918 if(fullPathScriptName == "")
919 bbtkError("Path ["<<upath<<"] doesn't exist");
921 bbtkError("Script ["<<fullPathScriptName<<"] not found");
923 bbtkError("No ["<<pkgname<<".bbs] script found");
927 LoadScript(fullPathScriptName);
933 //=======================================================================
935 void Interpreter::LoadScript( std::string fullPathScriptName)
937 if (find(mFileName.begin(),mFileName.end(),fullPathScriptName)
940 bbtkMessage("Interpreter",1,
941 "file '"<<fullPathScriptName
942 <<"' already open : do not open it once more to prevent recursive inclusion"<<std::endl);
946 bbtkMessage("Interpreter",1,fullPathScriptName<<" found"<<std::endl);
949 s = new std::ifstream;
950 s->open(fullPathScriptName.c_str());
953 bbtkError("Could not open file ["<<fullPathScriptName<<"]");
957 bbtkMessage("Interpreter",1," -->[" << fullPathScriptName
958 << "] found" << std::endl);
961 mFileName.push_back(fullPathScriptName);
966 //=======================================================================
970 void Interpreter::CloseCurrentFile()
972 bbtkDebugMessage("Interpreter",9,"Interpreter::CloseCurrentFile()"
977 bbtkDebugMessage("Interpreter",9," -> no file left open"<<std::endl);
981 mFile.back()->close();
984 bbtkDebugMessage("Interpreter",9,
985 " Closing file '"<<mFileName.back()<<"'"<<std::endl);
987 mFileName.pop_back();
989 bbtkDebugMessage("Interpreter",9," Remains "
991 <<" open"<<std::endl);
992 bbtkDebugMessage("Interpreter",9,"EO Interpreter::CloseCurrentFile()"
995 //=======================================================================
997 //=======================================================================
1001 void Interpreter::CloseAllFiles()
1003 bbtkDebugMessage("Interpreter",9,"Interpreter::CloseAllFiles()"
1006 while (mFile.size() != 0)
1008 mFile.back()->close();
1009 delete mFile.back();
1011 bbtkDebugMessage("Interpreter",9,
1012 " Closing file '"<<mFileName.back()<<"'"<<std::endl);
1013 mFileName.pop_back();
1016 bbtkDebugMessage("Interpreter",9,"EO Interpreter::CloseAllFiles()"
1019 //=======================================================================
1023 //=======================================================================
1027 void Interpreter::InterpretCommand( const std::vector<std::string>& words,
1028 CommandInfoType& info )
1030 bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretCommand(...)"<<std::endl);
1032 // searches the command keyword
1033 CommandDictType::iterator c;
1034 c = mCommandDict.find(words[0]);
1035 if ( c == mCommandDict.end() ) {
1036 bbtkError(words[0]<<" : unknown command");
1039 // tests the number of args
1040 if ( ( words.size()-1 < c->second.argmin ) ||
1041 ( words.size()-1 > c->second.argmax ) )
1043 HelpCommand(words[0]);
1044 bbtkError(words[0]<<" : wrong number of arguments");
1048 bbtkDecTab("Interpreter",9);
1050 //=======================================================================
1053 //=======================================================================
1054 /// Displays help on all the commands
1055 void Interpreter::Help(const std::vector<std::string>& words)
1057 unsigned int nbarg = words.size()-1;
1065 if (words[1]=="packages")
1067 PrintPackages(true);
1072 HelpCommand(words[1]);
1074 catch (bbtk::Exception e)
1078 HelpPackage(words[1]);
1080 catch (bbtk::Exception f)
1084 HelpBlackBox(words[1]);
1086 catch (bbtk::Exception g)
1090 this->mExecuter->ShowRelations(words[1],"0","9999");
1092 catch (bbtk::Exception h){
1093 bbtkError("\""<<words[1].c_str()
1094 <<"\" is not a known command, package, black box type or black box name");
1102 if (words[2]=="all")
1104 if ( words[1]=="packages" )
1106 PrintPackages(true,true);
1111 HelpPackage(words[1],true);
1113 catch (bbtk::Exception f)
1119 HelpCommand(words[0]);
1120 bbtkError(words[0]<<" : syntax error");
1125 bbtkError("Should not reach here !!!");
1128 //=======================================================================
1130 //===================================================================
1131 /// Displays the Configuration
1132 void Interpreter::Config() const
1134 bbtkDebugMessageInc("Core",9,"Factory::Config"<<std::endl);
1136 ConfigurationFile cf = ConfigurationFile::GetInstance();
1138 const std::string config_xml_full_path = cf.Get_config_xml_full_path();
1139 const std::string description = cf.Get_description();
1140 const std::string url = cf.Get_url();
1141 const std::string data_path = cf.Get_data_path();
1142 const std::string default_doc_tmp = cf.Get_default_doc_tmp();
1143 const std::string file_separator = cf.Get_file_separator();
1144 const std::vector<std::string>bbs_paths = cf.Get_bbs_paths();
1145 const std::vector<std::string>package_paths = cf.Get_package_paths();
1147 bbtkMessage("Help",1, "=============" << std::endl);
1148 bbtkMessage("Help",1, "Configuration" << std::endl);
1149 bbtkMessage("Help",1, "=============" << std::endl);
1150 bbtkMessage("Help",1, "bbtk_config.xml : [" << config_xml_full_path << "]" << std::endl);
1151 bbtkMessage("Help",1, "Documentation Url : [" << url << "]" << std::endl);
1152 bbtkMessage("Help",1, "Data Path : [" << data_path << "]" << std::endl);
1153 bbtkMessage("Help",1, "Default Doc_tmp : [" << default_doc_tmp << "]" << std::endl);
1154 bbtkMessage("Help",1, "File Separator : [" << file_separator << "]" << std::endl);
1156 std::vector<std::string>::const_iterator i;
1158 bbtkMessage("Help",1, "BBS Paths " << std::endl);
1159 for (i = bbs_paths.begin(); i!=bbs_paths.end(); ++i )
1161 bbtkMessage("Help",1,"--- ["<<*i<<"]"<<std::endl);
1164 bbtkMessage("Help",1, "PACKAGE Paths : " << std::endl);
1165 for (i = package_paths.begin(); i!=package_paths.end(); ++i )
1167 bbtkMessage("Help",1,"--- ["<<*i<<"]"<<std::endl);
1170 bbtkDebugDecTab("Core",9);
1173 //=======================================================================
1174 /// Displays help on all the commands
1175 void Interpreter::HelpCommands()
1177 std::cout << "Available commands :" << std::endl;
1178 CommandDictType::iterator i;
1179 for ( i = mCommandDict.begin();
1180 i != mCommandDict.end();
1182 std::cout << " " << i->first << std::endl;
1183 // std::cout << " usage : " << i->second.syntax << std::endl;
1184 // std::cout << " " << i->second.help << std::endl;
1188 //=======================================================================
1191 //=======================================================================
1192 /// Displays help on a particular commands
1193 void Interpreter::HelpCommand(const std::string& s)
1195 CommandDictType::iterator c;
1196 c = mCommandDict.find(s);
1197 if ( c == mCommandDict.end() ) {
1198 bbtkError(s<<" : Unknown command");
1200 // std::cout << " " << s << " : "<< std::endl;
1201 // CommandParamDictType::iterator i;
1202 // for ( i = c->second.begin();
1203 // i != c->second.end();
1205 std::cout << " usage : " << c->second.syntax << std::endl;
1206 std::cout << " " << c->second.help << std::endl;
1209 //=======================================================================
1212 //=======================================================================
1213 /// Fills the vector commands with the commands which
1214 /// have the first n chars of buf for prefix
1215 /// TODO : skip initial spaces in buf and also return the position of first
1216 /// non blank char in buf
1217 void Interpreter::FindCommandsWithPrefix( char* buf,
1219 std::vector<std::string>& commands )
1221 CommandDictType::const_iterator i;
1222 for (i=mCommandDict.begin(); i!=mCommandDict.end(); ++i)
1224 if ((i->first).find(buf,0,n) == 0)
1225 commands.push_back(i->first);
1228 //=======================================================================
1232 //=======================================================================
1233 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1235 inline void PrintChar(char c) { write(STDOUT_FILENO,&c,1); }
1236 inline void BackSpace() { write(STDOUT_FILENO,"\b \b",3); }
1238 // LG : KEYBOARD CODES AS SCANNED ON MY TTY : UNIVERSAL ?
1239 // IF NOT THE USER SHOULD BE ABLE TO CONFIGURE IT
1240 // E.G. STORE THIS IN bbtk_config.xml
1241 #define BBTK_UP_ARROW_KBCODE 0x00415B1B
1242 #define BBTK_DOWN_ARROW_KBCODE 0x00425B1B
1243 #define BBTK_RIGHT_ARROW_KBCODE 0x00435B1B
1244 #define BBTK_LEFT_ARROW_KBCODE 0x00445B1B
1245 #define BBTK_BACKSPACE_KBCODE 0x00000008
1246 #define BBTK_DEL_KBCODE 0x0000007F
1247 #define BBTK_SPACE_KBCODE 0x00000020
1249 //=======================================================================
1250 void Interpreter::GetLineFromPrompt(std::string& s)
1255 int MAX_LINE_SIZE = 160;
1256 int MAX_HISTORY_SIZE = 100;
1258 char* newline = new char[MAX_LINE_SIZE];
1259 memset(newline,0,MAX_LINE_SIZE);
1260 char* histline = new char[MAX_LINE_SIZE];
1261 memset(histline,0,MAX_LINE_SIZE);
1263 char* line = newline;
1264 int hist = mHistory.size();
1271 read ( STDIN_FILENO, &c, 4) ;
1273 bbtkDebugMessage("Debug",9,"[0x"<<std::hex<<c<<"]\n");
1275 // Printable character
1276 if ( (ind<MAX_LINE_SIZE-1) &&
1277 ( c >= BBTK_SPACE_KBCODE ) &&
1278 ( c < BBTK_DEL_KBCODE ))
1286 // delete the unused line
1292 // empty lines are not stored in from history
1295 // if history too long : delete oldest command
1296 if (mHistory.size()>MAX_HISTORY_SIZE)
1298 delete mHistory.front();
1299 mHistory.pop_front();
1301 mHistory.push_back(line);
1306 else if ( (ind>0) &&
1307 ((c == BBTK_BACKSPACE_KBCODE) ||
1308 (c == BBTK_DEL_KBCODE)) )
1316 // TODO : Command completion
1317 std::vector<std::string> commands;
1318 FindCommandsWithPrefix( line,ind,commands);
1319 if (commands.size()==1)
1321 std::string com = *commands.begin();
1322 for (; ind<com.size(); ++ind)
1324 PrintChar(com[ind]);
1330 else if (commands.size()>1)
1332 std::vector<std::string>::iterator i;
1334 for (i=commands.begin();i!=commands.end();++i)
1336 write(STDOUT_FILENO,(*i).c_str(),strlen((*i).c_str()));
1339 write(STDOUT_FILENO,"\n> ",3);
1340 //for (int j=0;j<ind;++j)
1342 write(STDOUT_FILENO,line,ind);
1346 // Arrow up : back in history
1347 else if (c==BBTK_UP_ARROW_KBCODE)
1351 // erase current line
1352 while (ind--) BackSpace();
1356 strcpy(histline,mHistory[hist]);
1360 write(STDOUT_FILENO,line,ind);
1363 // Arrow down : down in history
1364 else if (c==BBTK_DOWN_ARROW_KBCODE)
1366 if (hist<mHistory.size()-1)
1368 // erase current line
1369 while (ind--) BackSpace();
1373 strcpy(histline,mHistory[hist]);
1377 write(STDOUT_FILENO,line,ind);
1379 // end of history : switch back to newline
1380 else if (hist==mHistory.size()-1)
1382 // erase current line
1383 while (ind--) BackSpace();
1390 write(STDOUT_FILENO,line,ind);
1394 else if (line[ind]!=0 && c==BBTK_RIGHT_ARROW_KBCODE)
1396 PrintChar(line[ind]);
1401 else if (ind>0 && c==BBTK_LEFT_ARROW_KBCODE)
1409 write(STDOUT_FILENO,"\n\r",2);
1417 //=======================================================================
1418 void Interpreter::GetLineFromPrompt(std::string& s)
1444 //=======================================================================
1450 //=======================================================================
1451 void Interpreter::CommandLineInterpreter()
1453 bbtkDebugMessageInc("Interpreter",9,
1454 "Interpreter::CommandLineInterpreter()"<<std::endl);
1456 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1457 // Initialise the tty in non canonical mode with no echo
1458 // oter remembers the previous settings to restore them after
1459 struct termios ter,oter;
1462 ter.c_lflag &= ~ECHO;
1463 ter.c_lflag &= ~ICANON;
1466 tcsetattr(0,TCSANOW,&ter);
1469 mCommandLine = true;
1471 bool insideComment = false; // for multiline comment
1477 GetLineFromPrompt(line);
1478 InterpretLine(line, insideComment);
1480 catch (QuitException e)
1484 catch (bbtk::Exception e)
1488 catch (std::exception& e)
1490 std::cerr << "* ERROR :: "<<e.what()<<" (not in bbtk)"<<std::endl;
1494 std::cerr << "* UNDEFINED ERROR (not a bbtk nor a std exception)"<<std::endl;
1499 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1500 tcsetattr(0,TCSANOW,&oter);
1503 std::cout << "Good bye !" << std::endl;
1505 bbtkDebugDecTab("Interpreter",9);
1508 //=======================================================================
1509 void Interpreter::Graph(const std::vector<std::string>& words)
1512 bool system_display = true;
1514 #ifdef _USE_WXWIDGETS_
1515 if ( WxConsole::GetInstance() != 0 ) system_display = false;
1518 if (words.size()==1)
1520 page = mExecuter->ShowGraph(".","0","0","","","",system_display);
1522 else if (words.size()==2)
1524 page = mExecuter->ShowGraph(words[1],"0","0","","","",system_display);
1526 else if (words.size()==3)
1528 page = mExecuter->ShowGraph(words[1],words[2],"0","","","",system_display);
1530 else if (words.size()==4)
1532 page = mExecuter->ShowGraph(words[1],words[2],words[3],"","","",system_display);
1534 else if (words.size()==5)
1536 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],"","",system_display);
1538 else if (words.size()==6)
1540 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],"",system_display);
1542 else if (words.size()==7)
1544 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],words[6],system_display);
1547 #ifdef _USE_WXWIDGETS_
1548 if ( WxConsole::GetInstance() != 0 )
1549 WxConsole::GetInstance()->ShowHtmlPage(page);
1552 //=======================================================================
1555 //=======================================================================
1556 void Interpreter::Index(const std::string& filename,
1557 const std::string& type)
1559 Factory::IndexEntryType t;
1560 if (type=="Initials") t = Factory::Initials;
1561 else if (type=="Keywords") t = Factory::Keywords;
1562 else if (type=="Packages") t = Factory::Packages;
1564 GetGlobalFactory()->CreateHtmlIndex(t,filename);
1566 //=======================================================================