1 /*=========================================================================
4 Module: $RCSfile: bbtkInterpreter.cxx,v $ $
6 Date: $Date: 2008/02/01 13:06:29 $
7 Version: $Revision: 1.17 $
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 // use ./directory/subdir/scrname.bbs
749 bbtkDebugMessageInc("Interpreter",9,"Interpreter::SwitchToFile( \""
750 <<name<<"\")"<<std::endl);
752 // to be removed in final version
755 std::vector<std::string> script_paths;
756 std::string fullPathScriptName; // full path script name
757 std::string pkgname; // e.g. <scriptname>.bbs
758 std::vector<std::string> Filenames;
760 if (use_configuration_file)
762 // The following is *NOT* a debug time message :
763 // It's a user intended message.
764 // Please don't remove it.
766 std::cout << "look for : [" << name << "] (use_configuration_file == TRUE)" << std::endl;
767 script_paths = ConfigurationFile::GetInstance().Get_bbs_paths();
770 pkgname = Utilities::ExtractScriptName(name,upath);
771 //std::cout <<"name [" << name << "] pkgname [" << pkgname << "] upath [" << upath << "]" << std::endl;
772 bool fullnameGiven = false;
773 bool foundFile = false;
775 if(pkgname == "*") // =========================================== load all boxes (e.g. std/boxes/*)
779 if (upath[0]=='/' || upath[1] == ':' ) // ==== absolute name, load all .bbs files
781 int nbFiles = Utilities::Explore(upath, false, Filenames);
783 for (std::vector<std::string>::iterator i = Filenames.begin(); i!= Filenames.end(); ++i)
785 if ((*i).substr((*i).size()-4, 4) != ".bbs")
786 continue; // ignore non .bbs files
792 std::cout << "WARNING : No '.bbs' file found in [" << upath << "]" << std::endl;
799 std::vector<std::string>::iterator i;
800 std::string fullDirectoryName;
801 for (i=script_paths.begin();i!=script_paths.end();++i)// ==== relative name, iterate + load all .bbs files
805 // we *really* want '.' to be the current working directory
807 char buf[2048]; // for getcwd
808 char * currentDir = getcwd(buf, 2048);
809 std::string cwd(currentDir);
813 fullDirectoryName = Utilities::MakePkgnameFromPath(path, upath, false);
814 //std::cout <<"fullpath [" << fullDirectoryName << "]" <<std::endl;
815 // Check if library exists
816 if ( ! Utilities::IsDirectory(fullDirectoryName) )
818 // The following is *NOT* a debug time message :
819 // It's a user intended message.
820 // Please don't remove it.
822 std::cout <<" [" <<fullDirectoryName <<"] : doesn't exist" <<std::endl;
823 continue; // try next path
828 int nbFiles = Utilities::Explore(fullDirectoryName, false, Filenames);
829 // std::cout << "=================nbFiles " << nbFiles << std::endl;
831 for (std::vector<std::string>::iterator i = Filenames.begin(); i!= Filenames.end(); ++i)
833 if ((*i).substr((*i).size()-4, 4) != ".bbs")
834 continue; // ignore non .bbs files
840 std::cout << "WARNING : No '.bbs' file found in [" << fullDirectoryName << "]" << std::endl;
842 break; // a directory was found; we stop iterating
847 //std::string::size_type slash_position = name.find_last_of("/\\");
849 // if name starts with a / or a . or contains : user is assumed to have passed a relative/absolute name
850 // (not only a plain script name)
851 // we trust him, and try to expland the directory name
852 // WARNING : starting from current local directory : ./whatYouWant (./ mandatory!)
854 if (name[0]=='/' || name[1] == ':' || name[0]=='.') // absolute path (linux/windows) or relative path
857 // ===========================================================check user supplied location
858 fullnameGiven = true;
860 fullPathScriptName = Utilities::ExpandLibName(name, verbose);
862 // allow user to always forget ".bbs"
863 int l = fullPathScriptName.size();
869 if (fullPathScriptName.substr(l-4, 4) != ".bbs")
871 fullPathScriptName = fullPathScriptName + ".bbs";
876 fullPathScriptName = fullPathScriptName + ".bbs";
879 if ( Utilities::FileExists(fullPathScriptName))
887 // =============================================================== iterate on the paths
890 std::vector<std::string>::iterator i;
891 for (i=script_paths.begin();i!=script_paths.end();++i)
895 // we *really* want '.' to be the current working directory
897 char buf[2048]; // for getcwd
898 char * currentDir = getcwd(buf, 2048);
899 std::string cwd(currentDir);
903 // fullPathScriptName = Utilities::MakePkgnameFromPath(path, name, true); //pkgname);
905 fullPathScriptName = Utilities::MakePkgnameFromPath(path, name, true);
906 //std::cout << "FULL PATH = "<<fullPathScriptName<<std::endl;
908 // Check if library exists
909 if ( ! Utilities::FileExists(fullPathScriptName) )
911 // The following is *NOT* a debug time message :
912 // It's a user intended message.
913 // Please don't remove it.
915 std::cout <<" [" <<fullPathScriptName <<"] : doesn't exist" <<std::endl;
916 continue; // try next path
919 std::cout <<" [" <<fullPathScriptName <<"] : found" <<std::endl;
921 break; // a script was found; we stop iterating
923 } //------------------ // end for ( package_paths.begin();i!=package_paths.end() )
929 if(fullPathScriptName == "")
930 bbtkError("Path ["<<upath<<"] doesn't exist");
932 bbtkError("Script ["<<fullPathScriptName<<"] not found");
934 bbtkError("No ["<<pkgname<<".bbs] script found");
938 LoadScript(fullPathScriptName);
944 //=======================================================================
946 void Interpreter::LoadScript( std::string fullPathScriptName)
948 bbtkMessage("Interpreter",1,fullPathScriptName<<" found"<<std::endl);
951 s = new std::ifstream;
952 s->open(fullPathScriptName.c_str());
955 bbtkError("Could not open file ["<<fullPathScriptName<<"]");
960 std::cout << " -->[" << fullPathScriptName << "] found" << std::endl;
963 mFileName.push_back(fullPathScriptName);
968 //=======================================================================
972 void Interpreter::CloseCurrentFile()
974 bbtkDebugMessage("Interpreter",9,"Interpreter::CloseCurrentFile()"
979 bbtkDebugMessage("Interpreter",9," -> no file left open"<<std::endl);
983 mFile.back()->close();
986 bbtkDebugMessage("Interpreter",9,
987 " Closing file '"<<mFileName.back()<<"'"<<std::endl);
989 mFileName.pop_back();
991 bbtkDebugMessage("Interpreter",9," Remains "
993 <<" open"<<std::endl);
994 bbtkDebugMessage("Interpreter",9,"EO Interpreter::CloseCurrentFile()"
997 //=======================================================================
999 //=======================================================================
1003 void Interpreter::CloseAllFiles()
1005 bbtkDebugMessage("Interpreter",9,"Interpreter::CloseAllFiles()"
1008 while (mFile.size() != 0)
1010 mFile.back()->close();
1011 delete mFile.back();
1013 bbtkDebugMessage("Interpreter",9,
1014 " Closing file '"<<mFileName.back()<<"'"<<std::endl);
1015 mFileName.pop_back();
1018 bbtkDebugMessage("Interpreter",9,"EO Interpreter::CloseAllFiles()"
1021 //=======================================================================
1025 //=======================================================================
1029 void Interpreter::InterpretCommand( const std::vector<std::string>& words,
1030 CommandInfoType& info )
1032 bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretCommand(...)"<<std::endl);
1034 // searches the command keyword
1035 CommandDictType::iterator c;
1036 c = mCommandDict.find(words[0]);
1037 if ( c == mCommandDict.end() ) {
1038 bbtkError(words[0]<<" : unknown command");
1041 // tests the number of args
1042 if ( ( words.size()-1 < c->second.argmin ) ||
1043 ( words.size()-1 > c->second.argmax ) )
1045 HelpCommand(words[0]);
1046 bbtkError(words[0]<<" : wrong number of arguments");
1050 bbtkDecTab("Interpreter",9);
1052 //=======================================================================
1055 //=======================================================================
1056 /// Displays help on all the commands
1057 void Interpreter::Help(const std::vector<std::string>& words)
1059 unsigned int nbarg = words.size()-1;
1067 if (words[1]=="packages")
1069 PrintPackages(true);
1074 HelpCommand(words[1]);
1076 catch (bbtk::Exception e)
1080 HelpPackage(words[1]);
1082 catch (bbtk::Exception f)
1086 HelpBlackBox(words[1]);
1088 catch (bbtk::Exception g)
1092 this->mExecuter->ShowRelations(words[1],"0","9999");
1094 catch (bbtk::Exception h){
1095 bbtkError("\""<<words[1].c_str()
1096 <<"\" is not a known command, package, black box type or black box name");
1104 if (words[2]=="all")
1106 if ( words[1]=="packages" )
1108 PrintPackages(true,true);
1113 HelpPackage(words[1],true);
1115 catch (bbtk::Exception f)
1121 HelpCommand(words[0]);
1122 bbtkError(words[0]<<" : syntax error");
1127 bbtkError("Should not reach here !!!");
1130 //=======================================================================
1132 //===================================================================
1133 /// Displays the Configuration
1134 void Interpreter::Config( bool verbose ) const
1136 bbtkDebugMessageInc("Core",9,"Factory::Config"<<std::endl);
1138 ConfigurationFile cf = ConfigurationFile::GetInstance();
1140 const std::string config_xml_full_path = cf.Get_config_xml_full_path();
1141 const std::string description = cf.Get_description();
1142 const std::string url = cf.Get_url();
1143 const std::string data_path = cf.Get_data_path();
1144 const std::string default_doc_tmp = cf.Get_default_doc_tmp();
1145 const std::string file_separator = cf.Get_file_separator();
1146 const std::vector<std::string>bbs_paths = cf.Get_bbs_paths();
1147 const std::vector<std::string>package_paths = cf.Get_package_paths();
1149 bbtkMessage("Help",1, "=============" << std::endl);
1150 bbtkMessage("Help",1, "Configuration" << std::endl);
1151 bbtkMessage("Help",1, "=============" << std::endl);
1152 bbtkMessage("Help",1, "bbtk_config.xml : [" << config_xml_full_path << "]" << std::endl);
1153 bbtkMessage("Help",1, "Documentation Url : [" << url << "]" << std::endl);
1154 bbtkMessage("Help",1, "Data Path : [" << data_path << "]" << std::endl);
1155 bbtkMessage("Help",1, "Default Doc_tmp : [" << default_doc_tmp << "]" << std::endl);
1156 bbtkMessage("Help",1, "File Separator : [" << file_separator << "]" << std::endl);
1158 std::vector<std::string>::const_iterator i;
1160 bbtkMessage("Help",1, "BBS Paths " << std::endl);
1161 for (i = bbs_paths.begin(); i!=bbs_paths.end(); ++i )
1163 bbtkMessage("Help",1,"--- ["<<*i<<"]"<<std::endl);
1166 bbtkMessage("Help",1, "PACKAGE Paths : " << std::endl);
1167 for (i = package_paths.begin(); i!=package_paths.end(); ++i )
1169 bbtkMessage("Help",1,"--- ["<<*i<<"]"<<std::endl);
1172 bbtkDebugDecTab("Core",9);
1175 //=======================================================================
1176 /// Displays help on all the commands
1177 void Interpreter::HelpCommands()
1179 std::cout << "Available commands :" << std::endl;
1180 CommandDictType::iterator i;
1181 for ( i = mCommandDict.begin();
1182 i != mCommandDict.end();
1184 std::cout << " " << i->first << std::endl;
1185 // std::cout << " usage : " << i->second.syntax << std::endl;
1186 // std::cout << " " << i->second.help << std::endl;
1190 //=======================================================================
1193 //=======================================================================
1194 /// Displays help on a particular commands
1195 void Interpreter::HelpCommand(const std::string& s)
1197 CommandDictType::iterator c;
1198 c = mCommandDict.find(s);
1199 if ( c == mCommandDict.end() ) {
1200 bbtkError(s<<" : Unknown command");
1202 // std::cout << " " << s << " : "<< std::endl;
1203 // CommandParamDictType::iterator i;
1204 // for ( i = c->second.begin();
1205 // i != c->second.end();
1207 std::cout << " usage : " << c->second.syntax << std::endl;
1208 std::cout << " " << c->second.help << std::endl;
1211 //=======================================================================
1214 //=======================================================================
1215 /// Fills the vector commands with the commands which
1216 /// have the first n chars of buf for prefix
1217 /// TODO : skip initial spaces in buf and also return the position of first
1218 /// non blank char in buf
1219 void Interpreter::FindCommandsWithPrefix( char* buf,
1221 std::vector<std::string>& commands )
1223 CommandDictType::const_iterator i;
1224 for (i=mCommandDict.begin(); i!=mCommandDict.end(); ++i)
1226 if ((i->first).find(buf,0,n) == 0)
1227 commands.push_back(i->first);
1230 //=======================================================================
1234 //=======================================================================
1235 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1237 inline void PrintChar(char c) { write(STDOUT_FILENO,&c,1); }
1238 inline void BackSpace() { write(STDOUT_FILENO,"\b \b",3); }
1240 // LG : KEYBOARD CODES AS SCANNED ON MY TTY : UNIVERSAL ?
1241 // IF NOT THE USER SHOULD BE ABLE TO CONFIGURE IT
1242 // E.G. STORE THIS IN bbtk_config.xml
1243 #define BBTK_UP_ARROW_KBCODE 0x00415B1B
1244 #define BBTK_DOWN_ARROW_KBCODE 0x00425B1B
1245 #define BBTK_RIGHT_ARROW_KBCODE 0x00435B1B
1246 #define BBTK_LEFT_ARROW_KBCODE 0x00445B1B
1247 #define BBTK_BACKSPACE_KBCODE 0x00000008
1248 #define BBTK_DEL_KBCODE 0x0000007F
1249 #define BBTK_SPACE_KBCODE 0x00000020
1251 //=======================================================================
1252 void Interpreter::GetLineFromPrompt(std::string& s)
1257 int MAX_LINE_SIZE = 160;
1258 int MAX_HISTORY_SIZE = 100;
1260 char* newline = new char[MAX_LINE_SIZE];
1261 memset(newline,0,MAX_LINE_SIZE);
1262 char* histline = new char[MAX_LINE_SIZE];
1263 memset(histline,0,MAX_LINE_SIZE);
1265 char* line = newline;
1266 int hist = mHistory.size();
1273 read ( STDIN_FILENO, &c, 4) ;
1275 bbtkDebugMessage("Debug",9,"[0x"<<std::hex<<c<<"]\n");
1277 // Printable character
1278 if ( (ind<MAX_LINE_SIZE-1) &&
1279 ( c >= BBTK_SPACE_KBCODE ) &&
1280 ( c < BBTK_DEL_KBCODE ))
1288 // delete the unused line
1294 // empty lines are not stored in from history
1297 // if history too long : delete oldest command
1298 if (mHistory.size()>MAX_HISTORY_SIZE)
1300 delete mHistory.front();
1301 mHistory.pop_front();
1303 mHistory.push_back(line);
1308 else if ( (ind>0) &&
1309 ((c == BBTK_BACKSPACE_KBCODE) ||
1310 (c == BBTK_DEL_KBCODE)) )
1318 // TODO : Command completion
1319 std::vector<std::string> commands;
1320 FindCommandsWithPrefix( line,ind,commands);
1321 if (commands.size()==1)
1323 std::string com = *commands.begin();
1324 for (; ind<com.size(); ++ind)
1326 PrintChar(com[ind]);
1332 else if (commands.size()>1)
1334 std::vector<std::string>::iterator i;
1336 for (i=commands.begin();i!=commands.end();++i)
1338 write(STDOUT_FILENO,(*i).c_str(),strlen((*i).c_str()));
1341 write(STDOUT_FILENO,"\n> ",3);
1342 //for (int j=0;j<ind;++j)
1344 write(STDOUT_FILENO,line,ind);
1348 // Arrow up : back in history
1349 else if (c==BBTK_UP_ARROW_KBCODE)
1353 // erase current line
1354 while (ind--) BackSpace();
1358 strcpy(histline,mHistory[hist]);
1362 write(STDOUT_FILENO,line,ind);
1365 // Arrow down : down in history
1366 else if (c==BBTK_DOWN_ARROW_KBCODE)
1368 if (hist<mHistory.size()-1)
1370 // erase current line
1371 while (ind--) BackSpace();
1375 strcpy(histline,mHistory[hist]);
1379 write(STDOUT_FILENO,line,ind);
1381 // end of history : switch back to newline
1382 else if (hist==mHistory.size()-1)
1384 // erase current line
1385 while (ind--) BackSpace();
1392 write(STDOUT_FILENO,line,ind);
1396 else if (line[ind]!=0 && c==BBTK_RIGHT_ARROW_KBCODE)
1398 PrintChar(line[ind]);
1403 else if (ind>0 && c==BBTK_LEFT_ARROW_KBCODE)
1411 write(STDOUT_FILENO,"\n\r",2);
1419 //=======================================================================
1420 void Interpreter::GetLineFromPrompt(std::string& s)
1446 //=======================================================================
1452 //=======================================================================
1453 void Interpreter::CommandLineInterpreter()
1455 bbtkDebugMessageInc("Interpreter",9,
1456 "Interpreter::CommandLineInterpreter()"<<std::endl);
1458 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1459 // Initialise the tty in non canonical mode with no echo
1460 // oter remembers the previous settings to restore them after
1461 struct termios ter,oter;
1464 ter.c_lflag &= ~ECHO;
1465 ter.c_lflag &= ~ICANON;
1468 tcsetattr(0,TCSANOW,&ter);
1471 mCommandLine = true;
1473 bool insideComment = false; // for multiline comment
1479 GetLineFromPrompt(line);
1480 InterpretLine(line, insideComment);
1482 catch (QuitException e)
1486 catch (bbtk::Exception e)
1490 catch (std::exception& e)
1492 std::cerr << "* ERROR :: "<<e.what()<<" (not in bbtk)"<<std::endl;
1496 std::cerr << "* UNDEFINED ERROR (not a bbtk nor a std exception)"<<std::endl;
1501 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1502 tcsetattr(0,TCSANOW,&oter);
1505 std::cout << "Good bye !" << std::endl;
1507 bbtkDebugDecTab("Interpreter",9);
1510 //=======================================================================
1511 void Interpreter::Graph(const std::vector<std::string>& words)
1514 bool system_display = true;
1516 #ifdef _USE_WXWIDGETS_
1517 if ( WxConsole::GetInstance() != 0 ) system_display = false;
1520 if (words.size()==1)
1522 page = mExecuter->ShowGraph(".","0","0","","","",system_display);
1524 else if (words.size()==2)
1526 page = mExecuter->ShowGraph(words[1],"0","0","","","",system_display);
1528 else if (words.size()==3)
1530 page = mExecuter->ShowGraph(words[1],words[2],"0","","","",system_display);
1532 else if (words.size()==4)
1534 page = mExecuter->ShowGraph(words[1],words[2],words[3],"","","",system_display);
1536 else if (words.size()==5)
1538 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],"","",system_display);
1540 else if (words.size()==6)
1542 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],"",system_display);
1544 else if (words.size()==7)
1546 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],words[6],system_display);
1549 #ifdef _USE_WXWIDGETS_
1550 if ( WxConsole::GetInstance() != 0 )
1551 WxConsole::GetInstance()->ShowHtmlPage(page);
1554 //=======================================================================