1 /*=========================================================================
4 Module: $RCSfile: bbtkInterpreter.cxx,v $ $
6 Date: $Date: 2008/03/03 11:43:52 $
7 Version: $Revision: 1.38 $
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()
291 std::cout << "=========================================~Interpreter()" << std::endl;
292 bbtkDebugMessageInc("Interpreter",9,"Interpreter::~Interpreter()" <<std::endl);
296 bbtkDebugDecTab("Interpreter",9);
298 //=======================================================================
301 //=======================================================================
305 void Interpreter::InterpretFile( const std::string& filename )
307 bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretFile(\""<<filename<<"\")"<<std::endl);
309 bool exm = mCommandLine;
310 mCommandLine = false;
314 SwitchToFile(filename);
315 bool insideComment = false; // for multiline comment
316 while (mFile.size()>0)
318 while ((mFile.size()>0) &&
319 (!mFile.back()->eof()))
323 mFile.back()->getline(buf,500);
325 std::string str(buf);
326 int size=str.length();
327 if ( str[ size-1 ]==13 )
332 InterpretLine(str, insideComment);
334 //if (mFile.size()>0)
338 catch (QuitException e)
341 catch (bbtk::Exception e)
343 std::cerr << "* ERROR : "<<e.GetMessage()<<std::endl;
344 if (mFileName.size()) {
345 std::cerr << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
346 std::cerr << "* LINE : "<<mLine.back()<<std::endl;
349 catch (std::exception& e)
351 std::cerr << "* ERROR : "<<e.what()<<" (not in bbtk)"<<std::endl;
352 if (mFileName.size()) {
353 std::cerr << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
354 std::cerr << "* LINE : "<<mLine.back()<<std::endl;
359 std::cout << "* UNDEFINED ERROR (not a bbtk nor a std exception)"<<std::endl;
360 if (mFileName.size()) {
361 std::cout << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
362 std::cout << "* LINE : "<<mLine.back()<<std::endl;
367 bbtkDebugMessage("Interpreter",9,"EO Interpreter::InterpretFile(\""<<filename<<"\")"<<std::endl);
368 bbtkDecTab("Interpreter",9);
372 //=======================================================================
376 //=======================================================================
380 void Interpreter::InterpretLine( const std::string& line, bool &insideComment )
383 bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretLine(\""<<line<<"\")"<<std::endl);
384 bbtkMessage("Echo",2,"\""<<line<<"\""<<std::endl);
386 std::vector<std::string> words;
387 SplitLine(line,words);
392 bbtkDebugDecTab("Interpreter",9);
396 // Single line comment : # or //
397 if ( words[0][0]=='#' || (words[0][0]=='/' && words[0][1]=='/') )
399 bbtkDebugDecTab("Interpreter",9);
400 bbtkMessage("Interpreter",9,"Comment"<<std::endl);
404 // Multi line comment ( /* ... */ ) -delimiters on different lines !-
406 if (words[0][0]=='/' && words[0][1]=='*')
408 bbtkDebugDecTab("Interpreter",9);
409 bbtkMessage("Interpreter",9,"In multiline comment"<<std::endl);
410 insideComment = true;
414 if (words[0][0]=='*' && words[0][1]=='/')
416 bbtkDebugDecTab("Interpreter",9);
417 bbtkMessage("Interpreter",9,"Out multiline comment"<<std::endl);
418 if ( !insideComment ) {
419 bbtkDebugDecTab("Interpreter",9);
420 bbtkMessage("Interpreter",9,"Comment mismatch : '*/' with no matching '/*'"<<std::endl);
422 insideComment = false;
428 bbtkDebugDecTab("Interpreter",9);
429 bbtkMessage("Interpreter",9,"Multiline Comment"<<std::endl);
434 CommandInfoType command;
435 InterpretCommand(words,command);
437 bbtkDebugMessage("Interpreter",9,
438 "Command='"<<command.category
439 <<"' code="<<command.code<<std::endl);
441 std::string left,right,left2,right2;
442 std::string filename;
443 switch (command.code)
446 mExecuter->Create(words[1],words[2]);
451 // mExecuter->Remove(words[1]);
455 Utilities::SplitAroundFirstDot(words[1],left,right);
456 Utilities::SplitAroundFirstDot(words[2],left2,right2);
457 mExecuter->Connect(left,right,left2,right2);
461 mExecuter->BeginPackage(words[1]);
465 mExecuter->EndPackage();
469 if (mFileName.size()>0)
471 filename = mIncludeFileName.back(); //Utilities::get_file_name(mFileName.back());
475 mExecuter->Define(words[1],"",filename);
479 mExecuter->Define(words[1],words[2],filename);
484 mExecuter->EndDefine();
488 Print(words[1]); /// \todo use generate command
492 if (words[1]=="freeze")
493 mExecuter->SetNoExecMode(true);
494 else if (words[1]=="unfreeze")
495 mExecuter->SetNoExecMode(false);
497 mExecuter->Update(words[1]);
501 Utilities::SplitAroundFirstDot(words[2],left,right);
502 mExecuter->DefineInput(words[1],left,right,words[3]);
506 Utilities::SplitAroundFirstDot(words[2],left,right);
507 mExecuter->DefineOutput(words[1],left,right,words[3]);
511 Utilities::SplitAroundFirstDot(words[1],left,right);
512 mExecuter->Set(left,right,words[2]);
516 mExecuter->Author(words[1]);
520 mExecuter->Category(words[1]);
525 Index("tmp_index.html");
526 else if (words.size()==2)
528 else if (words.size()==3)
529 Index(words[1],words[2]);
533 mExecuter->Description(words[1]);
543 bbtk::MessageManager::PrintInfo();
547 sscanf(words[2].c_str(),"%d",&level);
548 bbtk::MessageManager::SetMessageLevel(words[1],level);
561 this->mExecuter->Reset();
567 InterpretFile(words[1]);
571 SwitchToFile(words[1]);
573 // if 'source' was given
576 this->mExecuter->SetCurrentFileName(words[1]);
581 LoadPackage(words[1]);
585 UnLoadPackage(words[1]);
590 throw QuitException();
594 if (words.size() == 2)
596 if (words[1]=="freeze") mExecuter->SetNoExecMode(true);
597 else if (words[1]=="unfreeze") mExecuter->SetNoExecMode(false);
601 mExecuter->SetWorkspaceName(words[2]);
606 bbtkInternalError("should not reach here !!!");
609 bbtkDecTab("Interpreter",9);
611 //=======================================================================
617 //=======================================================================
621 void Interpreter::SplitLine ( const std::string& str, std::vector<std::string>& tokens)
623 bbtkDebugMessageInc("Interpreter",9,"Interpreter::SplitLine(\""<<str<<"\")"<<std::endl);
625 std::string delimiters = "\"";
626 std::vector<std::string> quote;
627 Utilities::SplitString(str,delimiters,quote);
630 std::vector<std::string>::iterator i;
631 for (i=quote.begin(); i!=quote.end(); )
633 Utilities::SplitString(*i,delimiters,tokens);
637 // bbtkDebugMessage("Interpreter",0,"\""<<*i<<"\""<<std::endl);
638 tokens.push_back(*i);
643 for (i=tokens.begin(); i!=tokens.end(); ++i)
645 bbtkDebugMessage("Interpreter",9,"["<<*i<<"] ");
647 bbtkDebugMessageCont("Interpreter",9,std::endl);
649 bbtkDebugDecTab("Interpreter",9);
651 //=======================================================================
654 //=======================================================================
655 // Replaces substrings "\\n" by a real carriage return "\n"
656 void SubsBackslashN ( std::string& s )
658 std::string ss("\\n");
659 std::string::size_type pos = 0;
662 while ( pos != std::string::npos )
664 s.replace(pos,2,cr,1);
665 pos = s.find(ss, pos-1);
668 //=======================================================================
671 //=======================================================================
675 void Interpreter::Print( const std::string& str)
677 if (mExecuter->GetNoExecMode()) return;
679 bbtkDebugMessageInc("Interpreter",9,"Interpreter::Print(\""<<str<<"\")"<<std::endl);
682 // InterpretLine ("load std")
683 // InterpretLine("new ConcatStrings _C_ ") -> trouver un nom unique : # commande
684 // InterpretLine("new Print _P_")
685 // InterpretLine("connect _C_.Out _P_.In")
689 std::vector<std::string> chains;
690 std::string delimiters("$");
692 // Skip delimiters at beginning.
693 std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
695 if (lastPos>0) is_text = false;
697 // Find first delimiter.
698 std::string::size_type pos = str.find_first_of(delimiters, lastPos);
700 while (std::string::npos != pos || std::string::npos != lastPos)
704 // Found a text token, add it to the vector.
705 chains.push_back(str.substr(lastPos, pos - lastPos));
706 // std::string token = str.substr(lastPos, pos - lastPos)
707 // InterpretLine("set _C_.In%num% %token%")
713 // is an output (between $$) : decode
714 std::string tok,box,output;
715 tok = str.substr(lastPos, pos - lastPos);
716 Utilities::SplitAroundFirstDot(tok,box,output);
717 chains.push_back( mExecuter->Get(box,output) );
719 // InterpretLine("connect %tok% _C_.In%num%")
722 // Skip delimiters. Note the "not_of"
723 lastPos = str.find_first_not_of(delimiters, pos);
724 // Find next delimiter
725 pos = str.find_first_of(delimiters, lastPos);
730 // InterpretLine("exec _P_")
731 // if (IS_IN_WORKSPACE) InterpretLine("delete _C_; delete _P_");
733 std::vector<std::string>::iterator i;
734 for (i= chains.begin(); i!=chains.end(); ++i)
736 // bbtkMessage("Echo",1,*i);
740 std::cout << std::endl;
741 bbtkDebugDecTab("Interpreter",9);
744 //=======================================================================
749 // ===================================================================================
751 void Interpreter::SwitchToFile( const std::string& name )
753 // Note : in the following :
754 // name : the user supplied name
755 // - abreviated name e.g. scr scr.bbs
756 // - relative full name e.g. ./scr.bbs ../../scr.bbs
757 // - absolute full name e.g. /home/usrname/proj/dir/scr.bbs
758 // same for Windows, with c:, d: ...
760 // use ./directory/subdir/scrname.bbs
763 bbtkDebugMessageInc("Interpreter",9,"Interpreter::SwitchToFile( \""
764 <<name<<"\")"<<std::endl);
766 std::vector<std::string> script_paths;
767 std::string fullPathScriptName; // full path script name
768 std::string pkgname; // e.g. <scriptname>.bbs
769 std::vector<std::string> Filenames;
771 // The following is *NOT* a debug time message :
772 // It's a user intended message.
773 // Please don't remove it.
774 bbtkMessage("Interpreter",1,
775 "look for : [" << name
776 << "]" << std::endl);
777 script_paths = ConfigurationFile::GetInstance().Get_bbs_paths();
780 pkgname = Utilities::ExtractScriptName(name,upath);
782 bool fullnameGiven = false;
783 bool foundFile = false;
785 if(pkgname == "*") // =========================================== load all boxes (e.g. std/boxes/*)
789 if (upath[0]=='/' || upath[1] == ':' ) // ==== absolute name, load all .bbs files
791 int nbFiles = Utilities::Explore(upath, false, Filenames);
793 for (std::vector<std::string>::iterator i = Filenames.begin(); i!= Filenames.end(); ++i)
795 if ((*i).substr((*i).size()-4, 4) != ".bbs")
796 continue; // ignore non .bbs files
801 bbtkMessage("Interpreter",2,
802 "WARNING : No '.bbs' file found in ["
803 << upath << "]" << std::endl);
808 std::vector<std::string>::iterator i;
809 std::string fullDirectoryName;
810 for (i=script_paths.begin();i!=script_paths.end();i++)// ==== relative name, iterate + load all .bbs files
814 // we *really* want '.' to be the current working directory
816 char buf[2048]; // for getcwd
817 char * currentDir = getcwd(buf, 2048);
818 std::string cwd(currentDir);
822 fullDirectoryName = Utilities::MakePkgnameFromPath(path, upath, false);
825 // without last slash "\"
826 std::string fullDirectoryNameClean = fullDirectoryName.substr(0,fullDirectoryName.size()-1);
828 // Check if library exists
829 if ( ! Utilities::IsDirectory( fullDirectoryNameClean ) )
831 // The following is *NOT* a debug time message :
832 // It's a user intended message.
833 // Please don't remove it.
834 bbtkMessage("Interpreter",1," [" <<fullDirectoryName
835 <<"] : doesn't exist" <<std::endl);
836 continue; // try next path
841 int nbFiles = Utilities::Explore(fullDirectoryName, false, Filenames);
844 for (std::vector<std::string>::iterator i = Filenames.begin(); i!= Filenames.end(); ++i)
846 if ((*i).substr((*i).size()-4, 4) != ".bbs")
847 continue; // ignore non .bbs files
852 bbtkMessage("Interpreter",1,
853 "WARNING : No '.bbs' file found in ["
854 << fullDirectoryName << "]" << std::endl);
856 //break; // a directory was found; we stop iterating
857 // LG : No! We want all files included !
862 //std::string::size_type slash_position = name.find_last_of("/\\");
864 // if name starts with a / or a . or contains : user is assumed to have passed a relative/absolute name
865 // (not only a plain script name)
866 // we trust him, and try to expland the directory name
867 // WARNING : starting from current local directory : ./whatYouWant (./ mandatory!)
869 if (name[0]=='/' || name[1] == ':' || name[0]=='.') // absolute path (linux/windows) or relative path
872 // ===========================================================check user supplied location
873 fullnameGiven = true;
875 fullPathScriptName = Utilities::ExpandLibName(name, false);
877 // allow user to always forget ".bbs"
878 int l = fullPathScriptName.size();
884 if (fullPathScriptName.substr(l-4, 4) != ".bbs")
886 fullPathScriptName = fullPathScriptName + ".bbs";
891 fullPathScriptName = fullPathScriptName + ".bbs";
894 if ( Utilities::FileExists(fullPathScriptName))
902 // =============================================================== iterate on the paths
905 std::vector<std::string>::iterator i;
906 for (i=script_paths.begin();i!=script_paths.end();++i)
910 // we *really* want '.' to be the current working directory
912 char buf[2048]; // for getcwd
913 char * currentDir = getcwd(buf, 2048);
914 std::string cwd(currentDir);
918 // fullPathScriptName = Utilities::MakePkgnameFromPath(path, name, true); //pkgname);
920 fullPathScriptName = Utilities::MakePkgnameFromPath(path, name, true);
923 // Check if library exists
924 if ( ! Utilities::FileExists(fullPathScriptName) )
926 // The following is *NOT* a debug time message :
927 // It's a user intended message.
928 // Please don't remove it.
929 bbtkMessage("Interpreter",2,
930 " [" <<fullPathScriptName <<"] : doesn't exist"
932 continue; // try next path
934 bbtkMessage("Interpreter",2,
935 " [" <<fullPathScriptName
936 <<"] : found" <<std::endl);
938 break; // a script was found; we stop iterating
940 } //------------------ // end for ( package_paths.begin();i!=package_paths.end() )
946 if(fullPathScriptName == "")
947 bbtkError("Path ["<<upath<<"] doesn't exist");
949 bbtkError("Script ["<<fullPathScriptName<<"] not found");
951 bbtkError("No ["<<pkgname<<".bbs] script found");
955 LoadScript(fullPathScriptName,name);
961 //=======================================================================
963 void Interpreter::LoadScript( std::string fullPathScriptName,
964 std::string includeScriptName)
966 if (find(mFileName.begin(),mFileName.end(),fullPathScriptName)
969 bbtkMessage("Interpreter",1,"file '"<<fullPathScriptName
970 <<"' already open : I do not open it once more to prevent recursive inclusion"<<std::endl);
975 s = new std::ifstream;
976 s->open(fullPathScriptName.c_str());
979 bbtkError("Could not open file ["<<fullPathScriptName<<"]");
983 bbtkMessage("Interpreter",1," -->[" << fullPathScriptName
984 << "] found" << std::endl);
987 mFileName.push_back(fullPathScriptName);
988 mIncludeFileName.push_back(includeScriptName);
993 //=======================================================================
997 void Interpreter::CloseCurrentFile()
999 bbtkDebugMessage("Interpreter",9,"Interpreter::CloseCurrentFile()"
1002 if (mFile.size()==0)
1004 bbtkDebugMessage("Interpreter",9," -> no file left open"<<std::endl);
1008 mFile.back()->close();
1009 delete mFile.back();
1011 bbtkDebugMessage("Interpreter",9,
1012 " Closing file '"<<mFileName.back()<<"'"<<std::endl);
1014 mFileName.pop_back();
1015 mIncludeFileName.pop_back();
1017 bbtkDebugMessage("Interpreter",9," Remains "
1019 <<" open"<<std::endl);
1020 bbtkDebugMessage("Interpreter",9,"EO Interpreter::CloseCurrentFile()"
1023 //=======================================================================
1025 //=======================================================================
1029 void Interpreter::CloseAllFiles()
1031 bbtkDebugMessage("Interpreter",9,"Interpreter::CloseAllFiles()"
1034 while (mFile.size() != 0)
1036 mFile.back()->close();
1037 delete mFile.back();
1039 bbtkDebugMessage("Interpreter",9,
1040 " Closing file '"<<mFileName.back()<<"'"<<std::endl);
1041 mFileName.pop_back();
1042 mIncludeFileName.pop_back();
1045 bbtkDebugMessage("Interpreter",9,"EO Interpreter::CloseAllFiles()"
1048 //=======================================================================
1052 //=======================================================================
1056 void Interpreter::InterpretCommand( const std::vector<std::string>& words,
1057 CommandInfoType& info )
1059 bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretCommand(...)"<<std::endl);
1061 // searches the command category
1062 CommandDictType::iterator c;
1063 c = mCommandDict.find(words[0]);
1064 if ( c == mCommandDict.end() ) {
1065 bbtkError(words[0]<<" : unknown command");
1068 // tests the number of args
1069 if ( ( words.size()-1 < c->second.argmin ) ||
1070 ( words.size()-1 > c->second.argmax ) )
1072 HelpCommand(words[0]);
1073 bbtkError(words[0]<<" : wrong number of arguments");
1077 bbtkDecTab("Interpreter",9);
1079 //=======================================================================
1082 //=======================================================================
1083 /// Displays help on all the commands
1084 void Interpreter::Help(const std::vector<std::string>& words)
1086 unsigned int nbarg = words.size()-1;
1094 if (words[1]=="packages")
1096 PrintPackages(true);
1101 HelpCommand(words[1]);
1103 catch (bbtk::Exception e)
1107 HelpPackage(words[1]);
1108 #ifdef _USE_WXWIDGETS_
1109 if ( WxConsole::GetInstance() != 0 )
1112 ConfigurationFile::GetInstance().Get_doc_path();
1113 url += "/bbdoc/" + words[1] + "/index.html";
1114 if (Utilities::FileExists(url))
1116 WxConsole::GetInstance()->ShowHtmlPage(url);
1121 catch (bbtk::Exception f)
1125 std::string package;
1126 HelpBlackBox(words[1],package);
1127 #ifdef _USE_WXWIDGETS_
1128 if ( WxConsole::GetInstance() != 0 )
1131 ConfigurationFile::GetInstance().Get_doc_path();
1132 url += "/bbdoc/" + package + "/index.html";
1133 if (Utilities::FileExists(url))
1135 url += "#" + words[1];
1136 WxConsole::GetInstance()->ShowHtmlPage(url);
1141 catch (bbtk::Exception g)
1145 this->mExecuter->ShowRelations(words[1],"0","9999");
1147 catch (bbtk::Exception h){
1148 bbtkError("\""<<words[1].c_str()
1149 <<"\" is not a known command, package, black box type or black box name");
1157 if (words[2]=="all")
1159 if ( words[1]=="packages" )
1161 PrintPackages(true,true);
1166 HelpPackage(words[1],true);
1168 catch (bbtk::Exception f)
1174 HelpCommand(words[0]);
1175 bbtkError(words[0]<<" : syntax error");
1180 bbtkError("Should not reach here !!!");
1183 //=======================================================================
1185 //===================================================================
1186 /// Displays the Configuration
1187 void Interpreter::Config() const
1189 ConfigurationFile::GetInstance().GetHelp(1);
1191 //===================================================================
1193 //=======================================================================
1194 /// Displays help on all the commands
1195 void Interpreter::HelpCommands()
1197 std::cout << "Available commands :" << std::endl;
1198 CommandDictType::iterator i;
1199 for ( i = mCommandDict.begin();
1200 i != mCommandDict.end();
1202 std::cout << " " << i->first << std::endl;
1203 // std::cout << " usage : " << i->second.syntax << std::endl;
1204 // std::cout << " " << i->second.help << std::endl;
1208 //=======================================================================
1211 //=======================================================================
1212 /// Displays help on a particular commands
1213 void Interpreter::HelpCommand(const std::string& s)
1215 CommandDictType::iterator c;
1216 c = mCommandDict.find(s);
1217 if ( c == mCommandDict.end() ) {
1218 bbtkError(s<<" : Unknown command");
1220 // std::cout << " " << s << " : "<< std::endl;
1221 // CommandParamDictType::iterator i;
1222 // for ( i = c->second.begin();
1223 // i != c->second.end();
1225 std::cout << " usage : " << c->second.syntax << std::endl;
1226 std::cout << " " << c->second.help << std::endl;
1229 //=======================================================================
1232 //=======================================================================
1233 /// Fills the vector commands with the commands which
1234 /// have the first n chars of buf for prefix
1235 /// TODO : skip initial spaces in buf and also return the position of first
1236 /// non blank char in buf
1237 void Interpreter::FindCommandsWithPrefix( char* buf,
1239 std::vector<std::string>& commands )
1241 CommandDictType::const_iterator i;
1242 for (i=mCommandDict.begin(); i!=mCommandDict.end(); ++i)
1244 if ((i->first).find(buf,0,n) == 0)
1245 commands.push_back(i->first);
1248 //=======================================================================
1252 //=======================================================================
1253 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1255 inline void PrintChar(char c) { write(STDOUT_FILENO,&c,1); }
1256 inline void BackSpace() { write(STDOUT_FILENO,"\b \b",3); }
1258 // LG : KEYBOARD CODES AS SCANNED ON MY TTY : UNIVERSAL ?
1259 // IF NOT THE USER SHOULD BE ABLE TO CONFIGURE IT
1260 // E.G. STORE THIS IN bbtk_config.xml
1261 #define BBTK_UP_ARROW_KBCODE 0x00415B1B
1262 #define BBTK_DOWN_ARROW_KBCODE 0x00425B1B
1263 #define BBTK_RIGHT_ARROW_KBCODE 0x00435B1B
1264 #define BBTK_LEFT_ARROW_KBCODE 0x00445B1B
1265 #define BBTK_BACKSPACE_KBCODE 0x00000008
1266 #define BBTK_DEL_KBCODE 0x0000007F
1267 #define BBTK_SPACE_KBCODE 0x00000020
1269 //=======================================================================
1270 void Interpreter::GetLineFromPrompt(std::string& s)
1275 int MAX_LINE_SIZE = 160;
1276 int MAX_HISTORY_SIZE = 100;
1278 char* newline = new char[MAX_LINE_SIZE];
1279 memset(newline,0,MAX_LINE_SIZE);
1280 char* histline = new char[MAX_LINE_SIZE];
1281 memset(histline,0,MAX_LINE_SIZE);
1283 char* line = newline;
1284 int hist = mHistory.size();
1290 read ( STDIN_FILENO, &c, 4) ;
1292 bbtkDebugMessage("Debug",9,"[0x"<<std::hex<<c<<"]\n");
1294 // Printable character
1295 if ( (ind<MAX_LINE_SIZE-1) &&
1296 ( c >= BBTK_SPACE_KBCODE ) &&
1297 ( c < BBTK_DEL_KBCODE ))
1305 // delete the unused line
1311 // empty lines are not stored in from history
1314 // if history too long : delete oldest command
1315 if (mHistory.size()>MAX_HISTORY_SIZE)
1317 delete mHistory.front();
1318 mHistory.pop_front();
1320 mHistory.push_back(line);
1325 else if ( (ind>0) &&
1326 ((c == BBTK_BACKSPACE_KBCODE) ||
1327 (c == BBTK_DEL_KBCODE)) )
1335 // TODO : Command completion
1336 std::vector<std::string> commands;
1337 FindCommandsWithPrefix( line,ind,commands);
1338 if (commands.size()==1)
1340 std::string com = *commands.begin();
1341 for (; ind<com.size(); ++ind)
1343 PrintChar(com[ind]);
1349 else if (commands.size()>1)
1351 std::vector<std::string>::iterator i;
1353 for (i=commands.begin();i!=commands.end();++i)
1355 write(STDOUT_FILENO,(*i).c_str(),strlen((*i).c_str()));
1358 write(STDOUT_FILENO,"\n> ",3);
1359 //for (int j=0;j<ind;++j)
1361 write(STDOUT_FILENO,line,ind);
1365 // Arrow up : back in history
1366 else if (c==BBTK_UP_ARROW_KBCODE)
1370 // erase current line
1371 while (ind--) BackSpace();
1375 strcpy(histline,mHistory[hist]);
1379 write(STDOUT_FILENO,line,ind);
1382 // Arrow down : down in history
1383 else if (c==BBTK_DOWN_ARROW_KBCODE)
1385 if (hist<mHistory.size()-1)
1387 // erase current line
1388 while (ind--) BackSpace();
1392 strcpy(histline,mHistory[hist]);
1396 write(STDOUT_FILENO,line,ind);
1398 // end of history : switch back to newline
1399 else if (hist==mHistory.size()-1)
1401 // erase current line
1402 while (ind--) BackSpace();
1409 write(STDOUT_FILENO,line,ind);
1413 else if (line[ind]!=0 && c==BBTK_RIGHT_ARROW_KBCODE)
1415 PrintChar(line[ind]);
1420 else if (ind>0 && c==BBTK_LEFT_ARROW_KBCODE)
1428 write(STDOUT_FILENO,"\n\r",2);
1436 //=======================================================================
1437 void Interpreter::GetLineFromPrompt(std::string& s)
1463 //=======================================================================
1469 //=======================================================================
1470 void Interpreter::CommandLineInterpreter()
1472 bbtkDebugMessageInc("Interpreter",9,
1473 "Interpreter::CommandLineInterpreter()"<<std::endl);
1475 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1476 // Initialise the tty in non canonical mode with no echo
1477 // oter remembers the previous settings to restore them after
1478 struct termios ter,oter;
1481 ter.c_lflag &= ~ECHO;
1482 ter.c_lflag &= ~ICANON;
1485 tcsetattr(0,TCSANOW,&ter);
1488 mCommandLine = true;
1490 bool insideComment = false; // for multiline comment
1496 GetLineFromPrompt(line);
1497 InterpretLine(line, insideComment);
1499 catch (QuitException e)
1503 catch (bbtk::Exception e)
1507 catch (std::exception& e)
1509 std::cerr << "* ERROR :: "<<e.what()<<" (not in bbtk)"<<std::endl;
1513 std::cerr << "* UNDEFINED ERROR (not a bbtk nor a std exception)"<<std::endl;
1518 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1519 tcsetattr(0,TCSANOW,&oter);
1522 std::cout << "Good bye !" << std::endl;
1524 bbtkDebugDecTab("Interpreter",9);
1527 //=======================================================================
1528 void Interpreter::Graph(const std::vector<std::string>& words)
1531 bool system_display = true;
1533 #ifdef _USE_WXWIDGETS_
1534 if ( WxConsole::GetInstance() != 0 ) system_display = false;
1537 if (words.size()==1)
1539 page = mExecuter->ShowGraph(".","0","0","","","",system_display);
1541 else if (words.size()==2)
1543 page = mExecuter->ShowGraph(words[1],"0","0","","","",system_display);
1545 else if (words.size()==3)
1547 page = mExecuter->ShowGraph(words[1],words[2],"0","","","",system_display);
1549 else if (words.size()==4)
1551 page = mExecuter->ShowGraph(words[1],words[2],words[3],"","","",system_display);
1553 else if (words.size()==5)
1555 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],"","",system_display);
1557 else if (words.size()==6)
1559 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],"",system_display);
1561 else if (words.size()==7)
1563 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],words[6],system_display);
1566 #ifdef _USE_WXWIDGETS_
1567 if ( WxConsole::GetInstance() != 0 )
1568 WxConsole::GetInstance()->ShowHtmlPage(page);
1571 //=======================================================================
1574 //=======================================================================
1575 void Interpreter::Index(const std::string& filename,
1576 const std::string& type)
1578 Factory::IndexEntryType t;
1579 if (type=="Initials") t = Factory::Initials;
1580 else if (type=="Categories") t = Factory::Categories;
1581 else if (type=="Packages") t = Factory::Packages;
1583 GetGlobalFactory()->CreateHtmlIndex(t,filename);
1585 //=======================================================================