1 /*=========================================================================
4 Module: $RCSfile: bbtkInterpreter.cxx,v $ $
6 Date: $Date: 2008/01/30 09:28:15 $
7 Version: $Revision: 1.15 $
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 = "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 [<verbose>|<v>]";
163 info.help = "Prints the value of all configuration parameters";
164 mCommandDict[info.keyword] = info;
166 info.keyword = "reset"; //EED
170 info.syntax = "reset";
171 info.help = "Deletes all boxes and unloads all packages (bbi is reset to its start state)";
172 mCommandDict[info.keyword] = info;
174 info.keyword = "author";
178 info.syntax = "author <string>";
179 info.help = "Adds the string <string> to the author information of the black box being defined";
180 mCommandDict[info.keyword] = info;
182 info.keyword = "keyword"; //JP
185 info.code = cKeyword;
186 info.syntax = "keyword <list of items, separated by ;>";
187 info.help = "Adds the string <string> to the keyword information of the black box being defined";
188 mCommandDict[info.keyword] = info;
190 info.keyword = "description";
193 info.code = cDescription;
194 info.syntax = "description <string>";
195 info.help = "Adds the string <string> to the descriptive information of the black box being defined";
196 mCommandDict[info.keyword] = info;
198 info.keyword = "help";
202 info.syntax = "help";
203 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>";
204 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.";
205 mCommandDict[info.keyword] = info;
207 info.keyword = "message";
210 info.code = cMessage;
211 info.syntax = "message <category> <level>";
212 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.";
213 mCommandDict[info.keyword] = info;
215 info.keyword = "include";
218 info.code = cInclude;
219 info.syntax = "include <filename>";
220 info.help = "Includes the file <filename>";
221 mCommandDict[info.keyword] = info;
223 info.keyword = "quit";
227 info.syntax = "quit";
228 info.help = "Quits the program (during script execution it stops the complete execution)";
229 mCommandDict[info.keyword] = info;
231 info.keyword = "load";
235 info.syntax = "load <packagename>";
236 info.help = "Loads the black box package <packagename>";
237 mCommandDict[info.keyword] = info;
239 info.keyword = "unload";
243 info.syntax = "unload <packagename>";
244 info.help = "Unloads the black box package <packagename>";
245 mCommandDict[info.keyword] = info;
247 info.keyword = "graph";
251 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 ]]]]]]";
252 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')";
253 mCommandDict[info.keyword] = info;
256 info.keyword = "workspace";
259 info.code = cWorkspace;
260 info.syntax = "workspace < ( freeze | unfreeze ) | ( rename <newname> ) >";
261 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.";
262 mCommandDict[info.keyword] = info;
265 bbtkDebugDecTab("Interpreter",9);
268 //=======================================================================
272 //=======================================================================
276 Interpreter::~Interpreter()
278 bbtkDebugMessageInc("Interpreter",9,"Interpreter::~Interpreter()" <<std::endl);
282 // std::cout <<"EO Interpreter::~Interpreter()"<<std::endl;
283 bbtkDebugDecTab("Interpreter",9);
285 //=======================================================================
288 //=======================================================================
292 void Interpreter::InterpretFile( const std::string& filename, bool use_configuration_file, bool verbose)
294 bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretFile(\""<<filename<<"\")"<<std::endl);
296 bool exm = mCommandLine;
297 mCommandLine = false;
301 SwitchToFile(filename, use_configuration_file, verbose);
302 bool insideComment = false; // for multiline comment
303 while (mFile.size()>0)
305 while ((mFile.size()>0) &&
306 (!mFile.back()->eof()))
310 mFile.back()->getline(buf,500);
312 std::string str(buf);
313 int size=str.length();
314 if ( str[ size-1 ]==13 )
319 InterpretLine(str, insideComment);
321 //if (mFile.size()>0)
325 catch (QuitException e)
328 catch (bbtk::Exception e)
330 std::cerr << "* ERROR : "<<e.GetMessage()<<std::endl;
331 if (mFileName.size()) {
332 std::cerr << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
333 std::cerr << "* LINE : "<<mLine.back()<<std::endl;
336 catch (std::exception& e)
338 std::cerr << "* ERROR : "<<e.what()<<" (not in bbtk)"<<std::endl;
339 if (mFileName.size()) {
340 std::cerr << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
341 std::cerr << "* LINE : "<<mLine.back()<<std::endl;
346 std::cout << "* UNDEFINED ERROR (not a bbtk nor a std exception)"<<std::endl;
347 if (mFileName.size()) {
348 std::cout << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
349 std::cout << "* LINE : "<<mLine.back()<<std::endl;
354 bbtkDebugMessage("Interpreter",9,"EO Interpreter::InterpretFile(\""<<filename<<"\")"<<std::endl);
355 bbtkDecTab("Interpreter",9);
359 //=======================================================================
363 //=======================================================================
367 void Interpreter::InterpretLine( const std::string& line, bool &insideComment )
370 bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretLine(\""<<line<<"\")"<<std::endl);
371 bbtkMessage("Echo",2,"\""<<line<<"\""<<std::endl);
373 std::vector<std::string> words;
374 SplitLine(line,words);
379 bbtkDebugDecTab("Interpreter",9);
383 // Single line comment : # or //
384 if ( words[0][0]=='#' || (words[0][0]=='/' && words[0][1]=='/') )
386 bbtkDebugDecTab("Interpreter",9);
387 bbtkMessage("Interpreter",9,"Comment"<<std::endl);
391 // Multi line comment ( /* ... */ ) -delimiters on different lines !-
393 if (words[0][0]=='/' && words[0][1]=='*')
395 bbtkDebugDecTab("Interpreter",9);
396 bbtkMessage("Interpreter",9,"In multiline comment"<<std::endl);
397 insideComment = true;
401 if (words[0][0]=='*' && words[0][1]=='/')
403 bbtkDebugDecTab("Interpreter",9);
404 bbtkMessage("Interpreter",9,"Out multiline comment"<<std::endl);
405 if ( !insideComment ) {
406 bbtkDebugDecTab("Interpreter",9);
407 bbtkMessage("Interpreter",9,"Comment mismatch : '*/' with no matching '/*'"<<std::endl);
409 insideComment = false;
415 bbtkDebugDecTab("Interpreter",9);
416 bbtkMessage("Interpreter",9,"Multiline Comment"<<std::endl);
421 CommandInfoType command;
422 InterpretCommand(words,command);
424 bbtkDebugMessage("Interpreter",9,
425 "Command='"<<command.keyword
426 <<"' code="<<command.code<<std::endl);
428 std::string left,right,left2,right2;
429 std::string filename;
430 switch (command.code)
433 mExecuter->Create(words[1],words[2]);
438 // mExecuter->Remove(words[1]);
442 Utilities::SplitAroundFirstDot(words[1],left,right);
443 Utilities::SplitAroundFirstDot(words[2],left2,right2);
444 mExecuter->Connect(left,right,left2,right2);
448 mExecuter->BeginPackage(words[1]);
452 mExecuter->EndPackage();
456 if (mFileName.size()>0)
458 filename = Utilities::get_file_name(mFileName.back());
462 mExecuter->Define(words[1],"",filename);
466 mExecuter->Define(words[1],words[2],filename);
471 mExecuter->EndDefine();
475 Print(words[1]); /// \todo use mExecuter
479 if (words[1]=="freeze")
480 mExecuter->SetNoExecMode(true);
481 else if (words[1]=="unfreeze")
482 mExecuter->SetNoExecMode(false);
484 mExecuter->Update(words[1]);
488 Utilities::SplitAroundFirstDot(words[2],left,right);
489 mExecuter->DefineInput(words[1],left,right,words[3]);
493 Utilities::SplitAroundFirstDot(words[2],left,right);
494 mExecuter->DefineOutput(words[1],left,right,words[3]);
498 Utilities::SplitAroundFirstDot(words[1],left,right);
499 mExecuter->Set(left,right,words[2]);
503 mExecuter->Author(words[1]);
507 mExecuter->Keyword(words[1]);
511 mExecuter->Description(words[1]);
521 bbtk::MessageManager::PrintInfo();
525 sscanf(words[2].c_str(),"%d",&level);
526 bbtk::MessageManager::SetMessageLevel(words[1],level);
535 if (words.size()>1) // any param for config means verbose = true
543 this->mExecuter->Reset();
549 InterpretFile(words[1], true, verbose); // true : better pass use_config_file
553 SwitchToFile(words[1], true, verbose); // true : better pass use_config_file
558 LoadPackage(words[1], true, verbose); // true : better pass use_config_file
562 UnLoadPackage(words[1]);
566 throw QuitException();
570 if (words.size() == 2)
572 if (words[1]=="freeze") mExecuter->SetNoExecMode(true);
573 else if (words[1]=="unfreeze") mExecuter->SetNoExecMode(false);
577 mExecuter->SetWorkspaceName(words[2]);
582 bbtkInternalError("should not reach here !!!");
585 bbtkDecTab("Interpreter",9);
587 //=======================================================================
591 //=======================================================================
592 void SplitString ( const std::string& str, const std::string& delimiters,
593 std::vector<std::string>& tokens)
595 // Skip delimiters at beginning.
596 std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
597 // Find first delimiter.
598 std::string::size_type pos = str.find_first_of(delimiters, lastPos);
600 while (std::string::npos != pos || std::string::npos != lastPos)
602 // Found a token, add it to the vector.
603 tokens.push_back(str.substr(lastPos, pos - lastPos));
604 // Skip delimiters. Note the "not_of"
605 lastPos = str.find_first_not_of(delimiters, pos);
606 // Find next delimiter
607 pos = str.find_first_of(delimiters, lastPos);
611 //=======================================================================
615 //=======================================================================
619 void Interpreter::SplitLine ( const std::string& str, std::vector<std::string>& tokens)
621 bbtkDebugMessageInc("Interpreter",9,"Interpreter::SplitLine(\""<<str<<"\")"<<std::endl);
623 std::string delimiters = "\"";
624 std::vector<std::string> quote;
625 SplitString(str,delimiters,quote);
628 std::vector<std::string>::iterator i;
629 for (i=quote.begin(); i!=quote.end(); )
631 SplitString(*i,delimiters,tokens);
635 // bbtkDebugMessage("Interpreter",0,"\""<<*i<<"\""<<std::endl);
636 tokens.push_back(*i);
641 for (i=tokens.begin(); i!=tokens.end(); ++i)
643 bbtkDebugMessage("Interpreter",9,"["<<*i<<"] ");
645 bbtkDebugMessageCont("Interpreter",9,std::endl);
647 bbtkDebugDecTab("Interpreter",9);
649 //=======================================================================
652 //=======================================================================
653 // Replaces substrings "\\n" by a real carriage return "\n"
654 void SubsBackslashN ( std::string& s )
656 // std::cout << "BEFORE=["<<s<<"]"<<std::endl;
657 std::string ss("\\n");
658 std::string::size_type pos = 0;
661 while ( pos != std::string::npos )
663 // std::cout << "*** find one "<<std::endl;
664 s.replace(pos,2,cr,1);
665 pos = s.find(ss, pos-1);
667 // std::cout << "AFTER=["<<s<<"]"<<std::endl;
669 //=======================================================================
672 //=======================================================================
676 void Interpreter::Print( const std::string& str)
678 if (mExecuter->GetNoExecMode()) return;
680 bbtkDebugMessageInc("Interpreter",9,"Interpreter::SplitLine(\""<<str<<"\")"<<std::endl);
682 std::vector<std::string> chains;
683 std::string delimiters("$");
685 // Skip delimiters at beginning.
686 std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
688 if (lastPos>0) is_text = false;
690 // Find first delimiter.
691 std::string::size_type pos = str.find_first_of(delimiters, lastPos);
693 while (std::string::npos != pos || std::string::npos != lastPos)
697 // Found a text token, add it to the vector.
698 chains.push_back(str.substr(lastPos, pos - lastPos));
699 // std::cout << "text='"<<chains.back()<<"'"<<std::endl;
703 // is an output (between $$) : decode
704 std::string tok,box,output;
705 tok = str.substr(lastPos, pos - lastPos);
706 Utilities::SplitAroundFirstDot(tok,box,output);
707 chains.push_back( mExecuter->Get(box,output) );
708 // std::cout << "outp='"<<chains.back()<<"'"<<std::endl;
710 // Skip delimiters. Note the "not_of"
711 lastPos = str.find_first_not_of(delimiters, pos);
712 // Find next delimiter
713 pos = str.find_first_of(delimiters, lastPos);
717 // std::cout << "nb="<<chains.size()<<std::endl;
718 std::vector<std::string>::iterator i;
719 for (i= chains.begin(); i!=chains.end(); ++i)
721 // bbtkMessage("Echo",1,*i);
725 std::cout << std::endl;
726 bbtkDebugDecTab("Interpreter",9);
729 //=======================================================================
734 // ===================================================================================
736 void Interpreter::SwitchToFile( const std::string& name,
737 bool use_configuration_file, bool verbose)
739 // Note : in the following :
740 // name : the user supplied name
741 // - abreviated name e.g. scr scr.bbs
742 // - relative full name e.g. ./scr.bbs ../../scr.bbs
743 // - absolute full name e.g. /home/usrname/proj/dir/scr.bbs
744 // same for Windows, with c:, d: ...
746 // expression like directory/subdir/scrname.bbs is FORBIDDEN (*)
747 // use ./directory/subdir/scrname.bbs
749 // (*) except when using packagename/boxes/*
751 bbtkDebugMessageInc("Interpreter",9,"Interpreter::SwitchToFile( \""
752 <<name<<"\")"<<std::endl);
754 // to be remove in final version
757 std::vector<std::string> script_paths;
758 std::string fullPathScriptName; // full path script name
759 std::string pkgname; // e.g. <scriptname>.bbs
761 if (use_configuration_file)
763 // The following is *NOT* a debug time message :
764 // It's a user intended message.
765 // Please don't remove it.
767 std::cout << "look for : [" << name << "] (use_configuration_file == TRUE)" << std::endl;
768 script_paths = ConfigurationFile::GetInstance().Get_bbs_paths();
771 pkgname = Utilities::ExtractScriptName(name,upath);
773 bool fullnameGiven = false;
774 bool foundFile = false;
776 if(pkgname == "*") // =========================================== load all boxes (e.g. std/boxes/*)
779 std::vector<std::string>::iterator i;
780 std::string fullDirectoryName;
781 for (i=script_paths.begin();i!=script_paths.end();++i)
785 // we *really* want '.' to be the current working directory
787 char buf[2048]; // for getcwd
788 char * currentDir = getcwd(buf, 2048);
789 std::string cwd(currentDir);
793 fullDirectoryName = Utilities::MakePkgnameFromPath(path, upath, false);
794 //std::cout <<"fullpath [" << fullDirectoryName << "]" <<std::endl;
795 // Check if library exists
796 if ( ! Utilities::IsDirectory(fullDirectoryName) )
798 // The following is *NOT* a debug time message :
799 // It's a user intended message.
800 // Please don't remove it.
802 std::cout <<" [" <<fullDirectoryName <<"] : doesn't exist" <<std::endl;
803 continue; // try next path
807 std::vector<std::string> Filenames;
808 int nbFiles = Utilities::Explore(fullDirectoryName, false, Filenames);
809 // std::cout << "=================nbFiles " << nbFiles << std::endl;
811 for (std::vector<std::string>::iterator i = Filenames.begin(); i!= Filenames.end(); ++i)
813 if ((*i).substr((*i).size()-4, 4) != ".bbs")
814 continue; // ignore non .bbs files
820 std::cout << "WARNING : No '.bbs' file found in [" << fullDirectoryName << "]" << std::endl;
822 break; // a directory was found; we stop iterating
827 std::string::size_type slash_position = name.find_last_of("/\\");
829 // if name starts with a / or a . or contains : user is assumed to have passed a relative/absolute name
830 // (not only a plain script name)
831 // we trust him, and try to expland the directory name
832 // WARNING : starting from current local directory : ./whatYouWant (./ mandatory!)
834 if (name[0]=='/' || name[1] == ':' || name[0]=='.') // absolute path (linux/windows) or relative path
837 // ===========================================================check user supplied location
838 fullnameGiven = true;
840 fullPathScriptName = Utilities::ExpandLibName(name, verbose);
842 // allow user to always forget ".bbs"
843 int l = fullPathScriptName.size();
849 if (fullPathScriptName.substr(l-4, 4) != ".bbs")
851 fullPathScriptName = fullPathScriptName + ".bbs";
856 fullPathScriptName = fullPathScriptName + ".bbs";
859 if ( Utilities::FileExists(fullPathScriptName))
867 // =============================================================== iterate on the paths
870 std::vector<std::string>::iterator i;
871 for (i=script_paths.begin();i!=script_paths.end();++i)
875 // we *really* want '.' to be the current working directory
877 char buf[2048]; // for getcwd
878 char * currentDir = getcwd(buf, 2048);
879 std::string cwd(currentDir);
883 // fullPathScriptName = Utilities::MakePkgnameFromPath(path, name, true); //pkgname);
885 fullPathScriptName = Utilities::MakePkgnameFromPath(path, name, true);
886 //std::cout << "FULL PATH = "<<fullPathScriptName<<std::endl;
888 // Check if library exists
889 if ( ! Utilities::FileExists(fullPathScriptName) )
891 // The following is *NOT* a debug time message :
892 // It's a user intended message.
893 // Please don't remove it.
895 std::cout <<" [" <<fullPathScriptName <<"] : doesn't exist" <<std::endl;
896 continue; // try next path
899 std::cout <<" [" <<fullPathScriptName <<"] : found" <<std::endl;
901 break; // a script was found; we stop iterating
903 } //------------------ // end for ( package_paths.begin();i!=package_paths.end() )
909 if(fullPathScriptName == "")
910 bbtkError("Path ["<<upath<<"] doesn't exist");
912 bbtkError("Script ["<<fullPathScriptName<<"] not found");
914 bbtkError("No ["<<pkgname<<".bbs] script found");
918 LoadScript(fullPathScriptName);
924 //=======================================================================
926 void Interpreter::LoadScript( std::string fullPathScriptName)
928 bbtkMessage("Interpreter",1,fullPathScriptName<<" found"<<std::endl);
931 s = new std::ifstream;
932 s->open(fullPathScriptName.c_str());
935 bbtkError("Could not open file ["<<fullPathScriptName<<"]");
940 std::cout << " -->[" << fullPathScriptName << "] found" << std::endl;
943 mFileName.push_back(fullPathScriptName);
948 //=======================================================================
952 void Interpreter::CloseCurrentFile()
954 bbtkDebugMessage("Interpreter",9,"Interpreter::CloseCurrentFile()"
959 bbtkDebugMessage("Interpreter",9," -> no file left open"<<std::endl);
963 mFile.back()->close();
966 bbtkDebugMessage("Interpreter",9,
967 " Closing file '"<<mFileName.back()<<"'"<<std::endl);
969 mFileName.pop_back();
971 bbtkDebugMessage("Interpreter",9," Remains "
973 <<" open"<<std::endl);
974 bbtkDebugMessage("Interpreter",9,"EO Interpreter::CloseCurrentFile()"
977 //=======================================================================
979 //=======================================================================
983 void Interpreter::CloseAllFiles()
985 bbtkDebugMessage("Interpreter",9,"Interpreter::CloseAllFiles()"
988 while (mFile.size() != 0)
990 mFile.back()->close();
993 bbtkDebugMessage("Interpreter",9,
994 " Closing file '"<<mFileName.back()<<"'"<<std::endl);
995 mFileName.pop_back();
998 bbtkDebugMessage("Interpreter",9,"EO Interpreter::CloseAllFiles()"
1001 //=======================================================================
1005 //=======================================================================
1009 void Interpreter::InterpretCommand( const std::vector<std::string>& words,
1010 CommandInfoType& info )
1012 bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretCommand(...)"<<std::endl);
1014 // searches the command keyword
1015 CommandDictType::iterator c;
1016 c = mCommandDict.find(words[0]);
1017 if ( c == mCommandDict.end() ) {
1018 bbtkError(words[0]<<" : unknown command");
1021 // tests the number of args
1022 if ( ( words.size()-1 < c->second.argmin ) ||
1023 ( words.size()-1 > c->second.argmax ) )
1025 HelpCommand(words[0]);
1026 bbtkError(words[0]<<" : wrong number of arguments");
1030 bbtkDecTab("Interpreter",9);
1032 //=======================================================================
1035 //=======================================================================
1036 /// Displays help on all the commands
1037 void Interpreter::Help(const std::vector<std::string>& words)
1039 unsigned int nbarg = words.size()-1;
1047 if (words[1]=="packages")
1049 PrintPackages(true);
1054 HelpCommand(words[1]);
1056 catch (bbtk::Exception e)
1060 HelpPackage(words[1]);
1062 catch (bbtk::Exception f)
1066 HelpBlackBox(words[1]);
1068 catch (bbtk::Exception g)
1072 this->mExecuter->ShowRelations(words[1],"0","9999");
1074 catch (bbtk::Exception h){
1075 bbtkError("\""<<words[1].c_str()
1076 <<"\" is not a known command, package, black box type or black box name");
1084 if (words[2]=="all")
1086 if ( words[1]=="packages" )
1088 PrintPackages(true,true);
1093 HelpPackage(words[1],true);
1095 catch (bbtk::Exception f)
1101 HelpCommand(words[0]);
1102 bbtkError(words[0]<<" : syntax error");
1107 bbtkError("Should not reach here !!!");
1110 //=======================================================================
1112 //===================================================================
1113 /// Displays the Configuration
1114 void Interpreter::Config( bool verbose ) const
1116 bbtkDebugMessageInc("Core",9,"Factory::Config"<<std::endl);
1118 ConfigurationFile cf = ConfigurationFile::GetInstance();
1120 const std::string config_xml_full_path = cf.Get_config_xml_full_path();
1121 const std::string description = cf.Get_description();
1122 const std::string url = cf.Get_url();
1123 const std::string data_path = cf.Get_data_path();
1124 const std::string default_doc_tmp = cf.Get_default_doc_tmp();
1125 const std::string file_separator = cf.Get_file_separator();
1126 const std::vector<std::string>bbs_paths = cf.Get_bbs_paths();
1127 const std::vector<std::string>package_paths = cf.Get_package_paths();
1129 bbtkMessage("Help",1, "=============" << std::endl);
1130 bbtkMessage("Help",1, "Configuration" << std::endl);
1131 bbtkMessage("Help",1, "=============" << std::endl);
1132 bbtkMessage("Help",1, "bbtk_config.xml : [" << config_xml_full_path << "]" << std::endl);
1133 bbtkMessage("Help",1, "Documentation Url : [" << url << "]" << std::endl);
1134 bbtkMessage("Help",1, "Data Path : [" << data_path << "]" << std::endl);
1135 bbtkMessage("Help",1, "Default Doc_tmp : [" << default_doc_tmp << "]" << std::endl);
1136 bbtkMessage("Help",1, "File Separator : [" << file_separator << "]" << std::endl);
1138 std::vector<std::string>::const_iterator i;
1140 bbtkMessage("Help",1, "BBS Paths " << std::endl);
1141 for (i = bbs_paths.begin(); i!=bbs_paths.end(); ++i )
1143 bbtkMessage("Help",1,"--- ["<<*i<<"]"<<std::endl);
1146 bbtkMessage("Help",1, "PACKAGE Paths : " << std::endl);
1147 for (i = package_paths.begin(); i!=package_paths.end(); ++i )
1149 bbtkMessage("Help",1,"--- ["<<*i<<"]"<<std::endl);
1152 bbtkDebugDecTab("Core",9);
1155 //=======================================================================
1156 /// Displays help on all the commands
1157 void Interpreter::HelpCommands()
1159 std::cout << "Available commands :" << std::endl;
1160 CommandDictType::iterator i;
1161 for ( i = mCommandDict.begin();
1162 i != mCommandDict.end();
1164 std::cout << " " << i->first << std::endl;
1165 // std::cout << " usage : " << i->second.syntax << std::endl;
1166 // std::cout << " " << i->second.help << std::endl;
1170 //=======================================================================
1173 //=======================================================================
1174 /// Displays help on a particular commands
1175 void Interpreter::HelpCommand(const std::string& s)
1177 CommandDictType::iterator c;
1178 c = mCommandDict.find(s);
1179 if ( c == mCommandDict.end() ) {
1180 bbtkError(s<<" : Unknown command");
1182 // std::cout << " " << s << " : "<< std::endl;
1183 // CommandParamDictType::iterator i;
1184 // for ( i = c->second.begin();
1185 // i != c->second.end();
1187 std::cout << " usage : " << c->second.syntax << std::endl;
1188 std::cout << " " << c->second.help << std::endl;
1191 //=======================================================================
1194 //=======================================================================
1195 /// Fills the vector commands with the commands which
1196 /// have the first n chars of buf for prefix
1197 /// TODO : skip initial spaces in buf and also return the position of first
1198 /// non blank char in buf
1199 void Interpreter::FindCommandsWithPrefix( char* buf,
1201 std::vector<std::string>& commands )
1203 CommandDictType::const_iterator i;
1204 for (i=mCommandDict.begin(); i!=mCommandDict.end(); ++i)
1206 if ((i->first).find(buf,0,n) == 0)
1207 commands.push_back(i->first);
1210 //=======================================================================
1214 //=======================================================================
1215 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1217 inline void PrintChar(char c) { write(STDOUT_FILENO,&c,1); }
1218 inline void BackSpace() { write(STDOUT_FILENO,"\b \b",3); }
1220 // LG : KEYBOARD CODES AS SCANNED ON MY TTY : UNIVERSAL ?
1221 // IF NOT THE USER SHOULD BE ABLE TO CONFIGURE IT
1222 // E.G. STORE THIS IN bbtk_config.xml
1223 #define BBTK_UP_ARROW_KBCODE 0x00415B1B
1224 #define BBTK_DOWN_ARROW_KBCODE 0x00425B1B
1225 #define BBTK_RIGHT_ARROW_KBCODE 0x00435B1B
1226 #define BBTK_LEFT_ARROW_KBCODE 0x00445B1B
1227 #define BBTK_BACKSPACE_KBCODE 0x00000008
1228 #define BBTK_DEL_KBCODE 0x0000007F
1229 #define BBTK_SPACE_KBCODE 0x00000020
1231 //=======================================================================
1232 void Interpreter::GetLineFromPrompt(std::string& s)
1237 int MAX_LINE_SIZE = 160;
1238 int MAX_HISTORY_SIZE = 100;
1240 char* newline = new char[MAX_LINE_SIZE];
1241 memset(newline,0,MAX_LINE_SIZE);
1242 char* histline = new char[MAX_LINE_SIZE];
1243 memset(histline,0,MAX_LINE_SIZE);
1245 char* line = newline;
1246 int hist = mHistory.size();
1253 read ( STDIN_FILENO, &c, 4) ;
1255 bbtkDebugMessage("Debug",9,"[0x"<<std::hex<<c<<"]\n");
1257 // Printable character
1258 if ( (ind<MAX_LINE_SIZE-1) &&
1259 ( c >= BBTK_SPACE_KBCODE ) &&
1260 ( c < BBTK_DEL_KBCODE ))
1268 // delete the unused line
1274 // empty lines are not stored in from history
1277 // if history too long : delete oldest command
1278 if (mHistory.size()>MAX_HISTORY_SIZE)
1280 delete mHistory.front();
1281 mHistory.pop_front();
1283 mHistory.push_back(line);
1288 else if ( (ind>0) &&
1289 ((c == BBTK_BACKSPACE_KBCODE) ||
1290 (c == BBTK_DEL_KBCODE)) )
1298 // TODO : Command completion
1299 std::vector<std::string> commands;
1300 FindCommandsWithPrefix( line,ind,commands);
1301 if (commands.size()==1)
1303 std::string com = *commands.begin();
1304 for (; ind<com.size(); ++ind)
1306 PrintChar(com[ind]);
1312 else if (commands.size()>1)
1314 std::vector<std::string>::iterator i;
1316 for (i=commands.begin();i!=commands.end();++i)
1318 write(STDOUT_FILENO,(*i).c_str(),strlen((*i).c_str()));
1321 write(STDOUT_FILENO,"\n> ",3);
1322 //for (int j=0;j<ind;++j)
1324 write(STDOUT_FILENO,line,ind);
1328 // Arrow up : back in history
1329 else if (c==BBTK_UP_ARROW_KBCODE)
1333 // erase current line
1334 while (ind--) BackSpace();
1338 strcpy(histline,mHistory[hist]);
1342 write(STDOUT_FILENO,line,ind);
1345 // Arrow down : down in history
1346 else if (c==BBTK_DOWN_ARROW_KBCODE)
1348 if (hist<mHistory.size()-1)
1350 // erase current line
1351 while (ind--) BackSpace();
1355 strcpy(histline,mHistory[hist]);
1359 write(STDOUT_FILENO,line,ind);
1361 // end of history : switch back to newline
1362 else if (hist==mHistory.size()-1)
1364 // erase current line
1365 while (ind--) BackSpace();
1372 write(STDOUT_FILENO,line,ind);
1376 else if (line[ind]!=0 && c==BBTK_RIGHT_ARROW_KBCODE)
1378 PrintChar(line[ind]);
1383 else if (ind>0 && c==BBTK_LEFT_ARROW_KBCODE)
1391 write(STDOUT_FILENO,"\n\r",2);
1399 //=======================================================================
1400 void Interpreter::GetLineFromPrompt(std::string& s)
1426 //=======================================================================
1432 //=======================================================================
1433 void Interpreter::CommandLineInterpreter()
1435 bbtkDebugMessageInc("Interpreter",9,
1436 "Interpreter::CommandLineInterpreter()"<<std::endl);
1438 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1439 // Initialise the tty in non canonical mode with no echo
1440 // oter remembers the previous settings to restore them after
1441 struct termios ter,oter;
1444 ter.c_lflag &= ~ECHO;
1445 ter.c_lflag &= ~ICANON;
1448 tcsetattr(0,TCSANOW,&ter);
1451 mCommandLine = true;
1453 bool insideComment = false; // for multiline comment
1459 GetLineFromPrompt(line);
1460 InterpretLine(line, insideComment);
1462 catch (QuitException e)
1466 catch (bbtk::Exception e)
1470 catch (std::exception& e)
1472 std::cerr << "* ERROR :: "<<e.what()<<" (not in bbtk)"<<std::endl;
1476 std::cerr << "* UNDEFINED ERROR (not a bbtk nor a std exception)"<<std::endl;
1481 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1482 tcsetattr(0,TCSANOW,&oter);
1485 std::cout << "Good bye !" << std::endl;
1487 bbtkDebugDecTab("Interpreter",9);
1490 //=======================================================================
1491 void Interpreter::Graph(const std::vector<std::string>& words)
1494 bool system_display = true;
1496 #ifdef _USE_WXWIDGETS_
1497 if ( WxConsole::GetInstance() != 0 ) system_display = false;
1500 if (words.size()==1)
1502 page = mExecuter->ShowGraph(".","0","0","","","",system_display);
1504 else if (words.size()==2)
1506 page = mExecuter->ShowGraph(words[1],"0","0","","","",system_display);
1508 else if (words.size()==3)
1510 page = mExecuter->ShowGraph(words[1],words[2],"0","","","",system_display);
1512 else if (words.size()==4)
1514 page = mExecuter->ShowGraph(words[1],words[2],words[3],"","","",system_display);
1516 else if (words.size()==5)
1518 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],"","",system_display);
1520 else if (words.size()==6)
1522 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],"",system_display);
1524 else if (words.size()==7)
1526 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],words[6],system_display);
1529 #ifdef _USE_WXWIDGETS_
1530 if ( WxConsole::GetInstance() != 0 )
1531 WxConsole::GetInstance()->ShowHtmlPage(page);
1534 //=======================================================================