1 /*=========================================================================
4 Module: $RCSfile: bbtkInterpreter.cxx,v $ $
6 Date: $Date: 2008/02/14 11:26:43 $
7 Version: $Revision: 1.31 $
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 = new bbtk::Transcriptor("GeneratedProgram.txt");
58 //mExecuter->SetFactory(mFactory);
60 // Builds the commands dict
63 info.category = "new";
67 info.syntax = "new <type> <name>";
68 info.help = "Creates a new black box of type <type> with name <name>";
69 mCommandDict[info.category] = info;
71 info.category = "delete";
75 info.syntax = "delete <box>";
76 info.help = "Deletes the black box of name <box>";
77 mCommandDict[info.category] = info;
79 info.category = "connect";
83 info.syntax = "connect <box1.output> <box2.input>";
84 info.help = "Connects the ouput <output> of black box <box1> to the input <input> of black box <box2>";
85 mCommandDict[info.category] = info;
87 info.category = "print";
91 info.syntax = "print <string>";
92 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').";
93 mCommandDict[info.category] = info;
95 info.category = "exec";
99 info.syntax = "exec <box | 'freeze' | 'unfreeze' >";
100 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.";
101 mCommandDict[info.category] = info;
103 info.category = "package";
106 info.code = cPackage;
107 info.syntax = "package <name>";
108 info.help = "Begins the definition of a package.";
109 mCommandDict[info.category] = info;
111 info.category = "endpackage";
114 info.code = cEndPackage;
115 info.syntax = "endpackage";
116 info.help = "Ends the definition of a package.";
117 mCommandDict[info.category] = info;
119 info.category = "define";
123 info.syntax = "define <type> [<package>]";
124 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.";
125 mCommandDict[info.category] = info;
127 info.category = "endefine";
130 info.code = cEndDefine;
131 info.syntax = "endefine";
132 info.help = "Ends the definition of a new type of complex black box";
133 mCommandDict[info.category] = info;
135 info.category = "input";
139 info.syntax = "input <name> <box.input> <help>";
140 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";
141 mCommandDict[info.category] = info;
143 info.category = "output";
147 info.syntax = "output <name> <box.output> <help>";
148 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";
149 mCommandDict[info.category] = info;
151 info.category = "set";
155 info.syntax = "set <box.input> <value>";
156 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";
157 mCommandDict[info.category] = info;
159 info.category = "config"; // JPR
163 info.syntax = "config";
164 info.help = "Prints the value of all configuration parameters";
165 mCommandDict[info.category] = info;
167 info.category = "index"; // LG
172 info.syntax = "index [<filename> ['Initials'(default)|'Packages'|'Categories']]";
173 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";
174 mCommandDict[info.category] = info;
176 info.category = "reset"; //EED
180 info.syntax = "reset";
181 info.help = "Deletes all boxes and unloads all packages (bbi is reset to its start state)";
182 mCommandDict[info.category] = info;
184 info.category = "author";
188 info.syntax = "author <string>";
189 info.help = "Adds the string <string> to the author information of the black box being defined";
190 mCommandDict[info.category] = info;
192 info.category = "category"; //JP
195 info.code = cCategory;
196 info.syntax = "category <list of items, separated by ;>";
197 info.help = "Adds the string <string> to the category information of the black box being defined";
198 mCommandDict[info.category] = info;
200 info.category = "description";
203 info.code = cDescription;
204 info.syntax = "description <string>";
205 info.help = "Adds the string <string> to the descriptive information of the black box being defined";
206 mCommandDict[info.category] = info;
208 info.category = "help";
212 info.syntax = "help";
213 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>";
214 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.";
215 mCommandDict[info.category] = info;
217 info.category = "message";
220 info.code = cMessage;
221 info.syntax = "message <kind> <level>";
222 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;
224 info.category = "include";
227 info.code = cInclude;
228 info.syntax = "include <filename> [source]";
229 info.help = "Includes the file <filename>.\n 'source' : If the keyword 'source' is provided then informs bbi that the included file is the source of the current box definition (Advanced; used to get the right 'Include' field in html doc of packages 'appli' scripts).";
230 mCommandDict[info.category] = info;
232 info.category = "quit";
236 info.syntax = "quit";
237 info.help = "Quits the program (during script execution it stops the complete execution)";
238 mCommandDict[info.category] = info;
240 info.category = "load";
244 info.syntax = "load <packagename>";
245 info.help = "Loads the black box package <packagename>";
246 mCommandDict[info.category] = info;
248 info.category = "unload";
252 info.syntax = "unload <packagename>";
253 info.help = "Unloads the black box package <packagename>";
254 mCommandDict[info.category] = info;
256 info.category = "graph";
260 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 ]]]]]]";
261 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')";
262 mCommandDict[info.category] = info;
265 info.category = "workspace";
268 info.code = cWorkspace;
269 info.syntax = "workspace < ( freeze | unfreeze ) | ( rename <newname> ) >";
270 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.";
271 mCommandDict[info.category] = info;
274 bbtkDebugDecTab("Interpreter",9);
277 //=======================================================================
281 //=======================================================================
285 Interpreter::~Interpreter()
287 bbtkDebugMessageInc("Interpreter",9,"Interpreter::~Interpreter()" <<std::endl);
291 bbtkDebugDecTab("Interpreter",9);
293 //=======================================================================
296 //=======================================================================
300 void Interpreter::InterpretFile( const std::string& filename,
301 bool use_configuration_file)
303 bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretFile(\""<<filename<<"\")"<<std::endl);
305 bool exm = mCommandLine;
306 mCommandLine = false;
310 SwitchToFile(filename, use_configuration_file);
311 bool insideComment = false; // for multiline comment
312 while (mFile.size()>0)
314 while ((mFile.size()>0) &&
315 (!mFile.back()->eof()))
319 mFile.back()->getline(buf,500);
321 std::string str(buf);
322 int size=str.length();
323 if ( str[ size-1 ]==13 )
328 InterpretLine(str, insideComment);
330 //if (mFile.size()>0)
334 catch (QuitException e)
337 catch (bbtk::Exception e)
339 std::cerr << "* ERROR : "<<e.GetMessage()<<std::endl;
340 if (mFileName.size()) {
341 std::cerr << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
342 std::cerr << "* LINE : "<<mLine.back()<<std::endl;
345 catch (std::exception& e)
347 std::cerr << "* ERROR : "<<e.what()<<" (not in bbtk)"<<std::endl;
348 if (mFileName.size()) {
349 std::cerr << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
350 std::cerr << "* LINE : "<<mLine.back()<<std::endl;
355 std::cout << "* UNDEFINED ERROR (not a bbtk nor a std exception)"<<std::endl;
356 if (mFileName.size()) {
357 std::cout << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
358 std::cout << "* LINE : "<<mLine.back()<<std::endl;
363 bbtkDebugMessage("Interpreter",9,"EO Interpreter::InterpretFile(\""<<filename<<"\")"<<std::endl);
364 bbtkDecTab("Interpreter",9);
368 //=======================================================================
372 //=======================================================================
376 void Interpreter::InterpretLine( const std::string& line, bool &insideComment )
379 bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretLine(\""<<line<<"\")"<<std::endl);
380 bbtkMessage("Echo",2,"\""<<line<<"\""<<std::endl);
382 std::vector<std::string> words;
383 SplitLine(line,words);
388 bbtkDebugDecTab("Interpreter",9);
392 // Single line comment : # or //
393 if ( words[0][0]=='#' || (words[0][0]=='/' && words[0][1]=='/') )
395 bbtkDebugDecTab("Interpreter",9);
396 bbtkMessage("Interpreter",9,"Comment"<<std::endl);
400 // Multi line comment ( /* ... */ ) -delimiters on different lines !-
402 if (words[0][0]=='/' && words[0][1]=='*')
404 bbtkDebugDecTab("Interpreter",9);
405 bbtkMessage("Interpreter",9,"In multiline comment"<<std::endl);
406 insideComment = true;
410 if (words[0][0]=='*' && words[0][1]=='/')
412 bbtkDebugDecTab("Interpreter",9);
413 bbtkMessage("Interpreter",9,"Out multiline comment"<<std::endl);
414 if ( !insideComment ) {
415 bbtkDebugDecTab("Interpreter",9);
416 bbtkMessage("Interpreter",9,"Comment mismatch : '*/' with no matching '/*'"<<std::endl);
418 insideComment = false;
424 bbtkDebugDecTab("Interpreter",9);
425 bbtkMessage("Interpreter",9,"Multiline Comment"<<std::endl);
430 CommandInfoType command;
431 InterpretCommand(words,command);
433 bbtkDebugMessage("Interpreter",9,
434 "Command='"<<command.category
435 <<"' code="<<command.code<<std::endl);
437 std::string left,right,left2,right2;
438 std::string filename;
439 switch (command.code)
442 mExecuter->Create(words[1],words[2]);
447 // mExecuter->Remove(words[1]);
451 Utilities::SplitAroundFirstDot(words[1],left,right);
452 Utilities::SplitAroundFirstDot(words[2],left2,right2);
453 mExecuter->Connect(left,right,left2,right2);
457 mExecuter->BeginPackage(words[1]);
461 mExecuter->EndPackage();
465 if (mFileName.size()>0)
467 filename = mIncludeFileName.back(); //Utilities::get_file_name(mFileName.back());
471 mExecuter->Define(words[1],"",filename);
475 mExecuter->Define(words[1],words[2],filename);
480 mExecuter->EndDefine();
484 Print(words[1]); /// \todo use mExecuter
488 if (words[1]=="freeze")
489 mExecuter->SetNoExecMode(true);
490 else if (words[1]=="unfreeze")
491 mExecuter->SetNoExecMode(false);
493 mExecuter->Update(words[1]);
497 Utilities::SplitAroundFirstDot(words[2],left,right);
498 mExecuter->DefineInput(words[1],left,right,words[3]);
502 Utilities::SplitAroundFirstDot(words[2],left,right);
503 mExecuter->DefineOutput(words[1],left,right,words[3]);
507 Utilities::SplitAroundFirstDot(words[1],left,right);
508 mExecuter->Set(left,right,words[2]);
512 mExecuter->Author(words[1]);
516 mExecuter->Category(words[1]);
521 Index("tmp_index.html");
522 else if (words.size()==2)
524 else if (words.size()==3)
525 Index(words[1],words[2]);
529 mExecuter->Description(words[1]);
539 bbtk::MessageManager::PrintInfo();
543 sscanf(words[2].c_str(),"%d",&level);
544 bbtk::MessageManager::SetMessageLevel(words[1],level);
557 this->mExecuter->Reset();
563 InterpretFile(words[1], true ); // true : better pass use_config_file
567 SwitchToFile(words[1], true ); // true : better pass use_config_file
569 // if 'source' was given
572 this->mExecuter->SetCurrentFileName(words[1]);
577 LoadPackage(words[1], true ); // true : better pass use_config_file
581 UnLoadPackage(words[1]);
585 throw QuitException();
589 if (words.size() == 2)
591 if (words[1]=="freeze") mExecuter->SetNoExecMode(true);
592 else if (words[1]=="unfreeze") mExecuter->SetNoExecMode(false);
596 mExecuter->SetWorkspaceName(words[2]);
601 bbtkInternalError("should not reach here !!!");
604 bbtkDecTab("Interpreter",9);
606 //=======================================================================
612 //=======================================================================
616 void Interpreter::SplitLine ( const std::string& str, std::vector<std::string>& tokens)
618 bbtkDebugMessageInc("Interpreter",9,"Interpreter::SplitLine(\""<<str<<"\")"<<std::endl);
620 std::string delimiters = "\"";
621 std::vector<std::string> quote;
622 Utilities::SplitString(str,delimiters,quote);
625 std::vector<std::string>::iterator i;
626 for (i=quote.begin(); i!=quote.end(); )
628 Utilities::SplitString(*i,delimiters,tokens);
632 // bbtkDebugMessage("Interpreter",0,"\""<<*i<<"\""<<std::endl);
633 tokens.push_back(*i);
638 for (i=tokens.begin(); i!=tokens.end(); ++i)
640 bbtkDebugMessage("Interpreter",9,"["<<*i<<"] ");
642 bbtkDebugMessageCont("Interpreter",9,std::endl);
644 bbtkDebugDecTab("Interpreter",9);
646 //=======================================================================
649 //=======================================================================
650 // Replaces substrings "\\n" by a real carriage return "\n"
651 void SubsBackslashN ( std::string& s )
653 std::string ss("\\n");
654 std::string::size_type pos = 0;
657 while ( pos != std::string::npos )
659 s.replace(pos,2,cr,1);
660 pos = s.find(ss, pos-1);
663 //=======================================================================
666 //=======================================================================
670 void Interpreter::Print( const std::string& str)
672 if (mExecuter->GetNoExecMode()) return;
674 bbtkDebugMessageInc("Interpreter",9,"Interpreter::SplitLine(\""<<str<<"\")"<<std::endl);
676 std::vector<std::string> chains;
677 std::string delimiters("$");
679 // Skip delimiters at beginning.
680 std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
682 if (lastPos>0) is_text = false;
684 // Find first delimiter.
685 std::string::size_type pos = str.find_first_of(delimiters, lastPos);
687 while (std::string::npos != pos || std::string::npos != lastPos)
691 // Found a text token, add it to the vector.
692 chains.push_back(str.substr(lastPos, pos - lastPos));
696 // is an output (between $$) : decode
697 std::string tok,box,output;
698 tok = str.substr(lastPos, pos - lastPos);
699 Utilities::SplitAroundFirstDot(tok,box,output);
700 chains.push_back( mExecuter->Get(box,output) );
702 // Skip delimiters. Note the "not_of"
703 lastPos = str.find_first_not_of(delimiters, pos);
704 // Find next delimiter
705 pos = str.find_first_of(delimiters, lastPos);
709 std::vector<std::string>::iterator i;
710 for (i= chains.begin(); i!=chains.end(); ++i)
712 // bbtkMessage("Echo",1,*i);
716 std::cout << std::endl;
717 bbtkDebugDecTab("Interpreter",9);
720 //=======================================================================
725 // ===================================================================================
727 void Interpreter::SwitchToFile( const std::string& name,
728 bool use_configuration_file )
730 // Note : in the following :
731 // name : the user supplied name
732 // - abreviated name e.g. scr scr.bbs
733 // - relative full name e.g. ./scr.bbs ../../scr.bbs
734 // - absolute full name e.g. /home/usrname/proj/dir/scr.bbs
735 // same for Windows, with c:, d: ...
737 // use ./directory/subdir/scrname.bbs
740 bbtkDebugMessageInc("Interpreter",9,"Interpreter::SwitchToFile( \""
741 <<name<<"\")"<<std::endl);
743 std::vector<std::string> script_paths;
744 std::string fullPathScriptName; // full path script name
745 std::string pkgname; // e.g. <scriptname>.bbs
746 std::vector<std::string> Filenames;
748 if (use_configuration_file)
750 // The following is *NOT* a debug time message :
751 // It's a user intended message.
752 // Please don't remove it.
753 bbtkMessage("Interpreter",1,
754 "look for : [" << name
755 << "] (use_configuration_file == TRUE)" << std::endl);
756 script_paths = ConfigurationFile::GetInstance().Get_bbs_paths();
759 pkgname = Utilities::ExtractScriptName(name,upath);
761 bool fullnameGiven = false;
762 bool foundFile = false;
764 if(pkgname == "*") // =========================================== load all boxes (e.g. std/boxes/*)
768 if (upath[0]=='/' || upath[1] == ':' ) // ==== absolute name, load all .bbs files
770 int nbFiles = Utilities::Explore(upath, false, Filenames);
772 for (std::vector<std::string>::iterator i = Filenames.begin(); i!= Filenames.end(); ++i)
774 if ((*i).substr((*i).size()-4, 4) != ".bbs")
775 continue; // ignore non .bbs files
780 bbtkMessage("Interpreter",2,
781 "WARNING : No '.bbs' file found in ["
782 << 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;
851 fullPathScriptName = Utilities::ExpandLibName(name, false);
853 // allow user to always forget ".bbs"
854 int l = fullPathScriptName.size();
860 if (fullPathScriptName.substr(l-4, 4) != ".bbs")
862 fullPathScriptName = fullPathScriptName + ".bbs";
867 fullPathScriptName = fullPathScriptName + ".bbs";
870 if ( Utilities::FileExists(fullPathScriptName))
878 // =============================================================== iterate on the paths
881 std::vector<std::string>::iterator i;
882 for (i=script_paths.begin();i!=script_paths.end();++i)
886 // we *really* want '.' to be the current working directory
888 char buf[2048]; // for getcwd
889 char * currentDir = getcwd(buf, 2048);
890 std::string cwd(currentDir);
894 // fullPathScriptName = Utilities::MakePkgnameFromPath(path, name, true); //pkgname);
896 fullPathScriptName = Utilities::MakePkgnameFromPath(path, name, true);
899 // Check if library exists
900 if ( ! Utilities::FileExists(fullPathScriptName) )
902 // The following is *NOT* a debug time message :
903 // It's a user intended message.
904 // Please don't remove it.
905 bbtkMessage("Interpreter",2,
906 " [" <<fullPathScriptName <<"] : doesn't exist"
908 continue; // try next path
910 bbtkMessage("Interpreter",2,
911 " [" <<fullPathScriptName
912 <<"] : found" <<std::endl);
914 break; // a script was found; we stop iterating
916 } //------------------ // end for ( package_paths.begin();i!=package_paths.end() )
922 if(fullPathScriptName == "")
923 bbtkError("Path ["<<upath<<"] doesn't exist");
925 bbtkError("Script ["<<fullPathScriptName<<"] not found");
927 bbtkError("No ["<<pkgname<<".bbs] script found");
931 LoadScript(fullPathScriptName,name);
937 //=======================================================================
939 void Interpreter::LoadScript( std::string fullPathScriptName,
940 std::string includeScriptName)
942 if (find(mFileName.begin(),mFileName.end(),fullPathScriptName)
945 bbtkMessage("Interpreter",1,"file '"<<fullPathScriptName
946 <<"' already open : I do not open it once more to prevent recursive inclusion"<<std::endl);
951 s = new std::ifstream;
952 s->open(fullPathScriptName.c_str());
955 bbtkError("Could not open file ["<<fullPathScriptName<<"]");
959 bbtkMessage("Interpreter",1," -->[" << fullPathScriptName
960 << "] found" << std::endl);
963 mFileName.push_back(fullPathScriptName);
964 mIncludeFileName.push_back(includeScriptName);
969 //=======================================================================
973 void Interpreter::CloseCurrentFile()
975 bbtkDebugMessage("Interpreter",9,"Interpreter::CloseCurrentFile()"
980 bbtkDebugMessage("Interpreter",9," -> no file left open"<<std::endl);
984 mFile.back()->close();
987 bbtkDebugMessage("Interpreter",9,
988 " Closing file '"<<mFileName.back()<<"'"<<std::endl);
990 mFileName.pop_back();
991 mIncludeFileName.pop_back();
993 bbtkDebugMessage("Interpreter",9," Remains "
995 <<" open"<<std::endl);
996 bbtkDebugMessage("Interpreter",9,"EO Interpreter::CloseCurrentFile()"
999 //=======================================================================
1001 //=======================================================================
1005 void Interpreter::CloseAllFiles()
1007 bbtkDebugMessage("Interpreter",9,"Interpreter::CloseAllFiles()"
1010 while (mFile.size() != 0)
1012 mFile.back()->close();
1013 delete mFile.back();
1015 bbtkDebugMessage("Interpreter",9,
1016 " Closing file '"<<mFileName.back()<<"'"<<std::endl);
1017 mFileName.pop_back();
1018 mIncludeFileName.pop_back();
1021 bbtkDebugMessage("Interpreter",9,"EO Interpreter::CloseAllFiles()"
1024 //=======================================================================
1028 //=======================================================================
1032 void Interpreter::InterpretCommand( const std::vector<std::string>& words,
1033 CommandInfoType& info )
1035 bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretCommand(...)"<<std::endl);
1037 // searches the command category
1038 CommandDictType::iterator c;
1039 c = mCommandDict.find(words[0]);
1040 if ( c == mCommandDict.end() ) {
1041 bbtkError(words[0]<<" : unknown command");
1044 // tests the number of args
1045 if ( ( words.size()-1 < c->second.argmin ) ||
1046 ( words.size()-1 > c->second.argmax ) )
1048 HelpCommand(words[0]);
1049 bbtkError(words[0]<<" : wrong number of arguments");
1053 bbtkDecTab("Interpreter",9);
1055 //=======================================================================
1058 //=======================================================================
1059 /// Displays help on all the commands
1060 void Interpreter::Help(const std::vector<std::string>& words)
1062 unsigned int nbarg = words.size()-1;
1070 if (words[1]=="packages")
1072 PrintPackages(true);
1077 HelpCommand(words[1]);
1079 catch (bbtk::Exception e)
1083 HelpPackage(words[1]);
1084 #ifdef _USE_WXWIDGETS_
1085 if ( WxConsole::GetInstance() != 0 )
1088 ConfigurationFile::GetInstance().Get_doc_path();
1089 url += "/bbdoc/" + words[1] + "/index.html";
1090 if (Utilities::FileExists(url))
1092 WxConsole::GetInstance()->ShowHtmlPage(url);
1097 catch (bbtk::Exception f)
1101 std::string package;
1102 HelpBlackBox(words[1],package);
1103 #ifdef _USE_WXWIDGETS_
1104 if ( WxConsole::GetInstance() != 0 )
1107 ConfigurationFile::GetInstance().Get_doc_path();
1108 url += "/bbdoc/" + package + "/index.html";
1109 if (Utilities::FileExists(url))
1111 url += "#" + words[1];
1112 WxConsole::GetInstance()->ShowHtmlPage(url);
1117 catch (bbtk::Exception g)
1121 this->mExecuter->ShowRelations(words[1],"0","9999");
1123 catch (bbtk::Exception h){
1124 bbtkError("\""<<words[1].c_str()
1125 <<"\" is not a known command, package, black box type or black box name");
1133 if (words[2]=="all")
1135 if ( words[1]=="packages" )
1137 PrintPackages(true,true);
1142 HelpPackage(words[1],true);
1144 catch (bbtk::Exception f)
1150 HelpCommand(words[0]);
1151 bbtkError(words[0]<<" : syntax error");
1156 bbtkError("Should not reach here !!!");
1159 //=======================================================================
1161 //===================================================================
1162 /// Displays the Configuration
1163 void Interpreter::Config() const
1165 ConfigurationFile::GetInstance().GetHelp(1);
1167 //===================================================================
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();
1266 read ( STDIN_FILENO, &c, 4) ;
1268 bbtkDebugMessage("Debug",9,"[0x"<<std::hex<<c<<"]\n");
1270 // Printable character
1271 if ( (ind<MAX_LINE_SIZE-1) &&
1272 ( c >= BBTK_SPACE_KBCODE ) &&
1273 ( c < BBTK_DEL_KBCODE ))
1281 // delete the unused line
1287 // empty lines are not stored in from history
1290 // if history too long : delete oldest command
1291 if (mHistory.size()>MAX_HISTORY_SIZE)
1293 delete mHistory.front();
1294 mHistory.pop_front();
1296 mHistory.push_back(line);
1301 else if ( (ind>0) &&
1302 ((c == BBTK_BACKSPACE_KBCODE) ||
1303 (c == BBTK_DEL_KBCODE)) )
1311 // TODO : Command completion
1312 std::vector<std::string> commands;
1313 FindCommandsWithPrefix( line,ind,commands);
1314 if (commands.size()==1)
1316 std::string com = *commands.begin();
1317 for (; ind<com.size(); ++ind)
1319 PrintChar(com[ind]);
1325 else if (commands.size()>1)
1327 std::vector<std::string>::iterator i;
1329 for (i=commands.begin();i!=commands.end();++i)
1331 write(STDOUT_FILENO,(*i).c_str(),strlen((*i).c_str()));
1334 write(STDOUT_FILENO,"\n> ",3);
1335 //for (int j=0;j<ind;++j)
1337 write(STDOUT_FILENO,line,ind);
1341 // Arrow up : back in history
1342 else if (c==BBTK_UP_ARROW_KBCODE)
1346 // erase current line
1347 while (ind--) BackSpace();
1351 strcpy(histline,mHistory[hist]);
1355 write(STDOUT_FILENO,line,ind);
1358 // Arrow down : down in history
1359 else if (c==BBTK_DOWN_ARROW_KBCODE)
1361 if (hist<mHistory.size()-1)
1363 // erase current line
1364 while (ind--) BackSpace();
1368 strcpy(histline,mHistory[hist]);
1372 write(STDOUT_FILENO,line,ind);
1374 // end of history : switch back to newline
1375 else if (hist==mHistory.size()-1)
1377 // erase current line
1378 while (ind--) BackSpace();
1385 write(STDOUT_FILENO,line,ind);
1389 else if (line[ind]!=0 && c==BBTK_RIGHT_ARROW_KBCODE)
1391 PrintChar(line[ind]);
1396 else if (ind>0 && c==BBTK_LEFT_ARROW_KBCODE)
1404 write(STDOUT_FILENO,"\n\r",2);
1412 //=======================================================================
1413 void Interpreter::GetLineFromPrompt(std::string& s)
1439 //=======================================================================
1445 //=======================================================================
1446 void Interpreter::CommandLineInterpreter()
1448 bbtkDebugMessageInc("Interpreter",9,
1449 "Interpreter::CommandLineInterpreter()"<<std::endl);
1451 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1452 // Initialise the tty in non canonical mode with no echo
1453 // oter remembers the previous settings to restore them after
1454 struct termios ter,oter;
1457 ter.c_lflag &= ~ECHO;
1458 ter.c_lflag &= ~ICANON;
1461 tcsetattr(0,TCSANOW,&ter);
1464 mCommandLine = true;
1466 bool insideComment = false; // for multiline comment
1472 GetLineFromPrompt(line);
1473 InterpretLine(line, insideComment);
1475 catch (QuitException e)
1479 catch (bbtk::Exception e)
1483 catch (std::exception& e)
1485 std::cerr << "* ERROR :: "<<e.what()<<" (not in bbtk)"<<std::endl;
1489 std::cerr << "* UNDEFINED ERROR (not a bbtk nor a std exception)"<<std::endl;
1494 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1495 tcsetattr(0,TCSANOW,&oter);
1498 std::cout << "Good bye !" << std::endl;
1500 bbtkDebugDecTab("Interpreter",9);
1503 //=======================================================================
1504 void Interpreter::Graph(const std::vector<std::string>& words)
1507 bool system_display = true;
1509 #ifdef _USE_WXWIDGETS_
1510 if ( WxConsole::GetInstance() != 0 ) system_display = false;
1513 if (words.size()==1)
1515 page = mExecuter->ShowGraph(".","0","0","","","",system_display);
1517 else if (words.size()==2)
1519 page = mExecuter->ShowGraph(words[1],"0","0","","","",system_display);
1521 else if (words.size()==3)
1523 page = mExecuter->ShowGraph(words[1],words[2],"0","","","",system_display);
1525 else if (words.size()==4)
1527 page = mExecuter->ShowGraph(words[1],words[2],words[3],"","","",system_display);
1529 else if (words.size()==5)
1531 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],"","",system_display);
1533 else if (words.size()==6)
1535 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],"",system_display);
1537 else if (words.size()==7)
1539 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],words[6],system_display);
1542 #ifdef _USE_WXWIDGETS_
1543 if ( WxConsole::GetInstance() != 0 )
1544 WxConsole::GetInstance()->ShowHtmlPage(page);
1547 //=======================================================================
1550 //=======================================================================
1551 void Interpreter::Index(const std::string& filename,
1552 const std::string& type)
1554 Factory::IndexEntryType t;
1555 if (type=="Initials") t = Factory::Initials;
1556 else if (type=="Categories") t = Factory::Categories;
1557 else if (type=="Packages") t = Factory::Packages;
1559 GetGlobalFactory()->CreateHtmlIndex(t,filename);
1561 //=======================================================================