1 /*=========================================================================
4 Module: $RCSfile: bbtkInterpreter.cxx,v $ $
6 Date: $Date: 2008/02/20 11:58:32 $
7 Version: $Revision: 1.35 $
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"
30 #ifdef CMAKE_HAVE_TERMIOS_H
32 #define BBTK_USE_TERMIOS_BASED_PROMPT
40 Interpreter* Interpreter::mGlobalInterpreter = NULL;
42 //=======================================================================
46 Interpreter::Interpreter()
50 bbtk::MessageManager::RegisterMessageType("Echo","Level>0 : Prints the 'echo' commands of the user.\n\tLevel>1 : Prints the command being interpreted",1);
51 bbtk::MessageManager::RegisterMessageType("Interpreter","Messages of the interpreter",0);
52 bbtkDebugMessageInc("Interpreter",9,"Interpreter::Interpreter()" <<std::endl);
54 mGlobalInterpreter = this;
56 mExecuter = new bbtk::Executer();
58 // For the time being, comment out previous line, and
59 // uncomment next line to check Transcriptor
61 // mExecuter = new bbtk::Transcriptor("GeneratedProgram.txt");
63 // Builds the commands dict
66 info.category = "new";
70 info.syntax = "new <type> <name>";
71 info.help = "Creates a new black box of type <type> with name <name>";
72 mCommandDict[info.category] = info;
74 info.category = "delete";
78 info.syntax = "delete <box>";
79 info.help = "Deletes the black box of name <box>";
80 mCommandDict[info.category] = info;
82 info.category = "connect";
86 info.syntax = "connect <box1.output> <box2.input>";
87 info.help = "Connects the ouput <output> of black box <box1> to the input <input> of black box <box2>";
88 mCommandDict[info.category] = info;
90 info.category = "print";
94 info.syntax = "print <string>";
95 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').";
96 mCommandDict[info.category] = info;
98 info.category = "exec";
102 info.syntax = "exec <box | 'freeze' | 'unfreeze' >";
103 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.";
104 mCommandDict[info.category] = info;
106 info.category = "package";
109 info.code = cPackage;
110 info.syntax = "package <name>";
111 info.help = "Begins the definition of a package.";
112 mCommandDict[info.category] = info;
114 info.category = "endpackage";
117 info.code = cEndPackage;
118 info.syntax = "endpackage";
119 info.help = "Ends the definition of a package.";
120 mCommandDict[info.category] = info;
122 info.category = "define";
126 info.syntax = "define <type> [<package>]";
127 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.";
128 mCommandDict[info.category] = info;
130 info.category = "endefine";
133 info.code = cEndDefine;
134 info.syntax = "endefine";
135 info.help = "Ends the definition of a new type of complex black box";
136 mCommandDict[info.category] = info;
138 info.category = "input";
142 info.syntax = "input <name> <box.input> <help>";
143 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";
144 mCommandDict[info.category] = info;
146 info.category = "output";
150 info.syntax = "output <name> <box.output> <help>";
151 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";
152 mCommandDict[info.category] = info;
154 info.category = "set";
158 info.syntax = "set <box.input> <value>";
159 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";
160 mCommandDict[info.category] = info;
162 info.category = "config"; // JPR
166 info.syntax = "config";
167 info.help = "Prints the value of all configuration parameters";
168 mCommandDict[info.category] = info;
170 info.category = "index"; // LG
175 info.syntax = "index [<filename> ['Initials'(default)|'Packages'|'Categories']]";
176 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";
177 mCommandDict[info.category] = info;
179 info.category = "reset"; //EED
183 info.syntax = "reset";
184 info.help = "Deletes all boxes and unloads all packages (bbi is reset to its start state)";
185 mCommandDict[info.category] = info;
187 info.category = "author";
191 info.syntax = "author <string>";
192 info.help = "Adds the string <string> to the author information of the black box being defined";
193 mCommandDict[info.category] = info;
195 info.category = "category"; //JP
198 info.code = cCategory;
199 info.syntax = "category <list of items, separated by ;>";
200 info.help = "Adds the string <string> to the category information of the black box being defined";
201 mCommandDict[info.category] = info;
203 info.category = "description";
206 info.code = cDescription;
207 info.syntax = "description <string>";
208 info.help = "Adds the string <string> to the descriptive information of the black box being defined";
209 mCommandDict[info.category] = info;
211 info.category = "help";
215 info.syntax = "help";
216 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>";
217 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.";
218 mCommandDict[info.category] = info;
220 info.category = "message";
223 info.code = cMessage;
224 info.syntax = "message <kind> <level>";
225 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;
227 info.category = "include";
230 info.code = cInclude;
231 info.syntax = "include <filename> [source]";
232 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).";
233 mCommandDict[info.category] = info;
235 info.category = "quit";
239 info.syntax = "quit";
240 info.help = "Quits the program (during script execution it stops the complete execution)";
241 mCommandDict[info.category] = info;
243 info.category = "load";
247 info.syntax = "load <packagename>";
248 info.help = "Loads the black box package <packagename>";
249 mCommandDict[info.category] = info;
251 info.category = "unload";
255 info.syntax = "unload <packagename>";
256 info.help = "Unloads the black box package <packagename>";
257 mCommandDict[info.category] = info;
259 info.category = "graph";
263 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 ]]]]]]";
264 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')";
265 mCommandDict[info.category] = info;
268 info.category = "workspace";
271 info.code = cWorkspace;
272 info.syntax = "workspace < ( freeze | unfreeze ) | ( rename <newname> ) >";
273 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.";
274 mCommandDict[info.category] = info;
277 bbtkDebugDecTab("Interpreter",9);
280 //=======================================================================
284 //=======================================================================
288 Interpreter::~Interpreter()
290 bbtkDebugMessageInc("Interpreter",9,"Interpreter::~Interpreter()" <<std::endl);
294 bbtkDebugDecTab("Interpreter",9);
296 //=======================================================================
299 //=======================================================================
303 void Interpreter::InterpretFile( const std::string& filename,
304 bool use_configuration_file)
306 bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretFile(\""<<filename<<"\")"<<std::endl);
308 bool exm = mCommandLine;
309 mCommandLine = false;
313 printf("EED: Interpreter::InterpretFile 01\n");
314 InterpretLine("message ALL 9", exm);
315 SwitchToFile(filename, use_configuration_file);
316 bool insideComment = false; // for multiline comment
317 while (mFile.size()>0)
319 while ((mFile.size()>0) &&
320 (!mFile.back()->eof()))
324 mFile.back()->getline(buf,500);
326 std::string str(buf);
327 int size=str.length();
328 if ( str[ size-1 ]==13 )
333 InterpretLine(str, insideComment);
335 //if (mFile.size()>0)
339 catch (QuitException e)
342 catch (bbtk::Exception e)
344 std::cerr << "* ERROR : "<<e.GetMessage()<<std::endl;
345 if (mFileName.size()) {
346 std::cerr << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
347 std::cerr << "* LINE : "<<mLine.back()<<std::endl;
350 catch (std::exception& e)
352 std::cerr << "* ERROR : "<<e.what()<<" (not in bbtk)"<<std::endl;
353 if (mFileName.size()) {
354 std::cerr << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
355 std::cerr << "* LINE : "<<mLine.back()<<std::endl;
360 std::cout << "* UNDEFINED ERROR (not a bbtk nor a std exception)"<<std::endl;
361 if (mFileName.size()) {
362 std::cout << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
363 std::cout << "* LINE : "<<mLine.back()<<std::endl;
368 bbtkDebugMessage("Interpreter",9,"EO Interpreter::InterpretFile(\""<<filename<<"\")"<<std::endl);
369 bbtkDecTab("Interpreter",9);
372 printf("EED: Interpreter::InterpretFile 02\n");
374 //=======================================================================
378 //=======================================================================
382 void Interpreter::InterpretLine( const std::string& line, bool &insideComment )
385 bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretLine(\""<<line<<"\")"<<std::endl);
386 bbtkMessage("Echo",2,"\""<<line<<"\""<<std::endl);
388 std::vector<std::string> words;
389 SplitLine(line,words);
394 bbtkDebugDecTab("Interpreter",9);
398 // Single line comment : # or //
399 if ( words[0][0]=='#' || (words[0][0]=='/' && words[0][1]=='/') )
401 bbtkDebugDecTab("Interpreter",9);
402 bbtkMessage("Interpreter",9,"Comment"<<std::endl);
406 // Multi line comment ( /* ... */ ) -delimiters on different lines !-
408 if (words[0][0]=='/' && words[0][1]=='*')
410 bbtkDebugDecTab("Interpreter",9);
411 bbtkMessage("Interpreter",9,"In multiline comment"<<std::endl);
412 insideComment = true;
416 if (words[0][0]=='*' && words[0][1]=='/')
418 bbtkDebugDecTab("Interpreter",9);
419 bbtkMessage("Interpreter",9,"Out multiline comment"<<std::endl);
420 if ( !insideComment ) {
421 bbtkDebugDecTab("Interpreter",9);
422 bbtkMessage("Interpreter",9,"Comment mismatch : '*/' with no matching '/*'"<<std::endl);
424 insideComment = false;
430 bbtkDebugDecTab("Interpreter",9);
431 bbtkMessage("Interpreter",9,"Multiline Comment"<<std::endl);
436 CommandInfoType command;
437 InterpretCommand(words,command);
439 bbtkDebugMessage("Interpreter",9,
440 "Command='"<<command.category
441 <<"' code="<<command.code<<std::endl);
443 std::string left,right,left2,right2;
444 std::string filename;
445 switch (command.code)
448 mExecuter->Create(words[1],words[2]);
453 // mExecuter->Remove(words[1]);
457 Utilities::SplitAroundFirstDot(words[1],left,right);
458 Utilities::SplitAroundFirstDot(words[2],left2,right2);
459 mExecuter->Connect(left,right,left2,right2);
463 mExecuter->BeginPackage(words[1]);
467 mExecuter->EndPackage();
471 if (mFileName.size()>0)
473 filename = mIncludeFileName.back(); //Utilities::get_file_name(mFileName.back());
477 mExecuter->Define(words[1],"",filename);
481 mExecuter->Define(words[1],words[2],filename);
486 mExecuter->EndDefine();
490 Print(words[1]); /// \todo use mExecuter
494 if (words[1]=="freeze")
495 mExecuter->SetNoExecMode(true);
496 else if (words[1]=="unfreeze")
497 mExecuter->SetNoExecMode(false);
499 mExecuter->Update(words[1]);
503 Utilities::SplitAroundFirstDot(words[2],left,right);
504 mExecuter->DefineInput(words[1],left,right,words[3]);
508 Utilities::SplitAroundFirstDot(words[2],left,right);
509 mExecuter->DefineOutput(words[1],left,right,words[3]);
513 Utilities::SplitAroundFirstDot(words[1],left,right);
514 mExecuter->Set(left,right,words[2]);
518 mExecuter->Author(words[1]);
522 mExecuter->Category(words[1]);
527 Index("tmp_index.html");
528 else if (words.size()==2)
530 else if (words.size()==3)
531 Index(words[1],words[2]);
535 mExecuter->Description(words[1]);
545 bbtk::MessageManager::PrintInfo();
549 sscanf(words[2].c_str(),"%d",&level);
550 bbtk::MessageManager::SetMessageLevel(words[1],level);
563 this->mExecuter->Reset();
569 InterpretFile(words[1], true ); // true : better pass use_config_file
573 SwitchToFile(words[1], true ); // true : better pass use_config_file
575 // if 'source' was given
578 this->mExecuter->SetCurrentFileName(words[1]);
583 LoadPackage(words[1], true ); // true : better pass use_config_file
587 UnLoadPackage(words[1]);
592 throw QuitException();
596 if (words.size() == 2)
598 if (words[1]=="freeze") mExecuter->SetNoExecMode(true);
599 else if (words[1]=="unfreeze") mExecuter->SetNoExecMode(false);
603 mExecuter->SetWorkspaceName(words[2]);
608 bbtkInternalError("should not reach here !!!");
611 bbtkDecTab("Interpreter",9);
613 //=======================================================================
619 //=======================================================================
623 void Interpreter::SplitLine ( const std::string& str, std::vector<std::string>& tokens)
625 bbtkDebugMessageInc("Interpreter",9,"Interpreter::SplitLine(\""<<str<<"\")"<<std::endl);
627 std::string delimiters = "\"";
628 std::vector<std::string> quote;
629 Utilities::SplitString(str,delimiters,quote);
632 std::vector<std::string>::iterator i;
633 for (i=quote.begin(); i!=quote.end(); )
635 Utilities::SplitString(*i,delimiters,tokens);
639 // bbtkDebugMessage("Interpreter",0,"\""<<*i<<"\""<<std::endl);
640 tokens.push_back(*i);
645 for (i=tokens.begin(); i!=tokens.end(); ++i)
647 bbtkDebugMessage("Interpreter",9,"["<<*i<<"] ");
649 bbtkDebugMessageCont("Interpreter",9,std::endl);
651 bbtkDebugDecTab("Interpreter",9);
653 //=======================================================================
656 //=======================================================================
657 // Replaces substrings "\\n" by a real carriage return "\n"
658 void SubsBackslashN ( std::string& s )
660 std::string ss("\\n");
661 std::string::size_type pos = 0;
664 while ( pos != std::string::npos )
666 s.replace(pos,2,cr,1);
667 pos = s.find(ss, pos-1);
670 //=======================================================================
673 //=======================================================================
677 void Interpreter::Print( const std::string& str)
679 if (mExecuter->GetNoExecMode()) return;
681 bbtkDebugMessageInc("Interpreter",9,"Interpreter::SplitLine(\""<<str<<"\")"<<std::endl);
683 std::vector<std::string> chains;
684 std::string delimiters("$");
686 // Skip delimiters at beginning.
687 std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
689 if (lastPos>0) is_text = false;
691 // Find first delimiter.
692 std::string::size_type pos = str.find_first_of(delimiters, lastPos);
694 while (std::string::npos != pos || std::string::npos != lastPos)
698 // Found a text token, add it to the vector.
699 chains.push_back(str.substr(lastPos, pos - lastPos));
703 // is an output (between $$) : decode
704 std::string tok,box,output;
705 tok = str.substr(lastPos, pos - lastPos);
706 Utilities::SplitAroundFirstDot(tok,box,output);
707 chains.push_back( mExecuter->Get(box,output) );
709 // Skip delimiters. Note the "not_of"
710 lastPos = str.find_first_not_of(delimiters, pos);
711 // Find next delimiter
712 pos = str.find_first_of(delimiters, lastPos);
716 std::vector<std::string>::iterator i;
717 for (i= chains.begin(); i!=chains.end(); ++i)
719 // bbtkMessage("Echo",1,*i);
723 std::cout << std::endl;
724 bbtkDebugDecTab("Interpreter",9);
727 //=======================================================================
732 // ===================================================================================
734 void Interpreter::SwitchToFile( const std::string& name,
735 bool use_configuration_file )
737 // Note : in the following :
738 // name : the user supplied name
739 // - abreviated name e.g. scr scr.bbs
740 // - relative full name e.g. ./scr.bbs ../../scr.bbs
741 // - absolute full name e.g. /home/usrname/proj/dir/scr.bbs
742 // same for Windows, with c:, d: ...
744 // use ./directory/subdir/scrname.bbs
747 bbtkDebugMessageInc("Interpreter",9,"Interpreter::SwitchToFile( \""
748 <<name<<"\")"<<std::endl);
750 std::vector<std::string> script_paths;
751 std::string fullPathScriptName; // full path script name
752 std::string pkgname; // e.g. <scriptname>.bbs
753 std::vector<std::string> Filenames;
755 if (use_configuration_file)
757 // The following is *NOT* a debug time message :
758 // It's a user intended message.
759 // Please don't remove it.
760 bbtkMessage("Interpreter",1,
761 "look for : [" << name
762 << "] (use_configuration_file == TRUE)" << std::endl);
763 script_paths = ConfigurationFile::GetInstance().Get_bbs_paths();
766 pkgname = Utilities::ExtractScriptName(name,upath);
768 bool fullnameGiven = false;
769 bool foundFile = false;
771 if(pkgname == "*") // =========================================== load all boxes (e.g. std/boxes/*)
775 if (upath[0]=='/' || upath[1] == ':' ) // ==== absolute name, load all .bbs files
777 int nbFiles = Utilities::Explore(upath, false, Filenames);
779 for (std::vector<std::string>::iterator i = Filenames.begin(); i!= Filenames.end(); ++i)
781 if ((*i).substr((*i).size()-4, 4) != ".bbs")
782 continue; // ignore non .bbs files
787 bbtkMessage("Interpreter",2,
788 "WARNING : No '.bbs' file found in ["
789 << upath << "]" << std::endl);
794 std::vector<std::string>::iterator i;
795 std::string fullDirectoryName;
796 for (i=script_paths.begin();i!=script_paths.end();i++)// ==== relative name, iterate + load all .bbs files
800 // we *really* want '.' to be the current working directory
802 char buf[2048]; // for getcwd
803 char * currentDir = getcwd(buf, 2048);
804 std::string cwd(currentDir);
808 fullDirectoryName = Utilities::MakePkgnameFromPath(path, upath, false);
811 // without last slash "\"
812 std::string fullDirectoryNameClean = fullDirectoryName.substr(0,fullDirectoryName.size()-1);
814 // Check if library exists
815 if ( ! Utilities::IsDirectory( fullDirectoryNameClean ) )
817 // The following is *NOT* a debug time message :
818 // It's a user intended message.
819 // Please don't remove it.
820 bbtkMessage("Interpreter",1," [" <<fullDirectoryName
821 <<"] : doesn't exist" <<std::endl);
822 continue; // try next path
827 int nbFiles = Utilities::Explore(fullDirectoryName, false, Filenames);
830 for (std::vector<std::string>::iterator i = Filenames.begin(); i!= Filenames.end(); ++i)
832 if ((*i).substr((*i).size()-4, 4) != ".bbs")
833 continue; // ignore non .bbs files
838 bbtkMessage("Interpreter",1,
839 "WARNING : No '.bbs' file found in ["
840 << fullDirectoryName << "]" << std::endl);
842 //break; // a directory was found; we stop iterating
843 // LG : No! We want all files included !
848 //std::string::size_type slash_position = name.find_last_of("/\\");
850 // if name starts with a / or a . or contains : user is assumed to have passed a relative/absolute name
851 // (not only a plain script name)
852 // we trust him, and try to expland the directory name
853 // WARNING : starting from current local directory : ./whatYouWant (./ mandatory!)
855 if (name[0]=='/' || name[1] == ':' || name[0]=='.') // absolute path (linux/windows) or relative path
858 // ===========================================================check user supplied location
859 fullnameGiven = true;
861 fullPathScriptName = Utilities::ExpandLibName(name, false);
863 // allow user to always forget ".bbs"
864 int l = fullPathScriptName.size();
870 if (fullPathScriptName.substr(l-4, 4) != ".bbs")
872 fullPathScriptName = fullPathScriptName + ".bbs";
877 fullPathScriptName = fullPathScriptName + ".bbs";
880 if ( Utilities::FileExists(fullPathScriptName))
888 // =============================================================== iterate on the paths
891 std::vector<std::string>::iterator i;
892 for (i=script_paths.begin();i!=script_paths.end();++i)
896 // we *really* want '.' to be the current working directory
898 char buf[2048]; // for getcwd
899 char * currentDir = getcwd(buf, 2048);
900 std::string cwd(currentDir);
904 // fullPathScriptName = Utilities::MakePkgnameFromPath(path, name, true); //pkgname);
906 fullPathScriptName = Utilities::MakePkgnameFromPath(path, name, true);
909 // Check if library exists
910 if ( ! Utilities::FileExists(fullPathScriptName) )
912 // The following is *NOT* a debug time message :
913 // It's a user intended message.
914 // Please don't remove it.
915 bbtkMessage("Interpreter",2,
916 " [" <<fullPathScriptName <<"] : doesn't exist"
918 continue; // try next path
920 bbtkMessage("Interpreter",2,
921 " [" <<fullPathScriptName
922 <<"] : found" <<std::endl);
924 break; // a script was found; we stop iterating
926 } //------------------ // end for ( package_paths.begin();i!=package_paths.end() )
932 if(fullPathScriptName == "")
933 bbtkError("Path ["<<upath<<"] doesn't exist");
935 bbtkError("Script ["<<fullPathScriptName<<"] not found");
937 bbtkError("No ["<<pkgname<<".bbs] script found");
941 LoadScript(fullPathScriptName,name);
947 //=======================================================================
949 void Interpreter::LoadScript( std::string fullPathScriptName,
950 std::string includeScriptName)
952 if (find(mFileName.begin(),mFileName.end(),fullPathScriptName)
955 bbtkMessage("Interpreter",1,"file '"<<fullPathScriptName
956 <<"' already open : I do not open it once more to prevent recursive inclusion"<<std::endl);
961 s = new std::ifstream;
962 s->open(fullPathScriptName.c_str());
965 bbtkError("Could not open file ["<<fullPathScriptName<<"]");
969 bbtkMessage("Interpreter",1," -->[" << fullPathScriptName
970 << "] found" << std::endl);
973 mFileName.push_back(fullPathScriptName);
974 mIncludeFileName.push_back(includeScriptName);
979 //=======================================================================
983 void Interpreter::CloseCurrentFile()
985 bbtkDebugMessage("Interpreter",9,"Interpreter::CloseCurrentFile()"
990 bbtkDebugMessage("Interpreter",9," -> no file left open"<<std::endl);
994 mFile.back()->close();
997 bbtkDebugMessage("Interpreter",9,
998 " Closing file '"<<mFileName.back()<<"'"<<std::endl);
1000 mFileName.pop_back();
1001 mIncludeFileName.pop_back();
1003 bbtkDebugMessage("Interpreter",9," Remains "
1005 <<" open"<<std::endl);
1006 bbtkDebugMessage("Interpreter",9,"EO Interpreter::CloseCurrentFile()"
1009 //=======================================================================
1011 //=======================================================================
1015 void Interpreter::CloseAllFiles()
1017 bbtkDebugMessage("Interpreter",9,"Interpreter::CloseAllFiles()"
1020 while (mFile.size() != 0)
1022 mFile.back()->close();
1023 delete mFile.back();
1025 bbtkDebugMessage("Interpreter",9,
1026 " Closing file '"<<mFileName.back()<<"'"<<std::endl);
1027 mFileName.pop_back();
1028 mIncludeFileName.pop_back();
1031 bbtkDebugMessage("Interpreter",9,"EO Interpreter::CloseAllFiles()"
1034 //=======================================================================
1038 //=======================================================================
1042 void Interpreter::InterpretCommand( const std::vector<std::string>& words,
1043 CommandInfoType& info )
1045 bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretCommand(...)"<<std::endl);
1047 // searches the command category
1048 CommandDictType::iterator c;
1049 c = mCommandDict.find(words[0]);
1050 if ( c == mCommandDict.end() ) {
1051 bbtkError(words[0]<<" : unknown command");
1054 // tests the number of args
1055 if ( ( words.size()-1 < c->second.argmin ) ||
1056 ( words.size()-1 > c->second.argmax ) )
1058 HelpCommand(words[0]);
1059 bbtkError(words[0]<<" : wrong number of arguments");
1063 bbtkDecTab("Interpreter",9);
1065 //=======================================================================
1068 //=======================================================================
1069 /// Displays help on all the commands
1070 void Interpreter::Help(const std::vector<std::string>& words)
1072 unsigned int nbarg = words.size()-1;
1080 if (words[1]=="packages")
1082 PrintPackages(true);
1087 HelpCommand(words[1]);
1089 catch (bbtk::Exception e)
1093 HelpPackage(words[1]);
1094 #ifdef _USE_WXWIDGETS_
1095 if ( WxConsole::GetInstance() != 0 )
1098 ConfigurationFile::GetInstance().Get_doc_path();
1099 url += "/bbdoc/" + words[1] + "/index.html";
1100 if (Utilities::FileExists(url))
1102 WxConsole::GetInstance()->ShowHtmlPage(url);
1107 catch (bbtk::Exception f)
1111 std::string package;
1112 HelpBlackBox(words[1],package);
1113 #ifdef _USE_WXWIDGETS_
1114 if ( WxConsole::GetInstance() != 0 )
1117 ConfigurationFile::GetInstance().Get_doc_path();
1118 url += "/bbdoc/" + package + "/index.html";
1119 if (Utilities::FileExists(url))
1121 url += "#" + words[1];
1122 WxConsole::GetInstance()->ShowHtmlPage(url);
1127 catch (bbtk::Exception g)
1131 this->mExecuter->ShowRelations(words[1],"0","9999");
1133 catch (bbtk::Exception h){
1134 bbtkError("\""<<words[1].c_str()
1135 <<"\" is not a known command, package, black box type or black box name");
1143 if (words[2]=="all")
1145 if ( words[1]=="packages" )
1147 PrintPackages(true,true);
1152 HelpPackage(words[1],true);
1154 catch (bbtk::Exception f)
1160 HelpCommand(words[0]);
1161 bbtkError(words[0]<<" : syntax error");
1166 bbtkError("Should not reach here !!!");
1169 //=======================================================================
1171 //===================================================================
1172 /// Displays the Configuration
1173 void Interpreter::Config() const
1175 ConfigurationFile::GetInstance().GetHelp(1);
1177 //===================================================================
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();
1276 read ( STDIN_FILENO, &c, 4) ;
1278 bbtkDebugMessage("Debug",9,"[0x"<<std::hex<<c<<"]\n");
1280 // Printable character
1281 if ( (ind<MAX_LINE_SIZE-1) &&
1282 ( c >= BBTK_SPACE_KBCODE ) &&
1283 ( c < BBTK_DEL_KBCODE ))
1291 // delete the unused line
1297 // empty lines are not stored in from history
1300 // if history too long : delete oldest command
1301 if (mHistory.size()>MAX_HISTORY_SIZE)
1303 delete mHistory.front();
1304 mHistory.pop_front();
1306 mHistory.push_back(line);
1311 else if ( (ind>0) &&
1312 ((c == BBTK_BACKSPACE_KBCODE) ||
1313 (c == BBTK_DEL_KBCODE)) )
1321 // TODO : Command completion
1322 std::vector<std::string> commands;
1323 FindCommandsWithPrefix( line,ind,commands);
1324 if (commands.size()==1)
1326 std::string com = *commands.begin();
1327 for (; ind<com.size(); ++ind)
1329 PrintChar(com[ind]);
1335 else if (commands.size()>1)
1337 std::vector<std::string>::iterator i;
1339 for (i=commands.begin();i!=commands.end();++i)
1341 write(STDOUT_FILENO,(*i).c_str(),strlen((*i).c_str()));
1344 write(STDOUT_FILENO,"\n> ",3);
1345 //for (int j=0;j<ind;++j)
1347 write(STDOUT_FILENO,line,ind);
1351 // Arrow up : back in history
1352 else if (c==BBTK_UP_ARROW_KBCODE)
1356 // erase current line
1357 while (ind--) BackSpace();
1361 strcpy(histline,mHistory[hist]);
1365 write(STDOUT_FILENO,line,ind);
1368 // Arrow down : down in history
1369 else if (c==BBTK_DOWN_ARROW_KBCODE)
1371 if (hist<mHistory.size()-1)
1373 // erase current line
1374 while (ind--) BackSpace();
1378 strcpy(histline,mHistory[hist]);
1382 write(STDOUT_FILENO,line,ind);
1384 // end of history : switch back to newline
1385 else if (hist==mHistory.size()-1)
1387 // erase current line
1388 while (ind--) BackSpace();
1395 write(STDOUT_FILENO,line,ind);
1399 else if (line[ind]!=0 && c==BBTK_RIGHT_ARROW_KBCODE)
1401 PrintChar(line[ind]);
1406 else if (ind>0 && c==BBTK_LEFT_ARROW_KBCODE)
1414 write(STDOUT_FILENO,"\n\r",2);
1422 //=======================================================================
1423 void Interpreter::GetLineFromPrompt(std::string& s)
1449 //=======================================================================
1455 //=======================================================================
1456 void Interpreter::CommandLineInterpreter()
1458 bbtkDebugMessageInc("Interpreter",9,
1459 "Interpreter::CommandLineInterpreter()"<<std::endl);
1461 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1462 // Initialise the tty in non canonical mode with no echo
1463 // oter remembers the previous settings to restore them after
1464 struct termios ter,oter;
1467 ter.c_lflag &= ~ECHO;
1468 ter.c_lflag &= ~ICANON;
1471 tcsetattr(0,TCSANOW,&ter);
1474 mCommandLine = true;
1476 bool insideComment = false; // for multiline comment
1482 GetLineFromPrompt(line);
1483 InterpretLine(line, insideComment);
1485 catch (QuitException e)
1489 catch (bbtk::Exception e)
1493 catch (std::exception& e)
1495 std::cerr << "* ERROR :: "<<e.what()<<" (not in bbtk)"<<std::endl;
1499 std::cerr << "* UNDEFINED ERROR (not a bbtk nor a std exception)"<<std::endl;
1504 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1505 tcsetattr(0,TCSANOW,&oter);
1508 std::cout << "Good bye !" << std::endl;
1510 bbtkDebugDecTab("Interpreter",9);
1513 //=======================================================================
1514 void Interpreter::Graph(const std::vector<std::string>& words)
1517 bool system_display = true;
1519 #ifdef _USE_WXWIDGETS_
1520 if ( WxConsole::GetInstance() != 0 ) system_display = false;
1523 if (words.size()==1)
1525 page = mExecuter->ShowGraph(".","0","0","","","",system_display);
1527 else if (words.size()==2)
1529 page = mExecuter->ShowGraph(words[1],"0","0","","","",system_display);
1531 else if (words.size()==3)
1533 page = mExecuter->ShowGraph(words[1],words[2],"0","","","",system_display);
1535 else if (words.size()==4)
1537 page = mExecuter->ShowGraph(words[1],words[2],words[3],"","","",system_display);
1539 else if (words.size()==5)
1541 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],"","",system_display);
1543 else if (words.size()==6)
1545 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],"",system_display);
1547 else if (words.size()==7)
1549 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],words[6],system_display);
1552 #ifdef _USE_WXWIDGETS_
1553 if ( WxConsole::GetInstance() != 0 )
1554 WxConsole::GetInstance()->ShowHtmlPage(page);
1557 //=======================================================================
1560 //=======================================================================
1561 void Interpreter::Index(const std::string& filename,
1562 const std::string& type)
1564 Factory::IndexEntryType t;
1565 if (type=="Initials") t = Factory::Initials;
1566 else if (type=="Categories") t = Factory::Categories;
1567 else if (type=="Packages") t = Factory::Packages;
1569 GetGlobalFactory()->CreateHtmlIndex(t,filename);
1571 //=======================================================================