1 /*=========================================================================
4 Module: $RCSfile: bbtkInterpreter.cxx,v $ $
6 Date: $Date: 2008/02/06 09:27:52 $
7 Version: $Revision: 1.26 $
9 Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
10 l'Image). All rights reserved. See Doc/License.txt or
11 http://www.creatis.insa-lyon.fr/Public/bbtk/License.html for details.
13 This software is distributed WITHOUT ANY WARRANTY; without even
14 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 PURPOSE. See the above copyright notices for more information.
17 =========================================================================*/
20 * \brief class Interpreter :
23 #include "bbtkInterpreter.h"
24 #include "bbtkMessageManager.h"
25 #include "bbtkConfigurationFile.h"
26 #include "bbtkWxConsole.h"
27 #include "bbtkUtilities.h"
29 #ifdef CMAKE_HAVE_TERMIOS_H
31 #define BBTK_USE_TERMIOS_BASED_PROMPT
39 Interpreter* Interpreter::mGlobalInterpreter = NULL;
41 //=======================================================================
45 Interpreter::Interpreter()
49 bbtk::MessageManager::RegisterMessageType("Echo","Level>0 : Prints the 'echo' commands of the user.\n\tLevel>1 : Prints the command being interpreted",1);
50 bbtk::MessageManager::RegisterMessageType("Interpreter","Messages of the interpreter",0);
51 bbtkDebugMessageInc("Interpreter",9,"Interpreter::Interpreter()" <<std::endl);
53 mGlobalInterpreter = this;
55 // mFactory = new bbtk::Factory();
56 mExecuter = new bbtk::Executer();
57 //mExecuter->SetFactory(mFactory);
59 // Builds the commands dict
62 info.category = "new";
66 info.syntax = "new <type> <name>";
67 info.help = "Creates a new black box of type <type> with name <name>";
68 mCommandDict[info.category] = info;
70 info.category = "delete";
74 info.syntax = "delete <box>";
75 info.help = "Deletes the black box of name <box>";
76 mCommandDict[info.category] = info;
78 info.category = "connect";
82 info.syntax = "connect <box1.output> <box2.input>";
83 info.help = "Connects the ouput <output> of black box <box1> to the input <input> of black box <box2>";
84 mCommandDict[info.category] = info;
86 info.category = "print";
90 info.syntax = "print <string>";
91 info.help = "Prints the string. Substitutes any token of the form '$box.output$' by the string adaptation of the output of the box (requires the right adaptor). No carriage return is issued at the end, use '\\n' to add carriage returns. The level of 'Echo' messages must be greater than 1 (see the command 'message').";
92 mCommandDict[info.category] = info;
94 info.category = "exec";
98 info.syntax = "exec <box | 'freeze' | 'unfreeze' >";
99 info.help = "Executes the black box of name <box> (and connected boxes if needed). If the special category 'freeze' is given then freezes any further execution command. 'unfreeze' reverts to normal execution mode.";
100 mCommandDict[info.category] = info;
102 info.category = "package";
105 info.code = cPackage;
106 info.syntax = "package <name>";
107 info.help = "Begins the definition of a package.";
108 mCommandDict[info.category] = info;
110 info.category = "endpackage";
113 info.code = cEndPackage;
114 info.syntax = "endpackage";
115 info.help = "Ends the definition of a package.";
116 mCommandDict[info.category] = info;
118 info.category = "define";
122 info.syntax = "define <type> [<package>]";
123 info.help = "Begins the definition of a new type of complex black box called <type>. If <package> if provided will create it in the given package.";
124 mCommandDict[info.category] = info;
126 info.category = "endefine";
129 info.code = cEndDefine;
130 info.syntax = "endefine";
131 info.help = "Ends the definition of a new type of complex black box";
132 mCommandDict[info.category] = info;
134 info.category = "input";
138 info.syntax = "input <name> <box.input> <help>";
139 info.help = "Defines the input <name> of the current working black box as being an alias for the input <input> of the black box <box>. <help> defines the help string for the newly created input";
140 mCommandDict[info.category] = info;
142 info.category = "output";
146 info.syntax = "output <name> <box.output> <help>";
147 info.help = "Defines the output <name> of the current working black box as being an alias for the output <output> of the black box <box>. <help> defines the help string for the newly created output";
148 mCommandDict[info.category] = info;
150 info.category = "set";
154 info.syntax = "set <box.input> <value>";
155 info.help = "Sets the value of the input <input> of the black box <box> to <value>. There must exist a string to the value type adaptor";
156 mCommandDict[info.category] = info;
158 info.category = "config"; // JPR
162 info.syntax = "config";
163 info.help = "Prints the value of all configuration parameters";
164 mCommandDict[info.category] = info;
166 info.category = "index"; // LG
171 info.syntax = "index [<filename> ['Initials'(default)|'Packages'|'Categories']]";
172 info.help = "Creates an html index of known boxes. If filename is provided then save it to the file 'filename'. The default index entries are the initial letters of the names of the boxes. If 'Packages' or 'Categories' is provided then the entries are either the packages names or the categories";
173 mCommandDict[info.category] = info;
175 info.category = "reset"; //EED
179 info.syntax = "reset";
180 info.help = "Deletes all boxes and unloads all packages (bbi is reset to its start state)";
181 mCommandDict[info.category] = info;
183 info.category = "author";
187 info.syntax = "author <string>";
188 info.help = "Adds the string <string> to the author information of the black box being defined";
189 mCommandDict[info.category] = info;
191 info.category = "category"; //JP
194 info.code = cCategory;
195 info.syntax = "category <list of items, separated by ;>";
196 info.help = "Adds the string <string> to the category information of the black box being defined";
197 mCommandDict[info.category] = info;
199 info.category = "description";
202 info.code = cDescription;
203 info.syntax = "description <string>";
204 info.help = "Adds the string <string> to the descriptive information of the black box being defined";
205 mCommandDict[info.category] = info;
207 info.category = "help";
211 info.syntax = "help";
212 info.syntax = "\n (1) help \n (2) help <command name> \n (3) help packages [all]\n (4) help <package name> [all]\n (5) help <black box type> \n (6) help <black box name>";
213 info.help = "Effect :\n (1) Lists all available commands;\n (2) Prints help on a particular command; \n (3) Lists the packages loaded and their black boxes.\n Add 'all' to list adaptors; \n (4) Prints short help on the black boxes of a package.\n Add 'all' to include adaptors; \n (5) Prints full help on a black box type; \n (6) Prints information on the inputs, outputs and connections of a black box instance.";
214 mCommandDict[info.category] = info;
216 info.category = "message";
219 info.code = cMessage;
220 info.syntax = "message <kind> <level>";
221 info.help = "Sets the level of the kind of messages <kind> to <level>.\n If kind='All' then sets the level for all kinds. If no kind nor level is passed then prints info on available kinds of messages and their current level."; mCommandDict[info.category] = info;
223 info.category = "include";
226 info.code = cInclude;
227 info.syntax = "include <filename> [source]";
228 info.help = "Includes the file <filename>.\n Advanced (used to get the right 'Include' field in doc of packages appli) : If the keyword 'source' is provided then informs bbi that the included file is the source of the current box definition.";
229 mCommandDict[info.category] = info;
231 info.category = "quit";
235 info.syntax = "quit";
236 info.help = "Quits the program (during script execution it stops the complete execution)";
237 mCommandDict[info.category] = info;
239 info.category = "load";
243 info.syntax = "load <packagename>";
244 info.help = "Loads the black box package <packagename>";
245 mCommandDict[info.category] = info;
247 info.category = "unload";
251 info.syntax = "unload <packagename>";
252 info.help = "Unloads the black box package <packagename>";
253 mCommandDict[info.category] = info;
255 info.category = "graph";
259 info.syntax = "graph [ BlackBoxName [ Detail 0..1 [ Level 0..99999 [ Output html file [ Custom header [ Custom title ]]]]]] \n graph [ BlackBoxNameType [ Detail 0..1 [ Level 0..99999 [ Output html file [ Custom header [ Custom title ]]]]]]";
260 info.help = "Shows a graphical view of a bbtk pipeline.\n- BlackBoxName : name of the box to view. Default '.' : current box.\n- BlackBoxNameType : name of the type of box to view, ex : 'workspace')";
261 mCommandDict[info.category] = info;
264 info.category = "workspace";
267 info.code = cWorkspace;
268 info.syntax = "workspace < ( freeze | unfreeze ) | ( rename <newname> ) >";
269 info.help = "Configures the workspace.\n 'freeze' allow to block execution commands while keeping definition commands active. 'unfreeze' turns back the worspace in 'normal' mode.\n 'rename' allow to set a new name to the workspace.";
270 mCommandDict[info.category] = info;
273 bbtkDebugDecTab("Interpreter",9);
276 //=======================================================================
280 //=======================================================================
284 Interpreter::~Interpreter()
286 bbtkDebugMessageInc("Interpreter",9,"Interpreter::~Interpreter()" <<std::endl);
290 bbtkDebugDecTab("Interpreter",9);
292 //=======================================================================
295 //=======================================================================
299 void Interpreter::InterpretFile( const std::string& filename,
300 bool use_configuration_file)
302 bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretFile(\""<<filename<<"\")"<<std::endl);
304 bool exm = mCommandLine;
305 mCommandLine = false;
309 SwitchToFile(filename, use_configuration_file);
310 bool insideComment = false; // for multiline comment
311 while (mFile.size()>0)
313 while ((mFile.size()>0) &&
314 (!mFile.back()->eof()))
318 mFile.back()->getline(buf,500);
320 std::string str(buf);
321 int size=str.length();
322 if ( str[ size-1 ]==13 )
327 InterpretLine(str, insideComment);
329 //if (mFile.size()>0)
333 catch (QuitException e)
336 catch (bbtk::Exception e)
338 std::cerr << "* ERROR : "<<e.GetMessage()<<std::endl;
339 if (mFileName.size()) {
340 std::cerr << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
341 std::cerr << "* LINE : "<<mLine.back()<<std::endl;
344 catch (std::exception& e)
346 std::cerr << "* ERROR : "<<e.what()<<" (not in bbtk)"<<std::endl;
347 if (mFileName.size()) {
348 std::cerr << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
349 std::cerr << "* LINE : "<<mLine.back()<<std::endl;
354 std::cout << "* UNDEFINED ERROR (not a bbtk nor a std exception)"<<std::endl;
355 if (mFileName.size()) {
356 std::cout << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
357 std::cout << "* LINE : "<<mLine.back()<<std::endl;
362 bbtkDebugMessage("Interpreter",9,"EO Interpreter::InterpretFile(\""<<filename<<"\")"<<std::endl);
363 bbtkDecTab("Interpreter",9);
367 //=======================================================================
371 //=======================================================================
375 void Interpreter::InterpretLine( const std::string& line, bool &insideComment )
378 bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretLine(\""<<line<<"\")"<<std::endl);
379 bbtkMessage("Echo",2,"\""<<line<<"\""<<std::endl);
381 std::vector<std::string> words;
382 SplitLine(line,words);
387 bbtkDebugDecTab("Interpreter",9);
391 // Single line comment : # or //
392 if ( words[0][0]=='#' || (words[0][0]=='/' && words[0][1]=='/') )
394 bbtkDebugDecTab("Interpreter",9);
395 bbtkMessage("Interpreter",9,"Comment"<<std::endl);
399 // Multi line comment ( /* ... */ ) -delimiters on different lines !-
401 if (words[0][0]=='/' && words[0][1]=='*')
403 bbtkDebugDecTab("Interpreter",9);
404 bbtkMessage("Interpreter",9,"In multiline comment"<<std::endl);
405 insideComment = true;
409 if (words[0][0]=='*' && words[0][1]=='/')
411 bbtkDebugDecTab("Interpreter",9);
412 bbtkMessage("Interpreter",9,"Out multiline comment"<<std::endl);
413 if ( !insideComment ) {
414 bbtkDebugDecTab("Interpreter",9);
415 bbtkMessage("Interpreter",9,"Comment mismatch : '*/' with no matching '/*'"<<std::endl);
417 insideComment = false;
423 bbtkDebugDecTab("Interpreter",9);
424 bbtkMessage("Interpreter",9,"Multiline Comment"<<std::endl);
429 CommandInfoType command;
430 InterpretCommand(words,command);
432 bbtkDebugMessage("Interpreter",9,
433 "Command='"<<command.category
434 <<"' code="<<command.code<<std::endl);
436 std::string left,right,left2,right2;
437 std::string filename;
438 switch (command.code)
441 mExecuter->Create(words[1],words[2]);
446 // mExecuter->Remove(words[1]);
450 Utilities::SplitAroundFirstDot(words[1],left,right);
451 Utilities::SplitAroundFirstDot(words[2],left2,right2);
452 mExecuter->Connect(left,right,left2,right2);
456 mExecuter->BeginPackage(words[1]);
460 mExecuter->EndPackage();
464 if (mFileName.size()>0)
466 filename = mIncludeFileName.back(); //Utilities::get_file_name(mFileName.back());
470 mExecuter->Define(words[1],"",filename);
474 mExecuter->Define(words[1],words[2],filename);
479 mExecuter->EndDefine();
483 Print(words[1]); /// \todo use mExecuter
487 if (words[1]=="freeze")
488 mExecuter->SetNoExecMode(true);
489 else if (words[1]=="unfreeze")
490 mExecuter->SetNoExecMode(false);
492 mExecuter->Update(words[1]);
496 Utilities::SplitAroundFirstDot(words[2],left,right);
497 mExecuter->DefineInput(words[1],left,right,words[3]);
501 Utilities::SplitAroundFirstDot(words[2],left,right);
502 mExecuter->DefineOutput(words[1],left,right,words[3]);
506 Utilities::SplitAroundFirstDot(words[1],left,right);
507 mExecuter->Set(left,right,words[2]);
511 mExecuter->Author(words[1]);
515 mExecuter->Category(words[1]);
520 Index("tmp_index.html");
521 else if (words.size()==2)
523 else if (words.size()==3)
524 Index(words[1],words[2]);
527 mExecuter->Description(words[1]);
537 bbtk::MessageManager::PrintInfo();
541 sscanf(words[2].c_str(),"%d",&level);
542 bbtk::MessageManager::SetMessageLevel(words[1],level);
555 this->mExecuter->Reset();
561 InterpretFile(words[1], true ); // true : better pass use_config_file
565 SwitchToFile(words[1], true ); // true : better pass use_config_file
567 // if 'source' was given
570 this->mExecuter->SetCurrentFileName(words[1]);
575 LoadPackage(words[1], true ); // true : better pass use_config_file
579 UnLoadPackage(words[1]);
583 throw QuitException();
587 if (words.size() == 2)
589 if (words[1]=="freeze") mExecuter->SetNoExecMode(true);
590 else if (words[1]=="unfreeze") mExecuter->SetNoExecMode(false);
594 mExecuter->SetWorkspaceName(words[2]);
599 bbtkInternalError("should not reach here !!!");
602 bbtkDecTab("Interpreter",9);
604 //=======================================================================
610 //=======================================================================
614 void Interpreter::SplitLine ( const std::string& str, std::vector<std::string>& tokens)
616 bbtkDebugMessageInc("Interpreter",9,"Interpreter::SplitLine(\""<<str<<"\")"<<std::endl);
618 std::string delimiters = "\"";
619 std::vector<std::string> quote;
620 Utilities::SplitString(str,delimiters,quote);
623 std::vector<std::string>::iterator i;
624 for (i=quote.begin(); i!=quote.end(); )
626 Utilities::SplitString(*i,delimiters,tokens);
630 // bbtkDebugMessage("Interpreter",0,"\""<<*i<<"\""<<std::endl);
631 tokens.push_back(*i);
636 for (i=tokens.begin(); i!=tokens.end(); ++i)
638 bbtkDebugMessage("Interpreter",9,"["<<*i<<"] ");
640 bbtkDebugMessageCont("Interpreter",9,std::endl);
642 bbtkDebugDecTab("Interpreter",9);
644 //=======================================================================
647 //=======================================================================
648 // Replaces substrings "\\n" by a real carriage return "\n"
649 void SubsBackslashN ( std::string& s )
651 std::string ss("\\n");
652 std::string::size_type pos = 0;
655 while ( pos != std::string::npos )
657 s.replace(pos,2,cr,1);
658 pos = s.find(ss, pos-1);
661 //=======================================================================
664 //=======================================================================
668 void Interpreter::Print( const std::string& str)
670 if (mExecuter->GetNoExecMode()) return;
672 bbtkDebugMessageInc("Interpreter",9,"Interpreter::SplitLine(\""<<str<<"\")"<<std::endl);
674 std::vector<std::string> chains;
675 std::string delimiters("$");
677 // Skip delimiters at beginning.
678 std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
680 if (lastPos>0) is_text = false;
682 // Find first delimiter.
683 std::string::size_type pos = str.find_first_of(delimiters, lastPos);
685 while (std::string::npos != pos || std::string::npos != lastPos)
689 // Found a text token, add it to the vector.
690 chains.push_back(str.substr(lastPos, pos - lastPos));
694 // is an output (between $$) : decode
695 std::string tok,box,output;
696 tok = str.substr(lastPos, pos - lastPos);
697 Utilities::SplitAroundFirstDot(tok,box,output);
698 chains.push_back( mExecuter->Get(box,output) );
700 // Skip delimiters. Note the "not_of"
701 lastPos = str.find_first_not_of(delimiters, pos);
702 // Find next delimiter
703 pos = str.find_first_of(delimiters, lastPos);
707 std::vector<std::string>::iterator i;
708 for (i= chains.begin(); i!=chains.end(); ++i)
710 // bbtkMessage("Echo",1,*i);
714 std::cout << std::endl;
715 bbtkDebugDecTab("Interpreter",9);
718 //=======================================================================
723 // ===================================================================================
725 void Interpreter::SwitchToFile( const std::string& name,
726 bool use_configuration_file )
728 // Note : in the following :
729 // name : the user supplied name
730 // - abreviated name e.g. scr scr.bbs
731 // - relative full name e.g. ./scr.bbs ../../scr.bbs
732 // - absolute full name e.g. /home/usrname/proj/dir/scr.bbs
733 // same for Windows, with c:, d: ...
735 // use ./directory/subdir/scrname.bbs
738 bbtkDebugMessageInc("Interpreter",9,"Interpreter::SwitchToFile( \""
739 <<name<<"\")"<<std::endl);
741 std::vector<std::string> script_paths;
742 std::string fullPathScriptName; // full path script name
743 std::string pkgname; // e.g. <scriptname>.bbs
744 std::vector<std::string> Filenames;
746 if (use_configuration_file)
748 // The following is *NOT* a debug time message :
749 // It's a user intended message.
750 // Please don't remove it.
751 bbtkMessage("Interpreter",1,
752 "look for : [" << name
753 << "] (use_configuration_file == TRUE)" << std::endl);
754 script_paths = ConfigurationFile::GetInstance().Get_bbs_paths();
757 pkgname = Utilities::ExtractScriptName(name,upath);
759 bool fullnameGiven = false;
760 bool foundFile = false;
762 if(pkgname == "*") // =========================================== load all boxes (e.g. std/boxes/*)
766 if (upath[0]=='/' || upath[1] == ':' ) // ==== absolute name, load all .bbs files
768 int nbFiles = Utilities::Explore(upath, false, Filenames);
770 for (std::vector<std::string>::iterator i = Filenames.begin(); i!= Filenames.end(); ++i)
772 if ((*i).substr((*i).size()-4, 4) != ".bbs")
773 continue; // ignore non .bbs files
778 bbtkMessage("Interpreter",2,
779 "WARNING : No '.bbs' file found in ["
780 << upath << "]" << std::endl);
787 std::vector<std::string>::iterator i;
788 std::string fullDirectoryName;
789 for (i=script_paths.begin();i!=script_paths.end();++i)// ==== relative name, iterate + load all .bbs files
793 // we *really* want '.' to be the current working directory
795 char buf[2048]; // for getcwd
796 char * currentDir = getcwd(buf, 2048);
797 std::string cwd(currentDir);
801 fullDirectoryName = Utilities::MakePkgnameFromPath(path, upath, false);
803 // Check if library exists
804 if ( ! Utilities::IsDirectory(fullDirectoryName) )
806 // The following is *NOT* a debug time message :
807 // It's a user intended message.
808 // Please don't remove it.
809 bbtkMessage("Interpreter",1," [" <<fullDirectoryName
810 <<"] : doesn't exist" <<std::endl);
811 continue; // try next path
816 int nbFiles = Utilities::Explore(fullDirectoryName, false, Filenames);
819 for (std::vector<std::string>::iterator i = Filenames.begin(); i!= Filenames.end(); ++i)
822 if ((*i).substr((*i).size()-4, 4) != ".bbs")
823 continue; // ignore non .bbs files
828 bbtkMessage("Interpreter",1,
829 "WARNING : No '.bbs' file found in ["
830 << fullDirectoryName << "]" << std::endl);
832 //break; // a directory was found; we stop iterating
833 // LG : No! We want all files included !
838 //std::string::size_type slash_position = name.find_last_of("/\\");
840 // if name starts with a / or a . or contains : user is assumed to have passed a relative/absolute name
841 // (not only a plain script name)
842 // we trust him, and try to expland the directory name
843 // WARNING : starting from current local directory : ./whatYouWant (./ mandatory!)
845 if (name[0]=='/' || name[1] == ':' || name[0]=='.') // absolute path (linux/windows) or relative path
848 // ===========================================================check user supplied location
849 fullnameGiven = true;
852 fullPathScriptName = Utilities::ExpandLibName(name, false);
854 // allow user to always forget ".bbs"
855 int l = fullPathScriptName.size();
861 if (fullPathScriptName.substr(l-4, 4) != ".bbs")
863 fullPathScriptName = fullPathScriptName + ".bbs";
868 fullPathScriptName = fullPathScriptName + ".bbs";
871 if ( Utilities::FileExists(fullPathScriptName))
879 // =============================================================== iterate on the paths
882 std::vector<std::string>::iterator i;
883 for (i=script_paths.begin();i!=script_paths.end();++i)
887 // we *really* want '.' to be the current working directory
889 char buf[2048]; // for getcwd
890 char * currentDir = getcwd(buf, 2048);
891 std::string cwd(currentDir);
895 // fullPathScriptName = Utilities::MakePkgnameFromPath(path, name, true); //pkgname);
897 fullPathScriptName = Utilities::MakePkgnameFromPath(path, name, true);
900 // Check if library exists
901 if ( ! Utilities::FileExists(fullPathScriptName) )
903 // The following is *NOT* a debug time message :
904 // It's a user intended message.
905 // Please don't remove it.
906 bbtkMessage("Interpreter",2,
907 " [" <<fullPathScriptName <<"] : doesn't exist"
909 continue; // try next path
911 bbtkMessage("Interpreter",2,
912 " [" <<fullPathScriptName
913 <<"] : found" <<std::endl);
915 break; // a script was found; we stop iterating
917 } //------------------ // end for ( package_paths.begin();i!=package_paths.end() )
923 if(fullPathScriptName == "")
924 bbtkError("Path ["<<upath<<"] doesn't exist");
926 bbtkError("Script ["<<fullPathScriptName<<"] not found");
928 bbtkError("No ["<<pkgname<<".bbs] script found");
932 LoadScript(fullPathScriptName,name);
938 //=======================================================================
940 void Interpreter::LoadScript( std::string fullPathScriptName,
941 std::string includeScriptName)
943 if (find(mFileName.begin(),mFileName.end(),fullPathScriptName)
946 bbtkMessage("Interpreter",1,"file '"<<fullPathScriptName
947 <<"' already open : I do not open it once more to prevent recursive inclusion"<<std::endl);
952 s = new std::ifstream;
953 s->open(fullPathScriptName.c_str());
956 bbtkError("Could not open file ["<<fullPathScriptName<<"]");
960 bbtkMessage("Interpreter",1," -->[" << fullPathScriptName
961 << "] found" << std::endl);
964 mFileName.push_back(fullPathScriptName);
965 mIncludeFileName.push_back(includeScriptName);
970 //=======================================================================
974 void Interpreter::CloseCurrentFile()
976 bbtkDebugMessage("Interpreter",9,"Interpreter::CloseCurrentFile()"
981 bbtkDebugMessage("Interpreter",9," -> no file left open"<<std::endl);
985 mFile.back()->close();
988 bbtkDebugMessage("Interpreter",9,
989 " Closing file '"<<mFileName.back()<<"'"<<std::endl);
991 mFileName.pop_back();
992 mIncludeFileName.pop_back();
994 bbtkDebugMessage("Interpreter",9," Remains "
996 <<" open"<<std::endl);
997 bbtkDebugMessage("Interpreter",9,"EO Interpreter::CloseCurrentFile()"
1000 //=======================================================================
1002 //=======================================================================
1006 void Interpreter::CloseAllFiles()
1008 bbtkDebugMessage("Interpreter",9,"Interpreter::CloseAllFiles()"
1011 while (mFile.size() != 0)
1013 mFile.back()->close();
1014 delete mFile.back();
1016 bbtkDebugMessage("Interpreter",9,
1017 " Closing file '"<<mFileName.back()<<"'"<<std::endl);
1018 mFileName.pop_back();
1019 mIncludeFileName.pop_back();
1022 bbtkDebugMessage("Interpreter",9,"EO Interpreter::CloseAllFiles()"
1025 //=======================================================================
1029 //=======================================================================
1033 void Interpreter::InterpretCommand( const std::vector<std::string>& words,
1034 CommandInfoType& info )
1036 bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretCommand(...)"<<std::endl);
1038 // searches the command category
1039 CommandDictType::iterator c;
1040 c = mCommandDict.find(words[0]);
1041 if ( c == mCommandDict.end() ) {
1042 bbtkError(words[0]<<" : unknown command");
1045 // tests the number of args
1046 if ( ( words.size()-1 < c->second.argmin ) ||
1047 ( words.size()-1 > c->second.argmax ) )
1049 HelpCommand(words[0]);
1050 bbtkError(words[0]<<" : wrong number of arguments");
1054 bbtkDecTab("Interpreter",9);
1056 //=======================================================================
1059 //=======================================================================
1060 /// Displays help on all the commands
1061 void Interpreter::Help(const std::vector<std::string>& words)
1063 unsigned int nbarg = words.size()-1;
1071 if (words[1]=="packages")
1073 PrintPackages(true);
1078 HelpCommand(words[1]);
1080 catch (bbtk::Exception e)
1084 HelpPackage(words[1]);
1086 catch (bbtk::Exception f)
1090 HelpBlackBox(words[1]);
1092 catch (bbtk::Exception g)
1096 this->mExecuter->ShowRelations(words[1],"0","9999");
1098 catch (bbtk::Exception h){
1099 bbtkError("\""<<words[1].c_str()
1100 <<"\" is not a known command, package, black box type or black box name");
1108 if (words[2]=="all")
1110 if ( words[1]=="packages" )
1112 PrintPackages(true,true);
1117 HelpPackage(words[1],true);
1119 catch (bbtk::Exception f)
1125 HelpCommand(words[0]);
1126 bbtkError(words[0]<<" : syntax error");
1131 bbtkError("Should not reach here !!!");
1134 //=======================================================================
1136 //===================================================================
1137 /// Displays the Configuration
1138 void Interpreter::Config() const
1140 bbtkDebugMessageInc("Kernel",9,"Factory::Config"<<std::endl);
1142 ConfigurationFile cf = ConfigurationFile::GetInstance();
1144 const std::string config_xml_full_path = cf.Get_config_xml_full_path();
1145 const std::string description = cf.Get_description();
1146 const std::string url = cf.Get_url();
1147 const std::string data_path = cf.Get_data_path();
1148 const std::string default_doc_tmp = cf.Get_default_doc_tmp();
1149 const std::string file_separator = cf.Get_file_separator();
1150 const std::vector<std::string>bbs_paths = cf.Get_bbs_paths();
1151 const std::vector<std::string>package_paths = cf.Get_package_paths();
1153 bbtkMessage("Help",1, "=============" << std::endl);
1154 bbtkMessage("Help",1, "Configuration" << std::endl);
1155 bbtkMessage("Help",1, "=============" << std::endl);
1156 bbtkMessage("Help",1, "bbtk_config.xml : [" << config_xml_full_path << "]" << std::endl);
1157 bbtkMessage("Help",1, "Documentation Url : [" << url << "]" << std::endl);
1158 bbtkMessage("Help",1, "Data Path : [" << data_path << "]" << std::endl);
1159 bbtkMessage("Help",1, "Default Doc_tmp : [" << default_doc_tmp << "]" << std::endl);
1160 bbtkMessage("Help",1, "File Separator : [" << file_separator << "]" << std::endl);
1162 std::vector<std::string>::const_iterator i;
1164 bbtkMessage("Help",1, "BBS Paths " << std::endl);
1165 for (i = bbs_paths.begin(); i!=bbs_paths.end(); ++i )
1167 bbtkMessage("Help",1,"--- ["<<*i<<"]"<<std::endl);
1170 bbtkMessage("Help",1, "PACKAGE Paths : " << std::endl);
1171 for (i = package_paths.begin(); i!=package_paths.end(); ++i )
1173 bbtkMessage("Help",1,"--- ["<<*i<<"]"<<std::endl);
1176 bbtkDebugDecTab("Kernel",9);
1179 //=======================================================================
1180 /// Displays help on all the commands
1181 void Interpreter::HelpCommands()
1183 std::cout << "Available commands :" << std::endl;
1184 CommandDictType::iterator i;
1185 for ( i = mCommandDict.begin();
1186 i != mCommandDict.end();
1188 std::cout << " " << i->first << std::endl;
1189 // std::cout << " usage : " << i->second.syntax << std::endl;
1190 // std::cout << " " << i->second.help << std::endl;
1194 //=======================================================================
1197 //=======================================================================
1198 /// Displays help on a particular commands
1199 void Interpreter::HelpCommand(const std::string& s)
1201 CommandDictType::iterator c;
1202 c = mCommandDict.find(s);
1203 if ( c == mCommandDict.end() ) {
1204 bbtkError(s<<" : Unknown command");
1206 // std::cout << " " << s << " : "<< std::endl;
1207 // CommandParamDictType::iterator i;
1208 // for ( i = c->second.begin();
1209 // i != c->second.end();
1211 std::cout << " usage : " << c->second.syntax << std::endl;
1212 std::cout << " " << c->second.help << std::endl;
1215 //=======================================================================
1218 //=======================================================================
1219 /// Fills the vector commands with the commands which
1220 /// have the first n chars of buf for prefix
1221 /// TODO : skip initial spaces in buf and also return the position of first
1222 /// non blank char in buf
1223 void Interpreter::FindCommandsWithPrefix( char* buf,
1225 std::vector<std::string>& commands )
1227 CommandDictType::const_iterator i;
1228 for (i=mCommandDict.begin(); i!=mCommandDict.end(); ++i)
1230 if ((i->first).find(buf,0,n) == 0)
1231 commands.push_back(i->first);
1234 //=======================================================================
1238 //=======================================================================
1239 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1241 inline void PrintChar(char c) { write(STDOUT_FILENO,&c,1); }
1242 inline void BackSpace() { write(STDOUT_FILENO,"\b \b",3); }
1244 // LG : KEYBOARD CODES AS SCANNED ON MY TTY : UNIVERSAL ?
1245 // IF NOT THE USER SHOULD BE ABLE TO CONFIGURE IT
1246 // E.G. STORE THIS IN bbtk_config.xml
1247 #define BBTK_UP_ARROW_KBCODE 0x00415B1B
1248 #define BBTK_DOWN_ARROW_KBCODE 0x00425B1B
1249 #define BBTK_RIGHT_ARROW_KBCODE 0x00435B1B
1250 #define BBTK_LEFT_ARROW_KBCODE 0x00445B1B
1251 #define BBTK_BACKSPACE_KBCODE 0x00000008
1252 #define BBTK_DEL_KBCODE 0x0000007F
1253 #define BBTK_SPACE_KBCODE 0x00000020
1255 //=======================================================================
1256 void Interpreter::GetLineFromPrompt(std::string& s)
1261 int MAX_LINE_SIZE = 160;
1262 int MAX_HISTORY_SIZE = 100;
1264 char* newline = new char[MAX_LINE_SIZE];
1265 memset(newline,0,MAX_LINE_SIZE);
1266 char* histline = new char[MAX_LINE_SIZE];
1267 memset(histline,0,MAX_LINE_SIZE);
1269 char* line = newline;
1270 int hist = mHistory.size();
1277 read ( STDIN_FILENO, &c, 4) ;
1279 bbtkDebugMessage("Debug",9,"[0x"<<std::hex<<c<<"]\n");
1281 // Printable character
1282 if ( (ind<MAX_LINE_SIZE-1) &&
1283 ( c >= BBTK_SPACE_KBCODE ) &&
1284 ( c < BBTK_DEL_KBCODE ))
1292 // delete the unused line
1298 // empty lines are not stored in from history
1301 // if history too long : delete oldest command
1302 if (mHistory.size()>MAX_HISTORY_SIZE)
1304 delete mHistory.front();
1305 mHistory.pop_front();
1307 mHistory.push_back(line);
1312 else if ( (ind>0) &&
1313 ((c == BBTK_BACKSPACE_KBCODE) ||
1314 (c == BBTK_DEL_KBCODE)) )
1322 // TODO : Command completion
1323 std::vector<std::string> commands;
1324 FindCommandsWithPrefix( line,ind,commands);
1325 if (commands.size()==1)
1327 std::string com = *commands.begin();
1328 for (; ind<com.size(); ++ind)
1330 PrintChar(com[ind]);
1336 else if (commands.size()>1)
1338 std::vector<std::string>::iterator i;
1340 for (i=commands.begin();i!=commands.end();++i)
1342 write(STDOUT_FILENO,(*i).c_str(),strlen((*i).c_str()));
1345 write(STDOUT_FILENO,"\n> ",3);
1346 //for (int j=0;j<ind;++j)
1348 write(STDOUT_FILENO,line,ind);
1352 // Arrow up : back in history
1353 else if (c==BBTK_UP_ARROW_KBCODE)
1357 // erase current line
1358 while (ind--) BackSpace();
1362 strcpy(histline,mHistory[hist]);
1366 write(STDOUT_FILENO,line,ind);
1369 // Arrow down : down in history
1370 else if (c==BBTK_DOWN_ARROW_KBCODE)
1372 if (hist<mHistory.size()-1)
1374 // erase current line
1375 while (ind--) BackSpace();
1379 strcpy(histline,mHistory[hist]);
1383 write(STDOUT_FILENO,line,ind);
1385 // end of history : switch back to newline
1386 else if (hist==mHistory.size()-1)
1388 // erase current line
1389 while (ind--) BackSpace();
1396 write(STDOUT_FILENO,line,ind);
1400 else if (line[ind]!=0 && c==BBTK_RIGHT_ARROW_KBCODE)
1402 PrintChar(line[ind]);
1407 else if (ind>0 && c==BBTK_LEFT_ARROW_KBCODE)
1415 write(STDOUT_FILENO,"\n\r",2);
1423 //=======================================================================
1424 void Interpreter::GetLineFromPrompt(std::string& s)
1450 //=======================================================================
1456 //=======================================================================
1457 void Interpreter::CommandLineInterpreter()
1459 bbtkDebugMessageInc("Interpreter",9,
1460 "Interpreter::CommandLineInterpreter()"<<std::endl);
1462 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1463 // Initialise the tty in non canonical mode with no echo
1464 // oter remembers the previous settings to restore them after
1465 struct termios ter,oter;
1468 ter.c_lflag &= ~ECHO;
1469 ter.c_lflag &= ~ICANON;
1472 tcsetattr(0,TCSANOW,&ter);
1475 mCommandLine = true;
1477 bool insideComment = false; // for multiline comment
1483 GetLineFromPrompt(line);
1484 InterpretLine(line, insideComment);
1486 catch (QuitException e)
1490 catch (bbtk::Exception e)
1494 catch (std::exception& e)
1496 std::cerr << "* ERROR :: "<<e.what()<<" (not in bbtk)"<<std::endl;
1500 std::cerr << "* UNDEFINED ERROR (not a bbtk nor a std exception)"<<std::endl;
1505 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1506 tcsetattr(0,TCSANOW,&oter);
1509 std::cout << "Good bye !" << std::endl;
1511 bbtkDebugDecTab("Interpreter",9);
1514 //=======================================================================
1515 void Interpreter::Graph(const std::vector<std::string>& words)
1518 bool system_display = true;
1520 #ifdef _USE_WXWIDGETS_
1521 if ( WxConsole::GetInstance() != 0 ) system_display = false;
1524 if (words.size()==1)
1526 page = mExecuter->ShowGraph(".","0","0","","","",system_display);
1528 else if (words.size()==2)
1530 page = mExecuter->ShowGraph(words[1],"0","0","","","",system_display);
1532 else if (words.size()==3)
1534 page = mExecuter->ShowGraph(words[1],words[2],"0","","","",system_display);
1536 else if (words.size()==4)
1538 page = mExecuter->ShowGraph(words[1],words[2],words[3],"","","",system_display);
1540 else if (words.size()==5)
1542 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],"","",system_display);
1544 else if (words.size()==6)
1546 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],"",system_display);
1548 else if (words.size()==7)
1550 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],words[6],system_display);
1553 #ifdef _USE_WXWIDGETS_
1554 if ( WxConsole::GetInstance() != 0 )
1555 WxConsole::GetInstance()->ShowHtmlPage(page);
1558 //=======================================================================
1561 //=======================================================================
1562 void Interpreter::Index(const std::string& filename,
1563 const std::string& type)
1565 Factory::IndexEntryType t;
1566 if (type=="Initials") t = Factory::Initials;
1567 else if (type=="Categories") t = Factory::Categories;
1568 else if (type=="Packages") t = Factory::Packages;
1570 GetGlobalFactory()->CreateHtmlIndex(t,filename);
1572 //=======================================================================