1 /*=========================================================================
4 Module: $RCSfile: bbtkInterpreter.cxx,v $ $
6 Date: $Date: 2008/02/21 07:30:20 $
7 Version: $Revision: 1.36 $
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 SwitchToFile(filename, use_configuration_file);
314 bool insideComment = false; // for multiline comment
315 while (mFile.size()>0)
317 while ((mFile.size()>0) &&
318 (!mFile.back()->eof()))
322 mFile.back()->getline(buf,500);
324 std::string str(buf);
325 int size=str.length();
326 if ( str[ size-1 ]==13 )
331 InterpretLine(str, insideComment);
333 //if (mFile.size()>0)
337 catch (QuitException e)
340 catch (bbtk::Exception e)
342 std::cerr << "* ERROR : "<<e.GetMessage()<<std::endl;
343 if (mFileName.size()) {
344 std::cerr << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
345 std::cerr << "* LINE : "<<mLine.back()<<std::endl;
348 catch (std::exception& e)
350 std::cerr << "* ERROR : "<<e.what()<<" (not in bbtk)"<<std::endl;
351 if (mFileName.size()) {
352 std::cerr << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
353 std::cerr << "* LINE : "<<mLine.back()<<std::endl;
358 std::cout << "* UNDEFINED ERROR (not a bbtk nor a std exception)"<<std::endl;
359 if (mFileName.size()) {
360 std::cout << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
361 std::cout << "* LINE : "<<mLine.back()<<std::endl;
366 bbtkDebugMessage("Interpreter",9,"EO Interpreter::InterpretFile(\""<<filename<<"\")"<<std::endl);
367 bbtkDecTab("Interpreter",9);
371 //=======================================================================
375 //=======================================================================
379 void Interpreter::InterpretLine( const std::string& line, bool &insideComment )
382 bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretLine(\""<<line<<"\")"<<std::endl);
383 bbtkMessage("Echo",2,"\""<<line<<"\""<<std::endl);
385 std::vector<std::string> words;
386 SplitLine(line,words);
391 bbtkDebugDecTab("Interpreter",9);
395 // Single line comment : # or //
396 if ( words[0][0]=='#' || (words[0][0]=='/' && words[0][1]=='/') )
398 bbtkDebugDecTab("Interpreter",9);
399 bbtkMessage("Interpreter",9,"Comment"<<std::endl);
403 // Multi line comment ( /* ... */ ) -delimiters on different lines !-
405 if (words[0][0]=='/' && words[0][1]=='*')
407 bbtkDebugDecTab("Interpreter",9);
408 bbtkMessage("Interpreter",9,"In multiline comment"<<std::endl);
409 insideComment = true;
413 if (words[0][0]=='*' && words[0][1]=='/')
415 bbtkDebugDecTab("Interpreter",9);
416 bbtkMessage("Interpreter",9,"Out multiline comment"<<std::endl);
417 if ( !insideComment ) {
418 bbtkDebugDecTab("Interpreter",9);
419 bbtkMessage("Interpreter",9,"Comment mismatch : '*/' with no matching '/*'"<<std::endl);
421 insideComment = false;
427 bbtkDebugDecTab("Interpreter",9);
428 bbtkMessage("Interpreter",9,"Multiline Comment"<<std::endl);
433 CommandInfoType command;
434 InterpretCommand(words,command);
436 bbtkDebugMessage("Interpreter",9,
437 "Command='"<<command.category
438 <<"' code="<<command.code<<std::endl);
440 std::string left,right,left2,right2;
441 std::string filename;
442 switch (command.code)
445 mExecuter->Create(words[1],words[2]);
450 // mExecuter->Remove(words[1]);
454 Utilities::SplitAroundFirstDot(words[1],left,right);
455 Utilities::SplitAroundFirstDot(words[2],left2,right2);
456 mExecuter->Connect(left,right,left2,right2);
460 mExecuter->BeginPackage(words[1]);
464 mExecuter->EndPackage();
468 if (mFileName.size()>0)
470 filename = mIncludeFileName.back(); //Utilities::get_file_name(mFileName.back());
474 mExecuter->Define(words[1],"",filename);
478 mExecuter->Define(words[1],words[2],filename);
483 mExecuter->EndDefine();
487 Print(words[1]); /// \todo use mExecuter
491 if (words[1]=="freeze")
492 mExecuter->SetNoExecMode(true);
493 else if (words[1]=="unfreeze")
494 mExecuter->SetNoExecMode(false);
496 mExecuter->Update(words[1]);
500 Utilities::SplitAroundFirstDot(words[2],left,right);
501 mExecuter->DefineInput(words[1],left,right,words[3]);
505 Utilities::SplitAroundFirstDot(words[2],left,right);
506 mExecuter->DefineOutput(words[1],left,right,words[3]);
510 Utilities::SplitAroundFirstDot(words[1],left,right);
511 mExecuter->Set(left,right,words[2]);
515 mExecuter->Author(words[1]);
519 mExecuter->Category(words[1]);
524 Index("tmp_index.html");
525 else if (words.size()==2)
527 else if (words.size()==3)
528 Index(words[1],words[2]);
532 mExecuter->Description(words[1]);
542 bbtk::MessageManager::PrintInfo();
546 sscanf(words[2].c_str(),"%d",&level);
547 bbtk::MessageManager::SetMessageLevel(words[1],level);
560 this->mExecuter->Reset();
566 InterpretFile(words[1], true ); // true : better pass use_config_file
570 SwitchToFile(words[1], true ); // true : better pass use_config_file
572 // if 'source' was given
575 this->mExecuter->SetCurrentFileName(words[1]);
580 LoadPackage(words[1], true ); // true : better pass use_config_file
584 UnLoadPackage(words[1]);
589 throw QuitException();
593 if (words.size() == 2)
595 if (words[1]=="freeze") mExecuter->SetNoExecMode(true);
596 else if (words[1]=="unfreeze") mExecuter->SetNoExecMode(false);
600 mExecuter->SetWorkspaceName(words[2]);
605 bbtkInternalError("should not reach here !!!");
608 bbtkDecTab("Interpreter",9);
610 //=======================================================================
616 //=======================================================================
620 void Interpreter::SplitLine ( const std::string& str, std::vector<std::string>& tokens)
622 bbtkDebugMessageInc("Interpreter",9,"Interpreter::SplitLine(\""<<str<<"\")"<<std::endl);
624 std::string delimiters = "\"";
625 std::vector<std::string> quote;
626 Utilities::SplitString(str,delimiters,quote);
629 std::vector<std::string>::iterator i;
630 for (i=quote.begin(); i!=quote.end(); )
632 Utilities::SplitString(*i,delimiters,tokens);
636 // bbtkDebugMessage("Interpreter",0,"\""<<*i<<"\""<<std::endl);
637 tokens.push_back(*i);
642 for (i=tokens.begin(); i!=tokens.end(); ++i)
644 bbtkDebugMessage("Interpreter",9,"["<<*i<<"] ");
646 bbtkDebugMessageCont("Interpreter",9,std::endl);
648 bbtkDebugDecTab("Interpreter",9);
650 //=======================================================================
653 //=======================================================================
654 // Replaces substrings "\\n" by a real carriage return "\n"
655 void SubsBackslashN ( std::string& s )
657 std::string ss("\\n");
658 std::string::size_type pos = 0;
661 while ( pos != std::string::npos )
663 s.replace(pos,2,cr,1);
664 pos = s.find(ss, pos-1);
667 //=======================================================================
670 //=======================================================================
674 void Interpreter::Print( const std::string& str)
676 if (mExecuter->GetNoExecMode()) return;
678 bbtkDebugMessageInc("Interpreter",9,"Interpreter::SplitLine(\""<<str<<"\")"<<std::endl);
680 std::vector<std::string> chains;
681 std::string delimiters("$");
683 // Skip delimiters at beginning.
684 std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
686 if (lastPos>0) is_text = false;
688 // Find first delimiter.
689 std::string::size_type pos = str.find_first_of(delimiters, lastPos);
691 while (std::string::npos != pos || std::string::npos != lastPos)
695 // Found a text token, add it to the vector.
696 chains.push_back(str.substr(lastPos, pos - lastPos));
700 // is an output (between $$) : decode
701 std::string tok,box,output;
702 tok = str.substr(lastPos, pos - lastPos);
703 Utilities::SplitAroundFirstDot(tok,box,output);
704 chains.push_back( mExecuter->Get(box,output) );
706 // Skip delimiters. Note the "not_of"
707 lastPos = str.find_first_not_of(delimiters, pos);
708 // Find next delimiter
709 pos = str.find_first_of(delimiters, lastPos);
713 std::vector<std::string>::iterator i;
714 for (i= chains.begin(); i!=chains.end(); ++i)
716 // bbtkMessage("Echo",1,*i);
720 std::cout << std::endl;
721 bbtkDebugDecTab("Interpreter",9);
724 //=======================================================================
729 // ===================================================================================
731 void Interpreter::SwitchToFile( const std::string& name,
732 bool use_configuration_file )
734 // Note : in the following :
735 // name : the user supplied name
736 // - abreviated name e.g. scr scr.bbs
737 // - relative full name e.g. ./scr.bbs ../../scr.bbs
738 // - absolute full name e.g. /home/usrname/proj/dir/scr.bbs
739 // same for Windows, with c:, d: ...
741 // use ./directory/subdir/scrname.bbs
744 bbtkDebugMessageInc("Interpreter",9,"Interpreter::SwitchToFile( \""
745 <<name<<"\")"<<std::endl);
747 std::vector<std::string> script_paths;
748 std::string fullPathScriptName; // full path script name
749 std::string pkgname; // e.g. <scriptname>.bbs
750 std::vector<std::string> Filenames;
752 if (use_configuration_file)
754 // The following is *NOT* a debug time message :
755 // It's a user intended message.
756 // Please don't remove it.
757 bbtkMessage("Interpreter",1,
758 "look for : [" << name
759 << "] (use_configuration_file == TRUE)" << std::endl);
760 script_paths = ConfigurationFile::GetInstance().Get_bbs_paths();
763 pkgname = Utilities::ExtractScriptName(name,upath);
765 bool fullnameGiven = false;
766 bool foundFile = false;
768 if(pkgname == "*") // =========================================== load all boxes (e.g. std/boxes/*)
772 if (upath[0]=='/' || upath[1] == ':' ) // ==== absolute name, load all .bbs files
774 int nbFiles = Utilities::Explore(upath, false, Filenames);
776 for (std::vector<std::string>::iterator i = Filenames.begin(); i!= Filenames.end(); ++i)
778 if ((*i).substr((*i).size()-4, 4) != ".bbs")
779 continue; // ignore non .bbs files
784 bbtkMessage("Interpreter",2,
785 "WARNING : No '.bbs' file found in ["
786 << upath << "]" << std::endl);
791 std::vector<std::string>::iterator i;
792 std::string fullDirectoryName;
793 for (i=script_paths.begin();i!=script_paths.end();i++)// ==== relative name, iterate + load all .bbs files
797 // we *really* want '.' to be the current working directory
799 char buf[2048]; // for getcwd
800 char * currentDir = getcwd(buf, 2048);
801 std::string cwd(currentDir);
805 fullDirectoryName = Utilities::MakePkgnameFromPath(path, upath, false);
808 // without last slash "\"
809 std::string fullDirectoryNameClean = fullDirectoryName.substr(0,fullDirectoryName.size()-1);
811 // Check if library exists
812 if ( ! Utilities::IsDirectory( fullDirectoryNameClean ) )
814 // The following is *NOT* a debug time message :
815 // It's a user intended message.
816 // Please don't remove it.
817 bbtkMessage("Interpreter",1," [" <<fullDirectoryName
818 <<"] : doesn't exist" <<std::endl);
819 continue; // try next path
824 int nbFiles = Utilities::Explore(fullDirectoryName, false, Filenames);
827 for (std::vector<std::string>::iterator i = Filenames.begin(); i!= Filenames.end(); ++i)
829 if ((*i).substr((*i).size()-4, 4) != ".bbs")
830 continue; // ignore non .bbs files
835 bbtkMessage("Interpreter",1,
836 "WARNING : No '.bbs' file found in ["
837 << fullDirectoryName << "]" << std::endl);
839 //break; // a directory was found; we stop iterating
840 // LG : No! We want all files included !
845 //std::string::size_type slash_position = name.find_last_of("/\\");
847 // if name starts with a / or a . or contains : user is assumed to have passed a relative/absolute name
848 // (not only a plain script name)
849 // we trust him, and try to expland the directory name
850 // WARNING : starting from current local directory : ./whatYouWant (./ mandatory!)
852 if (name[0]=='/' || name[1] == ':' || name[0]=='.') // absolute path (linux/windows) or relative path
855 // ===========================================================check user supplied location
856 fullnameGiven = true;
858 fullPathScriptName = Utilities::ExpandLibName(name, false);
860 // allow user to always forget ".bbs"
861 int l = fullPathScriptName.size();
867 if (fullPathScriptName.substr(l-4, 4) != ".bbs")
869 fullPathScriptName = fullPathScriptName + ".bbs";
874 fullPathScriptName = fullPathScriptName + ".bbs";
877 if ( Utilities::FileExists(fullPathScriptName))
885 // =============================================================== iterate on the paths
888 std::vector<std::string>::iterator i;
889 for (i=script_paths.begin();i!=script_paths.end();++i)
893 // we *really* want '.' to be the current working directory
895 char buf[2048]; // for getcwd
896 char * currentDir = getcwd(buf, 2048);
897 std::string cwd(currentDir);
901 // fullPathScriptName = Utilities::MakePkgnameFromPath(path, name, true); //pkgname);
903 fullPathScriptName = Utilities::MakePkgnameFromPath(path, name, true);
906 // Check if library exists
907 if ( ! Utilities::FileExists(fullPathScriptName) )
909 // The following is *NOT* a debug time message :
910 // It's a user intended message.
911 // Please don't remove it.
912 bbtkMessage("Interpreter",2,
913 " [" <<fullPathScriptName <<"] : doesn't exist"
915 continue; // try next path
917 bbtkMessage("Interpreter",2,
918 " [" <<fullPathScriptName
919 <<"] : found" <<std::endl);
921 break; // a script was found; we stop iterating
923 } //------------------ // end for ( package_paths.begin();i!=package_paths.end() )
929 if(fullPathScriptName == "")
930 bbtkError("Path ["<<upath<<"] doesn't exist");
932 bbtkError("Script ["<<fullPathScriptName<<"] not found");
934 bbtkError("No ["<<pkgname<<".bbs] script found");
938 LoadScript(fullPathScriptName,name);
944 //=======================================================================
946 void Interpreter::LoadScript( std::string fullPathScriptName,
947 std::string includeScriptName)
949 if (find(mFileName.begin(),mFileName.end(),fullPathScriptName)
952 bbtkMessage("Interpreter",1,"file '"<<fullPathScriptName
953 <<"' already open : I do not open it once more to prevent recursive inclusion"<<std::endl);
958 s = new std::ifstream;
959 s->open(fullPathScriptName.c_str());
962 bbtkError("Could not open file ["<<fullPathScriptName<<"]");
966 bbtkMessage("Interpreter",1," -->[" << fullPathScriptName
967 << "] found" << std::endl);
970 mFileName.push_back(fullPathScriptName);
971 mIncludeFileName.push_back(includeScriptName);
976 //=======================================================================
980 void Interpreter::CloseCurrentFile()
982 bbtkDebugMessage("Interpreter",9,"Interpreter::CloseCurrentFile()"
987 bbtkDebugMessage("Interpreter",9," -> no file left open"<<std::endl);
991 mFile.back()->close();
994 bbtkDebugMessage("Interpreter",9,
995 " Closing file '"<<mFileName.back()<<"'"<<std::endl);
997 mFileName.pop_back();
998 mIncludeFileName.pop_back();
1000 bbtkDebugMessage("Interpreter",9," Remains "
1002 <<" open"<<std::endl);
1003 bbtkDebugMessage("Interpreter",9,"EO Interpreter::CloseCurrentFile()"
1006 //=======================================================================
1008 //=======================================================================
1012 void Interpreter::CloseAllFiles()
1014 bbtkDebugMessage("Interpreter",9,"Interpreter::CloseAllFiles()"
1017 while (mFile.size() != 0)
1019 mFile.back()->close();
1020 delete mFile.back();
1022 bbtkDebugMessage("Interpreter",9,
1023 " Closing file '"<<mFileName.back()<<"'"<<std::endl);
1024 mFileName.pop_back();
1025 mIncludeFileName.pop_back();
1028 bbtkDebugMessage("Interpreter",9,"EO Interpreter::CloseAllFiles()"
1031 //=======================================================================
1035 //=======================================================================
1039 void Interpreter::InterpretCommand( const std::vector<std::string>& words,
1040 CommandInfoType& info )
1042 bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretCommand(...)"<<std::endl);
1044 // searches the command category
1045 CommandDictType::iterator c;
1046 c = mCommandDict.find(words[0]);
1047 if ( c == mCommandDict.end() ) {
1048 bbtkError(words[0]<<" : unknown command");
1051 // tests the number of args
1052 if ( ( words.size()-1 < c->second.argmin ) ||
1053 ( words.size()-1 > c->second.argmax ) )
1055 HelpCommand(words[0]);
1056 bbtkError(words[0]<<" : wrong number of arguments");
1060 bbtkDecTab("Interpreter",9);
1062 //=======================================================================
1065 //=======================================================================
1066 /// Displays help on all the commands
1067 void Interpreter::Help(const std::vector<std::string>& words)
1069 unsigned int nbarg = words.size()-1;
1077 if (words[1]=="packages")
1079 PrintPackages(true);
1084 HelpCommand(words[1]);
1086 catch (bbtk::Exception e)
1090 HelpPackage(words[1]);
1091 #ifdef _USE_WXWIDGETS_
1092 if ( WxConsole::GetInstance() != 0 )
1095 ConfigurationFile::GetInstance().Get_doc_path();
1096 url += "/bbdoc/" + words[1] + "/index.html";
1097 if (Utilities::FileExists(url))
1099 WxConsole::GetInstance()->ShowHtmlPage(url);
1104 catch (bbtk::Exception f)
1108 std::string package;
1109 HelpBlackBox(words[1],package);
1110 #ifdef _USE_WXWIDGETS_
1111 if ( WxConsole::GetInstance() != 0 )
1114 ConfigurationFile::GetInstance().Get_doc_path();
1115 url += "/bbdoc/" + package + "/index.html";
1116 if (Utilities::FileExists(url))
1118 url += "#" + words[1];
1119 WxConsole::GetInstance()->ShowHtmlPage(url);
1124 catch (bbtk::Exception g)
1128 this->mExecuter->ShowRelations(words[1],"0","9999");
1130 catch (bbtk::Exception h){
1131 bbtkError("\""<<words[1].c_str()
1132 <<"\" is not a known command, package, black box type or black box name");
1140 if (words[2]=="all")
1142 if ( words[1]=="packages" )
1144 PrintPackages(true,true);
1149 HelpPackage(words[1],true);
1151 catch (bbtk::Exception f)
1157 HelpCommand(words[0]);
1158 bbtkError(words[0]<<" : syntax error");
1163 bbtkError("Should not reach here !!!");
1166 //=======================================================================
1168 //===================================================================
1169 /// Displays the Configuration
1170 void Interpreter::Config() const
1172 ConfigurationFile::GetInstance().GetHelp(1);
1174 //===================================================================
1176 //=======================================================================
1177 /// Displays help on all the commands
1178 void Interpreter::HelpCommands()
1180 std::cout << "Available commands :" << std::endl;
1181 CommandDictType::iterator i;
1182 for ( i = mCommandDict.begin();
1183 i != mCommandDict.end();
1185 std::cout << " " << i->first << std::endl;
1186 // std::cout << " usage : " << i->second.syntax << std::endl;
1187 // std::cout << " " << i->second.help << std::endl;
1191 //=======================================================================
1194 //=======================================================================
1195 /// Displays help on a particular commands
1196 void Interpreter::HelpCommand(const std::string& s)
1198 CommandDictType::iterator c;
1199 c = mCommandDict.find(s);
1200 if ( c == mCommandDict.end() ) {
1201 bbtkError(s<<" : Unknown command");
1203 // std::cout << " " << s << " : "<< std::endl;
1204 // CommandParamDictType::iterator i;
1205 // for ( i = c->second.begin();
1206 // i != c->second.end();
1208 std::cout << " usage : " << c->second.syntax << std::endl;
1209 std::cout << " " << c->second.help << std::endl;
1212 //=======================================================================
1215 //=======================================================================
1216 /// Fills the vector commands with the commands which
1217 /// have the first n chars of buf for prefix
1218 /// TODO : skip initial spaces in buf and also return the position of first
1219 /// non blank char in buf
1220 void Interpreter::FindCommandsWithPrefix( char* buf,
1222 std::vector<std::string>& commands )
1224 CommandDictType::const_iterator i;
1225 for (i=mCommandDict.begin(); i!=mCommandDict.end(); ++i)
1227 if ((i->first).find(buf,0,n) == 0)
1228 commands.push_back(i->first);
1231 //=======================================================================
1235 //=======================================================================
1236 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1238 inline void PrintChar(char c) { write(STDOUT_FILENO,&c,1); }
1239 inline void BackSpace() { write(STDOUT_FILENO,"\b \b",3); }
1241 // LG : KEYBOARD CODES AS SCANNED ON MY TTY : UNIVERSAL ?
1242 // IF NOT THE USER SHOULD BE ABLE TO CONFIGURE IT
1243 // E.G. STORE THIS IN bbtk_config.xml
1244 #define BBTK_UP_ARROW_KBCODE 0x00415B1B
1245 #define BBTK_DOWN_ARROW_KBCODE 0x00425B1B
1246 #define BBTK_RIGHT_ARROW_KBCODE 0x00435B1B
1247 #define BBTK_LEFT_ARROW_KBCODE 0x00445B1B
1248 #define BBTK_BACKSPACE_KBCODE 0x00000008
1249 #define BBTK_DEL_KBCODE 0x0000007F
1250 #define BBTK_SPACE_KBCODE 0x00000020
1252 //=======================================================================
1253 void Interpreter::GetLineFromPrompt(std::string& s)
1258 int MAX_LINE_SIZE = 160;
1259 int MAX_HISTORY_SIZE = 100;
1261 char* newline = new char[MAX_LINE_SIZE];
1262 memset(newline,0,MAX_LINE_SIZE);
1263 char* histline = new char[MAX_LINE_SIZE];
1264 memset(histline,0,MAX_LINE_SIZE);
1266 char* line = newline;
1267 int hist = mHistory.size();
1273 read ( STDIN_FILENO, &c, 4) ;
1275 bbtkDebugMessage("Debug",9,"[0x"<<std::hex<<c<<"]\n");
1277 // Printable character
1278 if ( (ind<MAX_LINE_SIZE-1) &&
1279 ( c >= BBTK_SPACE_KBCODE ) &&
1280 ( c < BBTK_DEL_KBCODE ))
1288 // delete the unused line
1294 // empty lines are not stored in from history
1297 // if history too long : delete oldest command
1298 if (mHistory.size()>MAX_HISTORY_SIZE)
1300 delete mHistory.front();
1301 mHistory.pop_front();
1303 mHistory.push_back(line);
1308 else if ( (ind>0) &&
1309 ((c == BBTK_BACKSPACE_KBCODE) ||
1310 (c == BBTK_DEL_KBCODE)) )
1318 // TODO : Command completion
1319 std::vector<std::string> commands;
1320 FindCommandsWithPrefix( line,ind,commands);
1321 if (commands.size()==1)
1323 std::string com = *commands.begin();
1324 for (; ind<com.size(); ++ind)
1326 PrintChar(com[ind]);
1332 else if (commands.size()>1)
1334 std::vector<std::string>::iterator i;
1336 for (i=commands.begin();i!=commands.end();++i)
1338 write(STDOUT_FILENO,(*i).c_str(),strlen((*i).c_str()));
1341 write(STDOUT_FILENO,"\n> ",3);
1342 //for (int j=0;j<ind;++j)
1344 write(STDOUT_FILENO,line,ind);
1348 // Arrow up : back in history
1349 else if (c==BBTK_UP_ARROW_KBCODE)
1353 // erase current line
1354 while (ind--) BackSpace();
1358 strcpy(histline,mHistory[hist]);
1362 write(STDOUT_FILENO,line,ind);
1365 // Arrow down : down in history
1366 else if (c==BBTK_DOWN_ARROW_KBCODE)
1368 if (hist<mHistory.size()-1)
1370 // erase current line
1371 while (ind--) BackSpace();
1375 strcpy(histline,mHistory[hist]);
1379 write(STDOUT_FILENO,line,ind);
1381 // end of history : switch back to newline
1382 else if (hist==mHistory.size()-1)
1384 // erase current line
1385 while (ind--) BackSpace();
1392 write(STDOUT_FILENO,line,ind);
1396 else if (line[ind]!=0 && c==BBTK_RIGHT_ARROW_KBCODE)
1398 PrintChar(line[ind]);
1403 else if (ind>0 && c==BBTK_LEFT_ARROW_KBCODE)
1411 write(STDOUT_FILENO,"\n\r",2);
1419 //=======================================================================
1420 void Interpreter::GetLineFromPrompt(std::string& s)
1446 //=======================================================================
1452 //=======================================================================
1453 void Interpreter::CommandLineInterpreter()
1455 bbtkDebugMessageInc("Interpreter",9,
1456 "Interpreter::CommandLineInterpreter()"<<std::endl);
1458 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1459 // Initialise the tty in non canonical mode with no echo
1460 // oter remembers the previous settings to restore them after
1461 struct termios ter,oter;
1464 ter.c_lflag &= ~ECHO;
1465 ter.c_lflag &= ~ICANON;
1468 tcsetattr(0,TCSANOW,&ter);
1471 mCommandLine = true;
1473 bool insideComment = false; // for multiline comment
1479 GetLineFromPrompt(line);
1480 InterpretLine(line, insideComment);
1482 catch (QuitException e)
1486 catch (bbtk::Exception e)
1490 catch (std::exception& e)
1492 std::cerr << "* ERROR :: "<<e.what()<<" (not in bbtk)"<<std::endl;
1496 std::cerr << "* UNDEFINED ERROR (not a bbtk nor a std exception)"<<std::endl;
1501 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1502 tcsetattr(0,TCSANOW,&oter);
1505 std::cout << "Good bye !" << std::endl;
1507 bbtkDebugDecTab("Interpreter",9);
1510 //=======================================================================
1511 void Interpreter::Graph(const std::vector<std::string>& words)
1514 bool system_display = true;
1516 #ifdef _USE_WXWIDGETS_
1517 if ( WxConsole::GetInstance() != 0 ) system_display = false;
1520 if (words.size()==1)
1522 page = mExecuter->ShowGraph(".","0","0","","","",system_display);
1524 else if (words.size()==2)
1526 page = mExecuter->ShowGraph(words[1],"0","0","","","",system_display);
1528 else if (words.size()==3)
1530 page = mExecuter->ShowGraph(words[1],words[2],"0","","","",system_display);
1532 else if (words.size()==4)
1534 page = mExecuter->ShowGraph(words[1],words[2],words[3],"","","",system_display);
1536 else if (words.size()==5)
1538 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],"","",system_display);
1540 else if (words.size()==6)
1542 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],"",system_display);
1544 else if (words.size()==7)
1546 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],words[6],system_display);
1549 #ifdef _USE_WXWIDGETS_
1550 if ( WxConsole::GetInstance() != 0 )
1551 WxConsole::GetInstance()->ShowHtmlPage(page);
1554 //=======================================================================
1557 //=======================================================================
1558 void Interpreter::Index(const std::string& filename,
1559 const std::string& type)
1561 Factory::IndexEntryType t;
1562 if (type=="Initials") t = Factory::Initials;
1563 else if (type=="Categories") t = Factory::Categories;
1564 else if (type=="Packages") t = Factory::Packages;
1566 GetGlobalFactory()->CreateHtmlIndex(t,filename);
1568 //=======================================================================