1 /*=========================================================================
4 Module: $RCSfile: bbtkInterpreter.cxx,v $ $
6 Date: $Date: 2008/02/05 13:23:46 $
7 Version: $Revision: 1.25 $
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
62 info.category = "new";
66 info.syntax = "new <type> <name>";
67 info.help = "Creates a new black box of type <type> with name <name>";
68 mCommandDict[info.category] = info;
70 info.category = "delete";
74 info.syntax = "delete <box>";
75 info.help = "Deletes the black box of name <box>";
76 mCommandDict[info.category] = info;
78 info.category = "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.category] = info;
86 info.category = "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.category] = info;
94 info.category = "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 category 'freeze' is given then freezes any further execution command. 'unfreeze' reverts to normal execution mode.";
100 mCommandDict[info.category] = info;
102 info.category = "package";
105 info.code = cPackage;
106 info.syntax = "package <name>";
107 info.help = "Begins the definition of a package.";
108 mCommandDict[info.category] = info;
110 info.category = "endpackage";
113 info.code = cEndPackage;
114 info.syntax = "endpackage";
115 info.help = "Ends the definition of a package.";
116 mCommandDict[info.category] = info;
118 info.category = "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.category] = info;
126 info.category = "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.category] = info;
134 info.category = "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.category] = info;
142 info.category = "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.category] = info;
150 info.category = "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.category] = info;
158 info.category = "config"; // JPR
162 info.syntax = "config";
163 info.help = "Prints the value of all configuration parameters";
164 mCommandDict[info.category] = info;
166 info.category = "index"; // LG
171 info.syntax = "index [<filename> ['Initials'(default)|'Packages'|'Categories']]";
172 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 'Categories' is provided then the entries are either the packages names or the categories";
173 mCommandDict[info.category] = info;
175 info.category = "reset"; //EED
179 info.syntax = "reset";
180 info.help = "Deletes all boxes and unloads all packages (bbi is reset to its start state)";
181 mCommandDict[info.category] = info;
183 info.category = "author";
187 info.syntax = "author <string>";
188 info.help = "Adds the string <string> to the author information of the black box being defined";
189 mCommandDict[info.category] = info;
191 info.category = "category"; //JP
194 info.code = cCategory;
195 info.syntax = "category <list of items, separated by ;>";
196 info.help = "Adds the string <string> to the category information of the black box being defined";
197 mCommandDict[info.category] = info;
199 info.category = "description";
202 info.code = cDescription;
203 info.syntax = "description <string>";
204 info.help = "Adds the string <string> to the descriptive information of the black box being defined";
205 mCommandDict[info.category] = info;
207 info.category = "help";
211 info.syntax = "help";
212 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>";
213 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.";
214 mCommandDict[info.category] = info;
216 info.category = "message";
219 info.code = cMessage;
220 info.syntax = "message <kind> <level>";
221 info.help = "Sets the level of the kind of messages <kind> to <level>.\n If kind='All' then sets the level for all kinds. If no kind nor level is passed then prints info on available kinds of messages and their current level."; mCommandDict[info.category] = info;
223 info.category = "include";
226 info.code = cInclude;
227 info.syntax = "include <filename>";
228 info.help = "Includes the file <filename>";
229 mCommandDict[info.category] = info;
231 info.category = "quit";
235 info.syntax = "quit";
236 info.help = "Quits the program (during script execution it stops the complete execution)";
237 mCommandDict[info.category] = info;
239 info.category = "load";
243 info.syntax = "load <packagename>";
244 info.help = "Loads the black box package <packagename>";
245 mCommandDict[info.category] = info;
247 info.category = "unload";
251 info.syntax = "unload <packagename>";
252 info.help = "Unloads the black box package <packagename>";
253 mCommandDict[info.category] = info;
255 info.category = "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.category] = info;
264 info.category = "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.category] = 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.category
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->Category(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",2,
902 " [" <<fullPathScriptName <<"] : doesn't exist"
904 continue; // try next path
906 bbtkMessage("Interpreter",2,
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,"file '"<<fullPathScriptName
941 <<"' already open : I do not open it once more to prevent recursive inclusion"<<std::endl);
946 s = new std::ifstream;
947 s->open(fullPathScriptName.c_str());
950 bbtkError("Could not open file ["<<fullPathScriptName<<"]");
954 bbtkMessage("Interpreter",1," -->[" << fullPathScriptName
955 << "] found" << std::endl);
958 mFileName.push_back(fullPathScriptName);
963 //=======================================================================
967 void Interpreter::CloseCurrentFile()
969 bbtkDebugMessage("Interpreter",9,"Interpreter::CloseCurrentFile()"
974 bbtkDebugMessage("Interpreter",9," -> no file left open"<<std::endl);
978 mFile.back()->close();
981 bbtkDebugMessage("Interpreter",9,
982 " Closing file '"<<mFileName.back()<<"'"<<std::endl);
984 mFileName.pop_back();
986 bbtkDebugMessage("Interpreter",9," Remains "
988 <<" open"<<std::endl);
989 bbtkDebugMessage("Interpreter",9,"EO Interpreter::CloseCurrentFile()"
992 //=======================================================================
994 //=======================================================================
998 void Interpreter::CloseAllFiles()
1000 bbtkDebugMessage("Interpreter",9,"Interpreter::CloseAllFiles()"
1003 while (mFile.size() != 0)
1005 mFile.back()->close();
1006 delete mFile.back();
1008 bbtkDebugMessage("Interpreter",9,
1009 " Closing file '"<<mFileName.back()<<"'"<<std::endl);
1010 mFileName.pop_back();
1013 bbtkDebugMessage("Interpreter",9,"EO Interpreter::CloseAllFiles()"
1016 //=======================================================================
1020 //=======================================================================
1024 void Interpreter::InterpretCommand( const std::vector<std::string>& words,
1025 CommandInfoType& info )
1027 bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretCommand(...)"<<std::endl);
1029 // searches the command category
1030 CommandDictType::iterator c;
1031 c = mCommandDict.find(words[0]);
1032 if ( c == mCommandDict.end() ) {
1033 bbtkError(words[0]<<" : unknown command");
1036 // tests the number of args
1037 if ( ( words.size()-1 < c->second.argmin ) ||
1038 ( words.size()-1 > c->second.argmax ) )
1040 HelpCommand(words[0]);
1041 bbtkError(words[0]<<" : wrong number of arguments");
1045 bbtkDecTab("Interpreter",9);
1047 //=======================================================================
1050 //=======================================================================
1051 /// Displays help on all the commands
1052 void Interpreter::Help(const std::vector<std::string>& words)
1054 unsigned int nbarg = words.size()-1;
1062 if (words[1]=="packages")
1064 PrintPackages(true);
1069 HelpCommand(words[1]);
1071 catch (bbtk::Exception e)
1075 HelpPackage(words[1]);
1077 catch (bbtk::Exception f)
1081 HelpBlackBox(words[1]);
1083 catch (bbtk::Exception g)
1087 this->mExecuter->ShowRelations(words[1],"0","9999");
1089 catch (bbtk::Exception h){
1090 bbtkError("\""<<words[1].c_str()
1091 <<"\" is not a known command, package, black box type or black box name");
1099 if (words[2]=="all")
1101 if ( words[1]=="packages" )
1103 PrintPackages(true,true);
1108 HelpPackage(words[1],true);
1110 catch (bbtk::Exception f)
1116 HelpCommand(words[0]);
1117 bbtkError(words[0]<<" : syntax error");
1122 bbtkError("Should not reach here !!!");
1125 //=======================================================================
1127 //===================================================================
1128 /// Displays the Configuration
1129 void Interpreter::Config() const
1131 bbtkDebugMessageInc("Kernel",9,"Factory::Config"<<std::endl);
1133 ConfigurationFile cf = ConfigurationFile::GetInstance();
1135 const std::string config_xml_full_path = cf.Get_config_xml_full_path();
1136 const std::string description = cf.Get_description();
1137 const std::string url = cf.Get_url();
1138 const std::string data_path = cf.Get_data_path();
1139 const std::string default_doc_tmp = cf.Get_default_doc_tmp();
1140 const std::string file_separator = cf.Get_file_separator();
1141 const std::vector<std::string>bbs_paths = cf.Get_bbs_paths();
1142 const std::vector<std::string>package_paths = cf.Get_package_paths();
1144 bbtkMessage("Help",1, "=============" << std::endl);
1145 bbtkMessage("Help",1, "Configuration" << std::endl);
1146 bbtkMessage("Help",1, "=============" << std::endl);
1147 bbtkMessage("Help",1, "bbtk_config.xml : [" << config_xml_full_path << "]" << std::endl);
1148 bbtkMessage("Help",1, "Documentation Url : [" << url << "]" << std::endl);
1149 bbtkMessage("Help",1, "Data Path : [" << data_path << "]" << std::endl);
1150 bbtkMessage("Help",1, "Default Doc_tmp : [" << default_doc_tmp << "]" << std::endl);
1151 bbtkMessage("Help",1, "File Separator : [" << file_separator << "]" << std::endl);
1153 std::vector<std::string>::const_iterator i;
1155 bbtkMessage("Help",1, "BBS Paths " << std::endl);
1156 for (i = bbs_paths.begin(); i!=bbs_paths.end(); ++i )
1158 bbtkMessage("Help",1,"--- ["<<*i<<"]"<<std::endl);
1161 bbtkMessage("Help",1, "PACKAGE Paths : " << std::endl);
1162 for (i = package_paths.begin(); i!=package_paths.end(); ++i )
1164 bbtkMessage("Help",1,"--- ["<<*i<<"]"<<std::endl);
1167 bbtkDebugDecTab("Kernel",9);
1170 //=======================================================================
1171 /// Displays help on all the commands
1172 void Interpreter::HelpCommands()
1174 std::cout << "Available commands :" << std::endl;
1175 CommandDictType::iterator i;
1176 for ( i = mCommandDict.begin();
1177 i != mCommandDict.end();
1179 std::cout << " " << i->first << std::endl;
1180 // std::cout << " usage : " << i->second.syntax << std::endl;
1181 // std::cout << " " << i->second.help << std::endl;
1185 //=======================================================================
1188 //=======================================================================
1189 /// Displays help on a particular commands
1190 void Interpreter::HelpCommand(const std::string& s)
1192 CommandDictType::iterator c;
1193 c = mCommandDict.find(s);
1194 if ( c == mCommandDict.end() ) {
1195 bbtkError(s<<" : Unknown command");
1197 // std::cout << " " << s << " : "<< std::endl;
1198 // CommandParamDictType::iterator i;
1199 // for ( i = c->second.begin();
1200 // i != c->second.end();
1202 std::cout << " usage : " << c->second.syntax << std::endl;
1203 std::cout << " " << c->second.help << std::endl;
1206 //=======================================================================
1209 //=======================================================================
1210 /// Fills the vector commands with the commands which
1211 /// have the first n chars of buf for prefix
1212 /// TODO : skip initial spaces in buf and also return the position of first
1213 /// non blank char in buf
1214 void Interpreter::FindCommandsWithPrefix( char* buf,
1216 std::vector<std::string>& commands )
1218 CommandDictType::const_iterator i;
1219 for (i=mCommandDict.begin(); i!=mCommandDict.end(); ++i)
1221 if ((i->first).find(buf,0,n) == 0)
1222 commands.push_back(i->first);
1225 //=======================================================================
1229 //=======================================================================
1230 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1232 inline void PrintChar(char c) { write(STDOUT_FILENO,&c,1); }
1233 inline void BackSpace() { write(STDOUT_FILENO,"\b \b",3); }
1235 // LG : KEYBOARD CODES AS SCANNED ON MY TTY : UNIVERSAL ?
1236 // IF NOT THE USER SHOULD BE ABLE TO CONFIGURE IT
1237 // E.G. STORE THIS IN bbtk_config.xml
1238 #define BBTK_UP_ARROW_KBCODE 0x00415B1B
1239 #define BBTK_DOWN_ARROW_KBCODE 0x00425B1B
1240 #define BBTK_RIGHT_ARROW_KBCODE 0x00435B1B
1241 #define BBTK_LEFT_ARROW_KBCODE 0x00445B1B
1242 #define BBTK_BACKSPACE_KBCODE 0x00000008
1243 #define BBTK_DEL_KBCODE 0x0000007F
1244 #define BBTK_SPACE_KBCODE 0x00000020
1246 //=======================================================================
1247 void Interpreter::GetLineFromPrompt(std::string& s)
1252 int MAX_LINE_SIZE = 160;
1253 int MAX_HISTORY_SIZE = 100;
1255 char* newline = new char[MAX_LINE_SIZE];
1256 memset(newline,0,MAX_LINE_SIZE);
1257 char* histline = new char[MAX_LINE_SIZE];
1258 memset(histline,0,MAX_LINE_SIZE);
1260 char* line = newline;
1261 int hist = mHistory.size();
1268 read ( STDIN_FILENO, &c, 4) ;
1270 bbtkDebugMessage("Debug",9,"[0x"<<std::hex<<c<<"]\n");
1272 // Printable character
1273 if ( (ind<MAX_LINE_SIZE-1) &&
1274 ( c >= BBTK_SPACE_KBCODE ) &&
1275 ( c < BBTK_DEL_KBCODE ))
1283 // delete the unused line
1289 // empty lines are not stored in from history
1292 // if history too long : delete oldest command
1293 if (mHistory.size()>MAX_HISTORY_SIZE)
1295 delete mHistory.front();
1296 mHistory.pop_front();
1298 mHistory.push_back(line);
1303 else if ( (ind>0) &&
1304 ((c == BBTK_BACKSPACE_KBCODE) ||
1305 (c == BBTK_DEL_KBCODE)) )
1313 // TODO : Command completion
1314 std::vector<std::string> commands;
1315 FindCommandsWithPrefix( line,ind,commands);
1316 if (commands.size()==1)
1318 std::string com = *commands.begin();
1319 for (; ind<com.size(); ++ind)
1321 PrintChar(com[ind]);
1327 else if (commands.size()>1)
1329 std::vector<std::string>::iterator i;
1331 for (i=commands.begin();i!=commands.end();++i)
1333 write(STDOUT_FILENO,(*i).c_str(),strlen((*i).c_str()));
1336 write(STDOUT_FILENO,"\n> ",3);
1337 //for (int j=0;j<ind;++j)
1339 write(STDOUT_FILENO,line,ind);
1343 // Arrow up : back in history
1344 else if (c==BBTK_UP_ARROW_KBCODE)
1348 // erase current line
1349 while (ind--) BackSpace();
1353 strcpy(histline,mHistory[hist]);
1357 write(STDOUT_FILENO,line,ind);
1360 // Arrow down : down in history
1361 else if (c==BBTK_DOWN_ARROW_KBCODE)
1363 if (hist<mHistory.size()-1)
1365 // erase current line
1366 while (ind--) BackSpace();
1370 strcpy(histline,mHistory[hist]);
1374 write(STDOUT_FILENO,line,ind);
1376 // end of history : switch back to newline
1377 else if (hist==mHistory.size()-1)
1379 // erase current line
1380 while (ind--) BackSpace();
1387 write(STDOUT_FILENO,line,ind);
1391 else if (line[ind]!=0 && c==BBTK_RIGHT_ARROW_KBCODE)
1393 PrintChar(line[ind]);
1398 else if (ind>0 && c==BBTK_LEFT_ARROW_KBCODE)
1406 write(STDOUT_FILENO,"\n\r",2);
1414 //=======================================================================
1415 void Interpreter::GetLineFromPrompt(std::string& s)
1441 //=======================================================================
1447 //=======================================================================
1448 void Interpreter::CommandLineInterpreter()
1450 bbtkDebugMessageInc("Interpreter",9,
1451 "Interpreter::CommandLineInterpreter()"<<std::endl);
1453 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1454 // Initialise the tty in non canonical mode with no echo
1455 // oter remembers the previous settings to restore them after
1456 struct termios ter,oter;
1459 ter.c_lflag &= ~ECHO;
1460 ter.c_lflag &= ~ICANON;
1463 tcsetattr(0,TCSANOW,&ter);
1466 mCommandLine = true;
1468 bool insideComment = false; // for multiline comment
1474 GetLineFromPrompt(line);
1475 InterpretLine(line, insideComment);
1477 catch (QuitException e)
1481 catch (bbtk::Exception e)
1485 catch (std::exception& e)
1487 std::cerr << "* ERROR :: "<<e.what()<<" (not in bbtk)"<<std::endl;
1491 std::cerr << "* UNDEFINED ERROR (not a bbtk nor a std exception)"<<std::endl;
1496 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1497 tcsetattr(0,TCSANOW,&oter);
1500 std::cout << "Good bye !" << std::endl;
1502 bbtkDebugDecTab("Interpreter",9);
1505 //=======================================================================
1506 void Interpreter::Graph(const std::vector<std::string>& words)
1509 bool system_display = true;
1511 #ifdef _USE_WXWIDGETS_
1512 if ( WxConsole::GetInstance() != 0 ) system_display = false;
1515 if (words.size()==1)
1517 page = mExecuter->ShowGraph(".","0","0","","","",system_display);
1519 else if (words.size()==2)
1521 page = mExecuter->ShowGraph(words[1],"0","0","","","",system_display);
1523 else if (words.size()==3)
1525 page = mExecuter->ShowGraph(words[1],words[2],"0","","","",system_display);
1527 else if (words.size()==4)
1529 page = mExecuter->ShowGraph(words[1],words[2],words[3],"","","",system_display);
1531 else if (words.size()==5)
1533 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],"","",system_display);
1535 else if (words.size()==6)
1537 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],"",system_display);
1539 else if (words.size()==7)
1541 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],words[6],system_display);
1544 #ifdef _USE_WXWIDGETS_
1545 if ( WxConsole::GetInstance() != 0 )
1546 WxConsole::GetInstance()->ShowHtmlPage(page);
1549 //=======================================================================
1552 //=======================================================================
1553 void Interpreter::Index(const std::string& filename,
1554 const std::string& type)
1556 Factory::IndexEntryType t;
1557 if (type=="Initials") t = Factory::Initials;
1558 else if (type=="Categories") t = Factory::Categories;
1559 else if (type=="Packages") t = Factory::Packages;
1561 GetGlobalFactory()->CreateHtmlIndex(t,filename);
1563 //=======================================================================