1 /*=========================================================================
4 Module: $RCSfile: bbtkInterpreter.cxx,v $ $
6 Date: $Date: 2008/02/05 11:39:32 $
7 Version: $Revision: 1.23 $
9 Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
10 l'Image). All rights reserved. See Doc/License.txt or
11 http://www.creatis.insa-lyon.fr/Public/bbtk/License.html for details.
13 This software is distributed WITHOUT ANY WARRANTY; without even
14 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 PURPOSE. See the above copyright notices for more information.
17 =========================================================================*/
20 * \brief class Interpreter :
23 #include "bbtkInterpreter.h"
24 #include "bbtkMessageManager.h"
25 #include "bbtkConfigurationFile.h"
26 #include "bbtkWxConsole.h"
27 #include "bbtkUtilities.h"
29 #ifdef CMAKE_HAVE_TERMIOS_H
31 #define BBTK_USE_TERMIOS_BASED_PROMPT
39 Interpreter* Interpreter::mGlobalInterpreter = NULL;
41 //=======================================================================
45 Interpreter::Interpreter()
49 bbtk::MessageManager::RegisterMessageType("Echo","Level>0 : Prints the 'echo' commands of the user.\n\tLevel>1 : Prints the command being interpreted",1);
50 bbtk::MessageManager::RegisterMessageType("Interpreter","Messages of the interpreter",0);
51 bbtkDebugMessageInc("Interpreter",9,"Interpreter::Interpreter()" <<std::endl);
53 mGlobalInterpreter = this;
55 // mFactory = new bbtk::Factory();
56 mExecuter = new bbtk::Executer();
57 //mExecuter->SetFactory(mFactory);
59 // Builds the commands dict
66 info.syntax = "new <type> <name>";
67 info.help = "Creates a new black box of type <type> with name <name>";
68 mCommandDict[info.keyword] = info;
70 info.keyword = "delete";
74 info.syntax = "delete <box>";
75 info.help = "Deletes the black box of name <box>";
76 mCommandDict[info.keyword] = info;
78 info.keyword = "connect";
82 info.syntax = "connect <box1.output> <box2.input>";
83 info.help = "Connects the ouput <output> of black box <box1> to the input <input> of black box <box2>";
84 mCommandDict[info.keyword] = info;
86 info.keyword = "print";
90 info.syntax = "print <string>";
91 info.help = "Prints the string. Substitutes any token of the form '$box.output$' by the string adaptation of the output of the box (requires the right adaptor). No carriage return is issued at the end, use '\\n' to add carriage returns. The level of 'Echo' messages must be greater than 1 (see the command 'message').";
92 mCommandDict[info.keyword] = info;
94 info.keyword = "exec";
98 info.syntax = "exec <box | 'freeze' | 'unfreeze' >";
99 info.help = "Executes the black box of name <box> (and connected boxes if needed). If the special keyword 'freeze' is given then freezes any further execution command. 'unfreeze' reverts to normal execution mode.";
100 mCommandDict[info.keyword] = info;
102 info.keyword = "package";
105 info.code = cPackage;
106 info.syntax = "package <name>";
107 info.help = "Begins the definition of a package.";
108 mCommandDict[info.keyword] = info;
110 info.keyword = "endpackage";
113 info.code = cEndPackage;
114 info.syntax = "endpackage";
115 info.help = "Ends the definition of a package.";
116 mCommandDict[info.keyword] = info;
118 info.keyword = "define";
122 info.syntax = "define <type> [<package>]";
123 info.help = "Begins the definition of a new type of complex black box called <type>. If <package> if provided will create it in the given package.";
124 mCommandDict[info.keyword] = info;
126 info.keyword = "endefine";
129 info.code = cEndDefine;
130 info.syntax = "endefine";
131 info.help = "Ends the definition of a new type of complex black box";
132 mCommandDict[info.keyword] = info;
134 info.keyword = "input";
138 info.syntax = "input <name> <box.input> <help>";
139 info.help = "Defines the input <name> of the current working black box as being an alias for the input <input> of the black box <box>. <help> defines the help string for the newly created input";
140 mCommandDict[info.keyword] = info;
142 info.keyword = "output";
146 info.syntax = "output <name> <box.output> <help>";
147 info.help = "Defines the output <name> of the current working black box as being an alias for the output <output> of the black box <box>. <help> defines the help string for the newly created output";
148 mCommandDict[info.keyword] = info;
150 info.keyword = "set";
154 info.syntax = "set <box.input> <value>";
155 info.help = "Sets the value of the input <input> of the black box <box> to <value>. There must exist a string to the value type adaptor";
156 mCommandDict[info.keyword] = info;
158 info.keyword = "config"; // JPR
162 info.syntax = "config";
163 info.help = "Prints the value of all configuration parameters";
164 mCommandDict[info.keyword] = info;
166 info.keyword = "index"; // LG
170 info.syntax = "index [<filename> ['Initials'(default)|'Packages'|'Categories']]";
171 info.help = "Creates an html index of known boxes. If filename is provided then save it to the file 'filename'. The default index entries are the initial letters of the names of the boxes. If 'Packages' or 'Categories' is provided then the entries are either the packages names or the categories";
172 mCommandDict[info.keyword] = info;
174 info.keyword = "reset"; //EED
178 info.syntax = "reset";
179 info.help = "Deletes all boxes and unloads all packages (bbi is reset to its start state)";
180 mCommandDict[info.keyword] = info;
182 info.keyword = "author";
186 info.syntax = "author <string>";
187 info.help = "Adds the string <string> to the author information of the black box being defined";
188 mCommandDict[info.keyword] = info;
190 info.keyword = "keyword"; //JP
193 info.code = cKeyword;
194 info.syntax = "keyword <list of items, separated by ;>";
195 info.help = "Adds the string <string> to the keyword information of the black box being defined";
196 mCommandDict[info.keyword] = info;
198 info.keyword = "description";
201 info.code = cDescription;
202 info.syntax = "description <string>";
203 info.help = "Adds the string <string> to the descriptive information of the black box being defined";
204 mCommandDict[info.keyword] = info;
206 info.keyword = "help";
210 info.syntax = "help";
211 info.syntax = "\n (1) help \n (2) help <command name> \n (3) help packages [all]\n (4) help <package name> [all]\n (5) help <black box type> \n (6) help <black box name>";
212 info.help = "Effect :\n (1) Lists all available commands;\n (2) Prints help on a particular command; \n (3) Lists the packages loaded and their black boxes.\n Add 'all' to list adaptors; \n (4) Prints short help on the black boxes of a package.\n Add 'all' to include adaptors; \n (5) Prints full help on a black box type; \n (6) Prints information on the inputs, outputs and connections of a black box instance.";
213 mCommandDict[info.keyword] = info;
215 info.keyword = "message";
218 info.code = cMessage;
219 info.syntax = "message <kind> <level>";
220 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.keyword] = info;
222 info.keyword = "include";
225 info.code = cInclude;
226 info.syntax = "include <filename>";
227 info.help = "Includes the file <filename>";
228 mCommandDict[info.keyword] = info;
230 info.keyword = "quit";
234 info.syntax = "quit";
235 info.help = "Quits the program (during script execution it stops the complete execution)";
236 mCommandDict[info.keyword] = info;
238 info.keyword = "load";
242 info.syntax = "load <packagename>";
243 info.help = "Loads the black box package <packagename>";
244 mCommandDict[info.keyword] = info;
246 info.keyword = "unload";
250 info.syntax = "unload <packagename>";
251 info.help = "Unloads the black box package <packagename>";
252 mCommandDict[info.keyword] = info;
254 info.keyword = "graph";
258 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 ]]]]]]";
259 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')";
260 mCommandDict[info.keyword] = info;
263 info.keyword = "workspace";
266 info.code = cWorkspace;
267 info.syntax = "workspace < ( freeze | unfreeze ) | ( rename <newname> ) >";
268 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.";
269 mCommandDict[info.keyword] = info;
272 bbtkDebugDecTab("Interpreter",9);
275 //=======================================================================
279 //=======================================================================
283 Interpreter::~Interpreter()
285 bbtkDebugMessageInc("Interpreter",9,"Interpreter::~Interpreter()" <<std::endl);
289 bbtkDebugDecTab("Interpreter",9);
291 //=======================================================================
294 //=======================================================================
298 void Interpreter::InterpretFile( const std::string& filename,
299 bool use_configuration_file)
301 bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretFile(\""<<filename<<"\")"<<std::endl);
303 bool exm = mCommandLine;
304 mCommandLine = false;
308 SwitchToFile(filename, use_configuration_file);
309 bool insideComment = false; // for multiline comment
310 while (mFile.size()>0)
312 while ((mFile.size()>0) &&
313 (!mFile.back()->eof()))
317 mFile.back()->getline(buf,500);
319 std::string str(buf);
320 int size=str.length();
321 if ( str[ size-1 ]==13 )
326 InterpretLine(str, insideComment);
328 //if (mFile.size()>0)
332 catch (QuitException e)
335 catch (bbtk::Exception e)
337 std::cerr << "* ERROR : "<<e.GetMessage()<<std::endl;
338 if (mFileName.size()) {
339 std::cerr << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
340 std::cerr << "* LINE : "<<mLine.back()<<std::endl;
343 catch (std::exception& e)
345 std::cerr << "* ERROR : "<<e.what()<<" (not in bbtk)"<<std::endl;
346 if (mFileName.size()) {
347 std::cerr << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
348 std::cerr << "* LINE : "<<mLine.back()<<std::endl;
353 std::cout << "* UNDEFINED ERROR (not a bbtk nor a std exception)"<<std::endl;
354 if (mFileName.size()) {
355 std::cout << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
356 std::cout << "* LINE : "<<mLine.back()<<std::endl;
361 bbtkDebugMessage("Interpreter",9,"EO Interpreter::InterpretFile(\""<<filename<<"\")"<<std::endl);
362 bbtkDecTab("Interpreter",9);
366 //=======================================================================
370 //=======================================================================
374 void Interpreter::InterpretLine( const std::string& line, bool &insideComment )
377 bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretLine(\""<<line<<"\")"<<std::endl);
378 bbtkMessage("Echo",2,"\""<<line<<"\""<<std::endl);
380 std::vector<std::string> words;
381 SplitLine(line,words);
386 bbtkDebugDecTab("Interpreter",9);
390 // Single line comment : # or //
391 if ( words[0][0]=='#' || (words[0][0]=='/' && words[0][1]=='/') )
393 bbtkDebugDecTab("Interpreter",9);
394 bbtkMessage("Interpreter",9,"Comment"<<std::endl);
398 // Multi line comment ( /* ... */ ) -delimiters on different lines !-
400 if (words[0][0]=='/' && words[0][1]=='*')
402 bbtkDebugDecTab("Interpreter",9);
403 bbtkMessage("Interpreter",9,"In multiline comment"<<std::endl);
404 insideComment = true;
408 if (words[0][0]=='*' && words[0][1]=='/')
410 bbtkDebugDecTab("Interpreter",9);
411 bbtkMessage("Interpreter",9,"Out multiline comment"<<std::endl);
412 if ( !insideComment ) {
413 bbtkDebugDecTab("Interpreter",9);
414 bbtkMessage("Interpreter",9,"Comment mismatch : '*/' with no matching '/*'"<<std::endl);
416 insideComment = false;
422 bbtkDebugDecTab("Interpreter",9);
423 bbtkMessage("Interpreter",9,"Multiline Comment"<<std::endl);
428 CommandInfoType command;
429 InterpretCommand(words,command);
431 bbtkDebugMessage("Interpreter",9,
432 "Command='"<<command.keyword
433 <<"' code="<<command.code<<std::endl);
435 std::string left,right,left2,right2;
436 std::string filename;
437 switch (command.code)
440 mExecuter->Create(words[1],words[2]);
445 // mExecuter->Remove(words[1]);
449 Utilities::SplitAroundFirstDot(words[1],left,right);
450 Utilities::SplitAroundFirstDot(words[2],left2,right2);
451 mExecuter->Connect(left,right,left2,right2);
455 mExecuter->BeginPackage(words[1]);
459 mExecuter->EndPackage();
463 if (mFileName.size()>0)
465 filename = Utilities::get_file_name(mFileName.back());
469 mExecuter->Define(words[1],"",filename);
473 mExecuter->Define(words[1],words[2],filename);
478 mExecuter->EndDefine();
482 Print(words[1]); /// \todo use mExecuter
486 if (words[1]=="freeze")
487 mExecuter->SetNoExecMode(true);
488 else if (words[1]=="unfreeze")
489 mExecuter->SetNoExecMode(false);
491 mExecuter->Update(words[1]);
495 Utilities::SplitAroundFirstDot(words[2],left,right);
496 mExecuter->DefineInput(words[1],left,right,words[3]);
500 Utilities::SplitAroundFirstDot(words[2],left,right);
501 mExecuter->DefineOutput(words[1],left,right,words[3]);
505 Utilities::SplitAroundFirstDot(words[1],left,right);
506 mExecuter->Set(left,right,words[2]);
510 mExecuter->Author(words[1]);
514 mExecuter->Keyword(words[1]);
519 Index("tmp_index.html");
520 else if (words.size()==2)
522 else if (words.size()==3)
523 Index(words[1],words[2]);
526 mExecuter->Description(words[1]);
536 bbtk::MessageManager::PrintInfo();
540 sscanf(words[2].c_str(),"%d",&level);
541 bbtk::MessageManager::SetMessageLevel(words[1],level);
554 this->mExecuter->Reset();
560 InterpretFile(words[1], true ); // true : better pass use_config_file
564 SwitchToFile(words[1], true ); // true : better pass use_config_file
569 LoadPackage(words[1], true ); // true : better pass use_config_file
573 UnLoadPackage(words[1]);
577 throw QuitException();
581 if (words.size() == 2)
583 if (words[1]=="freeze") mExecuter->SetNoExecMode(true);
584 else if (words[1]=="unfreeze") mExecuter->SetNoExecMode(false);
588 mExecuter->SetWorkspaceName(words[2]);
593 bbtkInternalError("should not reach here !!!");
596 bbtkDecTab("Interpreter",9);
598 //=======================================================================
604 //=======================================================================
608 void Interpreter::SplitLine ( const std::string& str, std::vector<std::string>& tokens)
610 bbtkDebugMessageInc("Interpreter",9,"Interpreter::SplitLine(\""<<str<<"\")"<<std::endl);
612 std::string delimiters = "\"";
613 std::vector<std::string> quote;
614 Utilities::SplitString(str,delimiters,quote);
617 std::vector<std::string>::iterator i;
618 for (i=quote.begin(); i!=quote.end(); )
620 Utilities::SplitString(*i,delimiters,tokens);
624 // bbtkDebugMessage("Interpreter",0,"\""<<*i<<"\""<<std::endl);
625 tokens.push_back(*i);
630 for (i=tokens.begin(); i!=tokens.end(); ++i)
632 bbtkDebugMessage("Interpreter",9,"["<<*i<<"] ");
634 bbtkDebugMessageCont("Interpreter",9,std::endl);
636 bbtkDebugDecTab("Interpreter",9);
638 //=======================================================================
641 //=======================================================================
642 // Replaces substrings "\\n" by a real carriage return "\n"
643 void SubsBackslashN ( std::string& s )
645 std::string ss("\\n");
646 std::string::size_type pos = 0;
649 while ( pos != std::string::npos )
651 s.replace(pos,2,cr,1);
652 pos = s.find(ss, pos-1);
655 //=======================================================================
658 //=======================================================================
662 void Interpreter::Print( const std::string& str)
664 if (mExecuter->GetNoExecMode()) return;
666 bbtkDebugMessageInc("Interpreter",9,"Interpreter::SplitLine(\""<<str<<"\")"<<std::endl);
668 std::vector<std::string> chains;
669 std::string delimiters("$");
671 // Skip delimiters at beginning.
672 std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
674 if (lastPos>0) is_text = false;
676 // Find first delimiter.
677 std::string::size_type pos = str.find_first_of(delimiters, lastPos);
679 while (std::string::npos != pos || std::string::npos != lastPos)
683 // Found a text token, add it to the vector.
684 chains.push_back(str.substr(lastPos, pos - lastPos));
688 // is an output (between $$) : decode
689 std::string tok,box,output;
690 tok = str.substr(lastPos, pos - lastPos);
691 Utilities::SplitAroundFirstDot(tok,box,output);
692 chains.push_back( mExecuter->Get(box,output) );
694 // Skip delimiters. Note the "not_of"
695 lastPos = str.find_first_not_of(delimiters, pos);
696 // Find next delimiter
697 pos = str.find_first_of(delimiters, lastPos);
701 std::vector<std::string>::iterator i;
702 for (i= chains.begin(); i!=chains.end(); ++i)
704 // bbtkMessage("Echo",1,*i);
708 std::cout << std::endl;
709 bbtkDebugDecTab("Interpreter",9);
712 //=======================================================================
717 // ===================================================================================
719 void Interpreter::SwitchToFile( const std::string& name,
720 bool use_configuration_file )
722 // Note : in the following :
723 // name : the user supplied name
724 // - abreviated name e.g. scr scr.bbs
725 // - relative full name e.g. ./scr.bbs ../../scr.bbs
726 // - absolute full name e.g. /home/usrname/proj/dir/scr.bbs
727 // same for Windows, with c:, d: ...
729 // use ./directory/subdir/scrname.bbs
732 bbtkDebugMessageInc("Interpreter",9,"Interpreter::SwitchToFile( \""
733 <<name<<"\")"<<std::endl);
735 std::vector<std::string> script_paths;
736 std::string fullPathScriptName; // full path script name
737 std::string pkgname; // e.g. <scriptname>.bbs
738 std::vector<std::string> Filenames;
740 if (use_configuration_file)
742 // The following is *NOT* a debug time message :
743 // It's a user intended message.
744 // Please don't remove it.
745 bbtkMessage("Interpreter",1,
746 "look for : [" << name
747 << "] (use_configuration_file == TRUE)" << std::endl);
748 script_paths = ConfigurationFile::GetInstance().Get_bbs_paths();
751 pkgname = Utilities::ExtractScriptName(name,upath);
753 bool fullnameGiven = false;
754 bool foundFile = false;
756 if(pkgname == "*") // =========================================== load all boxes (e.g. std/boxes/*)
760 if (upath[0]=='/' || upath[1] == ':' ) // ==== absolute name, load all .bbs files
762 int nbFiles = Utilities::Explore(upath, false, Filenames);
764 for (std::vector<std::string>::iterator i = Filenames.begin(); i!= Filenames.end(); ++i)
766 if ((*i).substr((*i).size()-4, 4) != ".bbs")
767 continue; // ignore non .bbs files
772 bbtkMessage("Interpreter",2,
773 "WARNING : No '.bbs' file found in ["
774 << upath << "]" << std::endl);
781 std::vector<std::string>::iterator i;
782 std::string fullDirectoryName;
783 for (i=script_paths.begin();i!=script_paths.end();++i)// ==== relative name, iterate + load all .bbs files
787 // we *really* want '.' to be the current working directory
789 char buf[2048]; // for getcwd
790 char * currentDir = getcwd(buf, 2048);
791 std::string cwd(currentDir);
795 fullDirectoryName = Utilities::MakePkgnameFromPath(path, upath, false);
797 // Check if library exists
798 if ( ! Utilities::IsDirectory(fullDirectoryName) )
800 // The following is *NOT* a debug time message :
801 // It's a user intended message.
802 // Please don't remove it.
803 bbtkMessage("Interpreter",1," [" <<fullDirectoryName
804 <<"] : doesn't exist" <<std::endl);
805 continue; // try next path
810 int nbFiles = Utilities::Explore(fullDirectoryName, false, Filenames);
813 for (std::vector<std::string>::iterator i = Filenames.begin(); i!= Filenames.end(); ++i)
816 if ((*i).substr((*i).size()-4, 4) != ".bbs")
817 continue; // ignore non .bbs files
822 bbtkMessage("Interpreter",1,
823 "WARNING : No '.bbs' file found in ["
824 << fullDirectoryName << "]" << std::endl);
826 //break; // a directory was found; we stop iterating
827 // LG : No! We want all files included !
832 //std::string::size_type slash_position = name.find_last_of("/\\");
834 // if name starts with a / or a . or contains : user is assumed to have passed a relative/absolute name
835 // (not only a plain script name)
836 // we trust him, and try to expland the directory name
837 // WARNING : starting from current local directory : ./whatYouWant (./ mandatory!)
839 if (name[0]=='/' || name[1] == ':' || name[0]=='.') // absolute path (linux/windows) or relative path
842 // ===========================================================check user supplied location
843 fullnameGiven = true;
846 fullPathScriptName = Utilities::ExpandLibName(name, false);
848 // allow user to always forget ".bbs"
849 int l = fullPathScriptName.size();
855 if (fullPathScriptName.substr(l-4, 4) != ".bbs")
857 fullPathScriptName = fullPathScriptName + ".bbs";
862 fullPathScriptName = fullPathScriptName + ".bbs";
865 if ( Utilities::FileExists(fullPathScriptName))
873 // =============================================================== iterate on the paths
876 std::vector<std::string>::iterator i;
877 for (i=script_paths.begin();i!=script_paths.end();++i)
881 // we *really* want '.' to be the current working directory
883 char buf[2048]; // for getcwd
884 char * currentDir = getcwd(buf, 2048);
885 std::string cwd(currentDir);
889 // fullPathScriptName = Utilities::MakePkgnameFromPath(path, name, true); //pkgname);
891 fullPathScriptName = Utilities::MakePkgnameFromPath(path, name, true);
894 // Check if library exists
895 if ( ! Utilities::FileExists(fullPathScriptName) )
897 // The following is *NOT* a debug time message :
898 // It's a user intended message.
899 // Please don't remove it.
900 bbtkMessage("Interpreter",2,
901 " [" <<fullPathScriptName <<"] : doesn't exist"
903 continue; // try next path
905 bbtkMessage("Interpreter",2,
906 " [" <<fullPathScriptName
907 <<"] : found" <<std::endl);
909 break; // a script was found; we stop iterating
911 } //------------------ // end for ( package_paths.begin();i!=package_paths.end() )
917 if(fullPathScriptName == "")
918 bbtkError("Path ["<<upath<<"] doesn't exist");
920 bbtkError("Script ["<<fullPathScriptName<<"] not found");
922 bbtkError("No ["<<pkgname<<".bbs] script found");
926 LoadScript(fullPathScriptName);
932 //=======================================================================
934 void Interpreter::LoadScript( std::string fullPathScriptName)
936 if (find(mFileName.begin(),mFileName.end(),fullPathScriptName)
939 bbtkMessage("Interpreter",1,"file '"<<fullPathScriptName
940 <<"' already open : I do not open it once more to prevent recursive inclusion"<<std::endl);
945 s = new std::ifstream;
946 s->open(fullPathScriptName.c_str());
949 bbtkError("Could not open file ["<<fullPathScriptName<<"]");
953 bbtkMessage("Interpreter",1," -->[" << fullPathScriptName
954 << "] found" << std::endl);
957 mFileName.push_back(fullPathScriptName);
962 //=======================================================================
966 void Interpreter::CloseCurrentFile()
968 bbtkDebugMessage("Interpreter",9,"Interpreter::CloseCurrentFile()"
973 bbtkDebugMessage("Interpreter",9," -> no file left open"<<std::endl);
977 mFile.back()->close();
980 bbtkDebugMessage("Interpreter",9,
981 " Closing file '"<<mFileName.back()<<"'"<<std::endl);
983 mFileName.pop_back();
985 bbtkDebugMessage("Interpreter",9," Remains "
987 <<" open"<<std::endl);
988 bbtkDebugMessage("Interpreter",9,"EO Interpreter::CloseCurrentFile()"
991 //=======================================================================
993 //=======================================================================
997 void Interpreter::CloseAllFiles()
999 bbtkDebugMessage("Interpreter",9,"Interpreter::CloseAllFiles()"
1002 while (mFile.size() != 0)
1004 mFile.back()->close();
1005 delete mFile.back();
1007 bbtkDebugMessage("Interpreter",9,
1008 " Closing file '"<<mFileName.back()<<"'"<<std::endl);
1009 mFileName.pop_back();
1012 bbtkDebugMessage("Interpreter",9,"EO Interpreter::CloseAllFiles()"
1015 //=======================================================================
1019 //=======================================================================
1023 void Interpreter::InterpretCommand( const std::vector<std::string>& words,
1024 CommandInfoType& info )
1026 bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretCommand(...)"<<std::endl);
1028 // searches the command keyword
1029 CommandDictType::iterator c;
1030 c = mCommandDict.find(words[0]);
1031 if ( c == mCommandDict.end() ) {
1032 bbtkError(words[0]<<" : unknown command");
1035 // tests the number of args
1036 if ( ( words.size()-1 < c->second.argmin ) ||
1037 ( words.size()-1 > c->second.argmax ) )
1039 HelpCommand(words[0]);
1040 bbtkError(words[0]<<" : wrong number of arguments");
1044 bbtkDecTab("Interpreter",9);
1046 //=======================================================================
1049 //=======================================================================
1050 /// Displays help on all the commands
1051 void Interpreter::Help(const std::vector<std::string>& words)
1053 unsigned int nbarg = words.size()-1;
1061 if (words[1]=="packages")
1063 PrintPackages(true);
1068 HelpCommand(words[1]);
1070 catch (bbtk::Exception e)
1074 HelpPackage(words[1]);
1076 catch (bbtk::Exception f)
1080 HelpBlackBox(words[1]);
1082 catch (bbtk::Exception g)
1086 this->mExecuter->ShowRelations(words[1],"0","9999");
1088 catch (bbtk::Exception h){
1089 bbtkError("\""<<words[1].c_str()
1090 <<"\" is not a known command, package, black box type or black box name");
1098 if (words[2]=="all")
1100 if ( words[1]=="packages" )
1102 PrintPackages(true,true);
1107 HelpPackage(words[1],true);
1109 catch (bbtk::Exception f)
1115 HelpCommand(words[0]);
1116 bbtkError(words[0]<<" : syntax error");
1121 bbtkError("Should not reach here !!!");
1124 //=======================================================================
1126 //===================================================================
1127 /// Displays the Configuration
1128 void Interpreter::Config() const
1130 bbtkDebugMessageInc("Core",9,"Factory::Config"<<std::endl);
1132 ConfigurationFile cf = ConfigurationFile::GetInstance();
1134 const std::string config_xml_full_path = cf.Get_config_xml_full_path();
1135 const std::string description = cf.Get_description();
1136 const std::string url = cf.Get_url();
1137 const std::string data_path = cf.Get_data_path();
1138 const std::string default_doc_tmp = cf.Get_default_doc_tmp();
1139 const std::string file_separator = cf.Get_file_separator();
1140 const std::vector<std::string>bbs_paths = cf.Get_bbs_paths();
1141 const std::vector<std::string>package_paths = cf.Get_package_paths();
1143 bbtkMessage("Help",1, "=============" << std::endl);
1144 bbtkMessage("Help",1, "Configuration" << std::endl);
1145 bbtkMessage("Help",1, "=============" << std::endl);
1146 bbtkMessage("Help",1, "bbtk_config.xml : [" << config_xml_full_path << "]" << std::endl);
1147 bbtkMessage("Help",1, "Documentation Url : [" << url << "]" << std::endl);
1148 bbtkMessage("Help",1, "Data Path : [" << data_path << "]" << std::endl);
1149 bbtkMessage("Help",1, "Default Doc_tmp : [" << default_doc_tmp << "]" << std::endl);
1150 bbtkMessage("Help",1, "File Separator : [" << file_separator << "]" << std::endl);
1152 std::vector<std::string>::const_iterator i;
1154 bbtkMessage("Help",1, "BBS Paths " << std::endl);
1155 for (i = bbs_paths.begin(); i!=bbs_paths.end(); ++i )
1157 bbtkMessage("Help",1,"--- ["<<*i<<"]"<<std::endl);
1160 bbtkMessage("Help",1, "PACKAGE Paths : " << std::endl);
1161 for (i = package_paths.begin(); i!=package_paths.end(); ++i )
1163 bbtkMessage("Help",1,"--- ["<<*i<<"]"<<std::endl);
1166 bbtkDebugDecTab("Core",9);
1169 //=======================================================================
1170 /// Displays help on all the commands
1171 void Interpreter::HelpCommands()
1173 std::cout << "Available commands :" << std::endl;
1174 CommandDictType::iterator i;
1175 for ( i = mCommandDict.begin();
1176 i != mCommandDict.end();
1178 std::cout << " " << i->first << std::endl;
1179 // std::cout << " usage : " << i->second.syntax << std::endl;
1180 // std::cout << " " << i->second.help << std::endl;
1184 //=======================================================================
1187 //=======================================================================
1188 /// Displays help on a particular commands
1189 void Interpreter::HelpCommand(const std::string& s)
1191 CommandDictType::iterator c;
1192 c = mCommandDict.find(s);
1193 if ( c == mCommandDict.end() ) {
1194 bbtkError(s<<" : Unknown command");
1196 // std::cout << " " << s << " : "<< std::endl;
1197 // CommandParamDictType::iterator i;
1198 // for ( i = c->second.begin();
1199 // i != c->second.end();
1201 std::cout << " usage : " << c->second.syntax << std::endl;
1202 std::cout << " " << c->second.help << std::endl;
1205 //=======================================================================
1208 //=======================================================================
1209 /// Fills the vector commands with the commands which
1210 /// have the first n chars of buf for prefix
1211 /// TODO : skip initial spaces in buf and also return the position of first
1212 /// non blank char in buf
1213 void Interpreter::FindCommandsWithPrefix( char* buf,
1215 std::vector<std::string>& commands )
1217 CommandDictType::const_iterator i;
1218 for (i=mCommandDict.begin(); i!=mCommandDict.end(); ++i)
1220 if ((i->first).find(buf,0,n) == 0)
1221 commands.push_back(i->first);
1224 //=======================================================================
1228 //=======================================================================
1229 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1231 inline void PrintChar(char c) { write(STDOUT_FILENO,&c,1); }
1232 inline void BackSpace() { write(STDOUT_FILENO,"\b \b",3); }
1234 // LG : KEYBOARD CODES AS SCANNED ON MY TTY : UNIVERSAL ?
1235 // IF NOT THE USER SHOULD BE ABLE TO CONFIGURE IT
1236 // E.G. STORE THIS IN bbtk_config.xml
1237 #define BBTK_UP_ARROW_KBCODE 0x00415B1B
1238 #define BBTK_DOWN_ARROW_KBCODE 0x00425B1B
1239 #define BBTK_RIGHT_ARROW_KBCODE 0x00435B1B
1240 #define BBTK_LEFT_ARROW_KBCODE 0x00445B1B
1241 #define BBTK_BACKSPACE_KBCODE 0x00000008
1242 #define BBTK_DEL_KBCODE 0x0000007F
1243 #define BBTK_SPACE_KBCODE 0x00000020
1245 //=======================================================================
1246 void Interpreter::GetLineFromPrompt(std::string& s)
1251 int MAX_LINE_SIZE = 160;
1252 int MAX_HISTORY_SIZE = 100;
1254 char* newline = new char[MAX_LINE_SIZE];
1255 memset(newline,0,MAX_LINE_SIZE);
1256 char* histline = new char[MAX_LINE_SIZE];
1257 memset(histline,0,MAX_LINE_SIZE);
1259 char* line = newline;
1260 int hist = mHistory.size();
1267 read ( STDIN_FILENO, &c, 4) ;
1269 bbtkDebugMessage("Debug",9,"[0x"<<std::hex<<c<<"]\n");
1271 // Printable character
1272 if ( (ind<MAX_LINE_SIZE-1) &&
1273 ( c >= BBTK_SPACE_KBCODE ) &&
1274 ( c < BBTK_DEL_KBCODE ))
1282 // delete the unused line
1288 // empty lines are not stored in from history
1291 // if history too long : delete oldest command
1292 if (mHistory.size()>MAX_HISTORY_SIZE)
1294 delete mHistory.front();
1295 mHistory.pop_front();
1297 mHistory.push_back(line);
1302 else if ( (ind>0) &&
1303 ((c == BBTK_BACKSPACE_KBCODE) ||
1304 (c == BBTK_DEL_KBCODE)) )
1312 // TODO : Command completion
1313 std::vector<std::string> commands;
1314 FindCommandsWithPrefix( line,ind,commands);
1315 if (commands.size()==1)
1317 std::string com = *commands.begin();
1318 for (; ind<com.size(); ++ind)
1320 PrintChar(com[ind]);
1326 else if (commands.size()>1)
1328 std::vector<std::string>::iterator i;
1330 for (i=commands.begin();i!=commands.end();++i)
1332 write(STDOUT_FILENO,(*i).c_str(),strlen((*i).c_str()));
1335 write(STDOUT_FILENO,"\n> ",3);
1336 //for (int j=0;j<ind;++j)
1338 write(STDOUT_FILENO,line,ind);
1342 // Arrow up : back in history
1343 else if (c==BBTK_UP_ARROW_KBCODE)
1347 // erase current line
1348 while (ind--) BackSpace();
1352 strcpy(histline,mHistory[hist]);
1356 write(STDOUT_FILENO,line,ind);
1359 // Arrow down : down in history
1360 else if (c==BBTK_DOWN_ARROW_KBCODE)
1362 if (hist<mHistory.size()-1)
1364 // erase current line
1365 while (ind--) BackSpace();
1369 strcpy(histline,mHistory[hist]);
1373 write(STDOUT_FILENO,line,ind);
1375 // end of history : switch back to newline
1376 else if (hist==mHistory.size()-1)
1378 // erase current line
1379 while (ind--) BackSpace();
1386 write(STDOUT_FILENO,line,ind);
1390 else if (line[ind]!=0 && c==BBTK_RIGHT_ARROW_KBCODE)
1392 PrintChar(line[ind]);
1397 else if (ind>0 && c==BBTK_LEFT_ARROW_KBCODE)
1405 write(STDOUT_FILENO,"\n\r",2);
1413 //=======================================================================
1414 void Interpreter::GetLineFromPrompt(std::string& s)
1440 //=======================================================================
1446 //=======================================================================
1447 void Interpreter::CommandLineInterpreter()
1449 bbtkDebugMessageInc("Interpreter",9,
1450 "Interpreter::CommandLineInterpreter()"<<std::endl);
1452 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1453 // Initialise the tty in non canonical mode with no echo
1454 // oter remembers the previous settings to restore them after
1455 struct termios ter,oter;
1458 ter.c_lflag &= ~ECHO;
1459 ter.c_lflag &= ~ICANON;
1462 tcsetattr(0,TCSANOW,&ter);
1465 mCommandLine = true;
1467 bool insideComment = false; // for multiline comment
1473 GetLineFromPrompt(line);
1474 InterpretLine(line, insideComment);
1476 catch (QuitException e)
1480 catch (bbtk::Exception e)
1484 catch (std::exception& e)
1486 std::cerr << "* ERROR :: "<<e.what()<<" (not in bbtk)"<<std::endl;
1490 std::cerr << "* UNDEFINED ERROR (not a bbtk nor a std exception)"<<std::endl;
1495 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1496 tcsetattr(0,TCSANOW,&oter);
1499 std::cout << "Good bye !" << std::endl;
1501 bbtkDebugDecTab("Interpreter",9);
1504 //=======================================================================
1505 void Interpreter::Graph(const std::vector<std::string>& words)
1508 bool system_display = true;
1510 #ifdef _USE_WXWIDGETS_
1511 if ( WxConsole::GetInstance() != 0 ) system_display = false;
1514 if (words.size()==1)
1516 page = mExecuter->ShowGraph(".","0","0","","","",system_display);
1518 else if (words.size()==2)
1520 page = mExecuter->ShowGraph(words[1],"0","0","","","",system_display);
1522 else if (words.size()==3)
1524 page = mExecuter->ShowGraph(words[1],words[2],"0","","","",system_display);
1526 else if (words.size()==4)
1528 page = mExecuter->ShowGraph(words[1],words[2],words[3],"","","",system_display);
1530 else if (words.size()==5)
1532 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],"","",system_display);
1534 else if (words.size()==6)
1536 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],"",system_display);
1538 else if (words.size()==7)
1540 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],words[6],system_display);
1543 #ifdef _USE_WXWIDGETS_
1544 if ( WxConsole::GetInstance() != 0 )
1545 WxConsole::GetInstance()->ShowHtmlPage(page);
1548 //=======================================================================
1551 //=======================================================================
1552 void Interpreter::Index(const std::string& filename,
1553 const std::string& type)
1555 Factory::IndexEntryType t;
1556 if (type=="Initials") t = Factory::Initials;
1557 else if (type=="Categories") t = Factory::Categories;
1558 else if (type=="Packages") t = Factory::Packages;
1560 GetGlobalFactory()->CreateHtmlIndex(t,filename);
1562 //=======================================================================