1 /*=========================================================================
4 Module: $RCSfile: bbtkInterpreter.cxx,v $ $
6 Date: $Date: 2008/02/04 13:02:58 $
7 Version: $Revision: 1.18 $
9 Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
10 l'Image). All rights reserved. See Doc/License.txt or
11 http://www.creatis.insa-lyon.fr/Public/bbtk/License.html for details.
13 This software is distributed WITHOUT ANY WARRANTY; without even
14 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 PURPOSE. See the above copyright notices for more information.
17 =========================================================================*/
20 * \brief class Interpreter :
23 #include "bbtkInterpreter.h"
24 #include "bbtkMessageManager.h"
25 #include "bbtkConfigurationFile.h"
26 #include "bbtkWxConsole.h"
27 #include "bbtkUtilities.h"
29 #ifdef CMAKE_HAVE_TERMIOS_H
31 #define BBTK_USE_TERMIOS_BASED_PROMPT
39 Interpreter* Interpreter::mGlobalInterpreter = NULL;
41 //=======================================================================
45 Interpreter::Interpreter()
47 mCommandLine(false), verbose(false)
49 bbtk::MessageManager::RegisterMessageType("Echo","Level>0 : Prints the 'echo' commands of the user.\n\tLevel>1 : Prints the command being interpreted",1);
50 bbtk::MessageManager::RegisterMessageType("Interpreter","Messages of the interpreter",0);
51 bbtkDebugMessageInc("Interpreter",9,"Interpreter::Interpreter()" <<std::endl);
53 mGlobalInterpreter = this;
55 // mFactory = new bbtk::Factory();
56 mExecuter = new bbtk::Executer();
57 //mExecuter->SetFactory(mFactory);
59 // Builds the commands dict
66 info.syntax = "new <type> <name>";
67 info.help = "Creates a new black box of type <type> with name <name>";
68 mCommandDict[info.keyword] = info;
70 info.keyword = "delete";
74 info.syntax = "delete <box>";
75 info.help = "Deletes the black box of name <box>";
76 mCommandDict[info.keyword] = info;
78 info.keyword = "connect";
82 info.syntax = "connect <box1.output> <box2.input>";
83 info.help = "Connects the ouput <output> of black box <box1> to the input <input> of black box <box2>";
84 mCommandDict[info.keyword] = info;
86 info.keyword = "print";
90 info.syntax = "print <string>";
91 info.help = "Prints the string. Substitutes any token of the form '$box.output$' by the string adaptation of the output of the box (requires the right adaptor). No carriage return is issued at the end, use '\\n' to add carriage returns. The level of 'Echo' messages must be greater than 1 (see the command 'message').";
92 mCommandDict[info.keyword] = info;
94 info.keyword = "exec";
98 info.syntax = "exec <box | 'freeze' | 'unfreeze' >";
99 info.help = "Executes the black box of name <box> (and connected boxes if needed). If the special keyword 'freeze' is given then freezes any further execution command. 'unfreeze' reverts to normal execution mode.";
100 mCommandDict[info.keyword] = info;
102 info.keyword = "package";
105 info.code = cPackage;
106 info.syntax = "package <name>";
107 info.help = "Begins the definition of a package.";
108 mCommandDict[info.keyword] = info;
110 info.keyword = "endpackage";
113 info.code = cEndPackage;
114 info.syntax = "endpackage";
115 info.help = "Ends the definition of a package.";
116 mCommandDict[info.keyword] = info;
118 info.keyword = "define";
122 info.syntax = "define <type> [<package>]";
123 info.help = "Begins the definition of a new type of complex black box called <type>. If <package> if provided will create it in the given package.";
124 mCommandDict[info.keyword] = info;
126 info.keyword = "endefine";
129 info.code = cEndDefine;
130 info.syntax = "endefine";
131 info.help = "Ends the definition of a new type of complex black box";
132 mCommandDict[info.keyword] = info;
134 info.keyword = "input";
138 info.syntax = "input <name> <box.input> <help>";
139 info.help = "Defines the input <name> of the current working black box as being an alias for the input <input> of the black box <box>. <help> defines the help string for the newly created input";
140 mCommandDict[info.keyword] = info;
142 info.keyword = "output";
146 info.syntax = "output <name> <box.output> <help>";
147 info.help = "Defines the output <name> of the current working black box as being an alias for the output <output> of the black box <box>. <help> defines the help string for the newly created output";
148 mCommandDict[info.keyword] = info;
150 info.keyword = "set";
154 info.syntax = "set <box.input> <value>";
155 info.help = "Sets the value of the input <input> of the black box <box> to <value>. There must exist a string to the value type adaptor";
156 mCommandDict[info.keyword] = info;
158 info.keyword = "config"; // JPR
162 info.syntax = "config [<verbose>|<v>]";
163 info.help = "Prints the value of all configuration parameters";
164 mCommandDict[info.keyword] = info;
166 info.keyword = "index"; // LG
170 info.syntax = "index [<filename> ['Initials'(default)|'Packages'|'Keywords']]";
171 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 'Keywords' is provided then the entries are either the package names or the keywords";
172 mCommandDict[info.keyword] = info;
174 info.keyword = "reset"; //EED
178 info.syntax = "reset";
179 info.help = "Deletes all boxes and unloads all packages (bbi is reset to its start state)";
180 mCommandDict[info.keyword] = info;
182 info.keyword = "author";
186 info.syntax = "author <string>";
187 info.help = "Adds the string <string> to the author information of the black box being defined";
188 mCommandDict[info.keyword] = info;
190 info.keyword = "keyword"; //JP
193 info.code = cKeyword;
194 info.syntax = "keyword <list of items, separated by ;>";
195 info.help = "Adds the string <string> to the keyword information of the black box being defined";
196 mCommandDict[info.keyword] = info;
198 info.keyword = "description";
201 info.code = cDescription;
202 info.syntax = "description <string>";
203 info.help = "Adds the string <string> to the descriptive information of the black box being defined";
204 mCommandDict[info.keyword] = info;
206 info.keyword = "help";
210 info.syntax = "help";
211 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>";
212 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.";
213 mCommandDict[info.keyword] = info;
215 info.keyword = "message";
218 info.code = cMessage;
219 info.syntax = "message <category> <level>";
220 info.help = "Sets the level of the category of messages <category> to <level>.\n If category='All' then sets the level for all categories. If no category nor level is passed then prints info on available categories of messages and their current level.";
221 mCommandDict[info.keyword] = info;
223 info.keyword = "include";
226 info.code = cInclude;
227 info.syntax = "include <filename>";
228 info.help = "Includes the file <filename>";
229 mCommandDict[info.keyword] = info;
231 info.keyword = "quit";
235 info.syntax = "quit";
236 info.help = "Quits the program (during script execution it stops the complete execution)";
237 mCommandDict[info.keyword] = info;
239 info.keyword = "load";
243 info.syntax = "load <packagename>";
244 info.help = "Loads the black box package <packagename>";
245 mCommandDict[info.keyword] = info;
247 info.keyword = "unload";
251 info.syntax = "unload <packagename>";
252 info.help = "Unloads the black box package <packagename>";
253 mCommandDict[info.keyword] = info;
255 info.keyword = "graph";
259 info.syntax = "graph [ BlackBoxName [ Detail 0..1 [ Level 0..99999 [ Output html file [ Custom header [ Custom title ]]]]]] \n graph [ BlackBoxNameType [ Detail 0..1 [ Level 0..99999 [ Output html file [ Custom header [ Custom title ]]]]]]";
260 info.help = "Shows a graphical view of a bbtk pipeline.\n- BlackBoxName : name of the box to view. Default '.' : current box.\n- BlackBoxNameType : name of the type of box to view, ex : 'workspace')";
261 mCommandDict[info.keyword] = info;
264 info.keyword = "workspace";
267 info.code = cWorkspace;
268 info.syntax = "workspace < ( freeze | unfreeze ) | ( rename <newname> ) >";
269 info.help = "Configures the workspace.\n 'freeze' allow to block execution commands while keeping definition commands active. 'unfreeze' turns back the worspace in 'normal' mode.\n 'rename' allow to set a new name to the workspace.";
270 mCommandDict[info.keyword] = info;
273 bbtkDebugDecTab("Interpreter",9);
276 //=======================================================================
280 //=======================================================================
284 Interpreter::~Interpreter()
286 bbtkDebugMessageInc("Interpreter",9,"Interpreter::~Interpreter()" <<std::endl);
290 // std::cout <<"EO Interpreter::~Interpreter()"<<std::endl;
291 bbtkDebugDecTab("Interpreter",9);
293 //=======================================================================
296 //=======================================================================
300 void Interpreter::InterpretFile( const std::string& filename, bool use_configuration_file, bool verbose)
302 bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretFile(\""<<filename<<"\")"<<std::endl);
304 bool exm = mCommandLine;
305 mCommandLine = false;
309 SwitchToFile(filename, use_configuration_file, verbose);
310 bool insideComment = false; // for multiline comment
311 while (mFile.size()>0)
313 while ((mFile.size()>0) &&
314 (!mFile.back()->eof()))
318 mFile.back()->getline(buf,500);
320 std::string str(buf);
321 int size=str.length();
322 if ( str[ size-1 ]==13 )
327 InterpretLine(str, insideComment);
329 //if (mFile.size()>0)
333 catch (QuitException e)
336 catch (bbtk::Exception e)
338 std::cerr << "* ERROR : "<<e.GetMessage()<<std::endl;
339 if (mFileName.size()) {
340 std::cerr << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
341 std::cerr << "* LINE : "<<mLine.back()<<std::endl;
344 catch (std::exception& e)
346 std::cerr << "* ERROR : "<<e.what()<<" (not in bbtk)"<<std::endl;
347 if (mFileName.size()) {
348 std::cerr << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
349 std::cerr << "* LINE : "<<mLine.back()<<std::endl;
354 std::cout << "* UNDEFINED ERROR (not a bbtk nor a std exception)"<<std::endl;
355 if (mFileName.size()) {
356 std::cout << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
357 std::cout << "* LINE : "<<mLine.back()<<std::endl;
362 bbtkDebugMessage("Interpreter",9,"EO Interpreter::InterpretFile(\""<<filename<<"\")"<<std::endl);
363 bbtkDecTab("Interpreter",9);
367 //=======================================================================
371 //=======================================================================
375 void Interpreter::InterpretLine( const std::string& line, bool &insideComment )
378 bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretLine(\""<<line<<"\")"<<std::endl);
379 bbtkMessage("Echo",2,"\""<<line<<"\""<<std::endl);
381 std::vector<std::string> words;
382 SplitLine(line,words);
387 bbtkDebugDecTab("Interpreter",9);
391 // Single line comment : # or //
392 if ( words[0][0]=='#' || (words[0][0]=='/' && words[0][1]=='/') )
394 bbtkDebugDecTab("Interpreter",9);
395 bbtkMessage("Interpreter",9,"Comment"<<std::endl);
399 // Multi line comment ( /* ... */ ) -delimiters on different lines !-
401 if (words[0][0]=='/' && words[0][1]=='*')
403 bbtkDebugDecTab("Interpreter",9);
404 bbtkMessage("Interpreter",9,"In multiline comment"<<std::endl);
405 insideComment = true;
409 if (words[0][0]=='*' && words[0][1]=='/')
411 bbtkDebugDecTab("Interpreter",9);
412 bbtkMessage("Interpreter",9,"Out multiline comment"<<std::endl);
413 if ( !insideComment ) {
414 bbtkDebugDecTab("Interpreter",9);
415 bbtkMessage("Interpreter",9,"Comment mismatch : '*/' with no matching '/*'"<<std::endl);
417 insideComment = false;
423 bbtkDebugDecTab("Interpreter",9);
424 bbtkMessage("Interpreter",9,"Multiline Comment"<<std::endl);
429 CommandInfoType command;
430 InterpretCommand(words,command);
432 bbtkDebugMessage("Interpreter",9,
433 "Command='"<<command.keyword
434 <<"' code="<<command.code<<std::endl);
436 std::string left,right,left2,right2;
437 std::string filename;
438 switch (command.code)
441 mExecuter->Create(words[1],words[2]);
446 // mExecuter->Remove(words[1]);
450 Utilities::SplitAroundFirstDot(words[1],left,right);
451 Utilities::SplitAroundFirstDot(words[2],left2,right2);
452 mExecuter->Connect(left,right,left2,right2);
456 mExecuter->BeginPackage(words[1]);
460 mExecuter->EndPackage();
464 if (mFileName.size()>0)
466 filename = Utilities::get_file_name(mFileName.back());
470 mExecuter->Define(words[1],"",filename);
474 mExecuter->Define(words[1],words[2],filename);
479 mExecuter->EndDefine();
483 Print(words[1]); /// \todo use mExecuter
487 if (words[1]=="freeze")
488 mExecuter->SetNoExecMode(true);
489 else if (words[1]=="unfreeze")
490 mExecuter->SetNoExecMode(false);
492 mExecuter->Update(words[1]);
496 Utilities::SplitAroundFirstDot(words[2],left,right);
497 mExecuter->DefineInput(words[1],left,right,words[3]);
501 Utilities::SplitAroundFirstDot(words[2],left,right);
502 mExecuter->DefineOutput(words[1],left,right,words[3]);
506 Utilities::SplitAroundFirstDot(words[1],left,right);
507 mExecuter->Set(left,right,words[2]);
511 mExecuter->Author(words[1]);
515 mExecuter->Keyword(words[1]);
520 Index("tmp_index.html");
521 else if (words.size()==2)
523 else if (words.size()==3)
524 Index(words[1],words[2]);
527 mExecuter->Description(words[1]);
537 bbtk::MessageManager::PrintInfo();
541 sscanf(words[2].c_str(),"%d",&level);
542 bbtk::MessageManager::SetMessageLevel(words[1],level);
551 if (words.size()>1) // any param for config means verbose = true
559 this->mExecuter->Reset();
565 InterpretFile(words[1], true, verbose); // true : better pass use_config_file
569 SwitchToFile(words[1], true, verbose); // true : better pass use_config_file
574 LoadPackage(words[1], true, verbose); // true : better pass use_config_file
578 UnLoadPackage(words[1]);
582 throw QuitException();
586 if (words.size() == 2)
588 if (words[1]=="freeze") mExecuter->SetNoExecMode(true);
589 else if (words[1]=="unfreeze") mExecuter->SetNoExecMode(false);
593 mExecuter->SetWorkspaceName(words[2]);
598 bbtkInternalError("should not reach here !!!");
601 bbtkDecTab("Interpreter",9);
603 //=======================================================================
609 //=======================================================================
613 void Interpreter::SplitLine ( const std::string& str, std::vector<std::string>& tokens)
615 bbtkDebugMessageInc("Interpreter",9,"Interpreter::SplitLine(\""<<str<<"\")"<<std::endl);
617 std::string delimiters = "\"";
618 std::vector<std::string> quote;
619 Utilities::SplitString(str,delimiters,quote);
622 std::vector<std::string>::iterator i;
623 for (i=quote.begin(); i!=quote.end(); )
625 Utilities::SplitString(*i,delimiters,tokens);
629 // bbtkDebugMessage("Interpreter",0,"\""<<*i<<"\""<<std::endl);
630 tokens.push_back(*i);
635 for (i=tokens.begin(); i!=tokens.end(); ++i)
637 bbtkDebugMessage("Interpreter",9,"["<<*i<<"] ");
639 bbtkDebugMessageCont("Interpreter",9,std::endl);
641 bbtkDebugDecTab("Interpreter",9);
643 //=======================================================================
646 //=======================================================================
647 // Replaces substrings "\\n" by a real carriage return "\n"
648 void SubsBackslashN ( std::string& s )
650 // std::cout << "BEFORE=["<<s<<"]"<<std::endl;
651 std::string ss("\\n");
652 std::string::size_type pos = 0;
655 while ( pos != std::string::npos )
657 // std::cout << "*** find one "<<std::endl;
658 s.replace(pos,2,cr,1);
659 pos = s.find(ss, pos-1);
661 // std::cout << "AFTER=["<<s<<"]"<<std::endl;
663 //=======================================================================
666 //=======================================================================
670 void Interpreter::Print( const std::string& str)
672 if (mExecuter->GetNoExecMode()) return;
674 bbtkDebugMessageInc("Interpreter",9,"Interpreter::SplitLine(\""<<str<<"\")"<<std::endl);
676 std::vector<std::string> chains;
677 std::string delimiters("$");
679 // Skip delimiters at beginning.
680 std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
682 if (lastPos>0) is_text = false;
684 // Find first delimiter.
685 std::string::size_type pos = str.find_first_of(delimiters, lastPos);
687 while (std::string::npos != pos || std::string::npos != lastPos)
691 // Found a text token, add it to the vector.
692 chains.push_back(str.substr(lastPos, pos - lastPos));
693 // std::cout << "text='"<<chains.back()<<"'"<<std::endl;
697 // is an output (between $$) : decode
698 std::string tok,box,output;
699 tok = str.substr(lastPos, pos - lastPos);
700 Utilities::SplitAroundFirstDot(tok,box,output);
701 chains.push_back( mExecuter->Get(box,output) );
702 // std::cout << "outp='"<<chains.back()<<"'"<<std::endl;
704 // Skip delimiters. Note the "not_of"
705 lastPos = str.find_first_not_of(delimiters, pos);
706 // Find next delimiter
707 pos = str.find_first_of(delimiters, lastPos);
711 // std::cout << "nb="<<chains.size()<<std::endl;
712 std::vector<std::string>::iterator i;
713 for (i= chains.begin(); i!=chains.end(); ++i)
715 // bbtkMessage("Echo",1,*i);
719 std::cout << std::endl;
720 bbtkDebugDecTab("Interpreter",9);
723 //=======================================================================
728 // ===================================================================================
730 void Interpreter::SwitchToFile( const std::string& name,
731 bool use_configuration_file, bool verbose)
733 // Note : in the following :
734 // name : the user supplied name
735 // - abreviated name e.g. scr scr.bbs
736 // - relative full name e.g. ./scr.bbs ../../scr.bbs
737 // - absolute full name e.g. /home/usrname/proj/dir/scr.bbs
738 // same for Windows, with c:, d: ...
740 // use ./directory/subdir/scrname.bbs
743 bbtkDebugMessageInc("Interpreter",9,"Interpreter::SwitchToFile( \""
744 <<name<<"\")"<<std::endl);
746 // to be removed in final version
749 std::vector<std::string> script_paths;
750 std::string fullPathScriptName; // full path script name
751 std::string pkgname; // e.g. <scriptname>.bbs
752 std::vector<std::string> Filenames;
754 if (use_configuration_file)
756 // The following is *NOT* a debug time message :
757 // It's a user intended message.
758 // Please don't remove it.
760 std::cout << "look for : [" << name << "] (use_configuration_file == TRUE)" << std::endl;
761 script_paths = ConfigurationFile::GetInstance().Get_bbs_paths();
764 pkgname = Utilities::ExtractScriptName(name,upath);
765 //std::cout <<"name [" << name << "] pkgname [" << pkgname << "] upath [" << upath << "]" << std::endl;
766 bool fullnameGiven = false;
767 bool foundFile = false;
769 if(pkgname == "*") // =========================================== load all boxes (e.g. std/boxes/*)
773 if (upath[0]=='/' || upath[1] == ':' ) // ==== absolute name, load all .bbs files
775 int nbFiles = Utilities::Explore(upath, false, Filenames);
777 for (std::vector<std::string>::iterator i = Filenames.begin(); i!= Filenames.end(); ++i)
779 if ((*i).substr((*i).size()-4, 4) != ".bbs")
780 continue; // ignore non .bbs files
786 std::cout << "WARNING : No '.bbs' file found in [" << upath << "]" << std::endl;
793 std::vector<std::string>::iterator i;
794 std::string fullDirectoryName;
795 for (i=script_paths.begin();i!=script_paths.end();++i)// ==== relative name, iterate + load all .bbs files
799 // we *really* want '.' to be the current working directory
801 char buf[2048]; // for getcwd
802 char * currentDir = getcwd(buf, 2048);
803 std::string cwd(currentDir);
807 fullDirectoryName = Utilities::MakePkgnameFromPath(path, upath, false);
808 //std::cout <<"fullpath [" << fullDirectoryName << "]" <<std::endl;
809 // Check if library exists
810 if ( ! Utilities::IsDirectory(fullDirectoryName) )
812 // The following is *NOT* a debug time message :
813 // It's a user intended message.
814 // Please don't remove it.
816 std::cout <<" [" <<fullDirectoryName <<"] : doesn't exist" <<std::endl;
817 continue; // try next path
822 int nbFiles = Utilities::Explore(fullDirectoryName, false, Filenames);
823 // std::cout << "=================nbFiles " << nbFiles << std::endl;
825 for (std::vector<std::string>::iterator i = Filenames.begin(); i!= Filenames.end(); ++i)
827 if ((*i).substr((*i).size()-4, 4) != ".bbs")
828 continue; // ignore non .bbs files
834 std::cout << "WARNING : No '.bbs' file found in [" << fullDirectoryName << "]" << std::endl;
836 break; // a directory was found; we stop iterating
841 //std::string::size_type slash_position = name.find_last_of("/\\");
843 // if name starts with a / or a . or contains : user is assumed to have passed a relative/absolute name
844 // (not only a plain script name)
845 // we trust him, and try to expland the directory name
846 // WARNING : starting from current local directory : ./whatYouWant (./ mandatory!)
848 if (name[0]=='/' || name[1] == ':' || name[0]=='.') // absolute path (linux/windows) or relative path
851 // ===========================================================check user supplied location
852 fullnameGiven = true;
854 fullPathScriptName = Utilities::ExpandLibName(name, verbose);
856 // allow user to always forget ".bbs"
857 int l = fullPathScriptName.size();
863 if (fullPathScriptName.substr(l-4, 4) != ".bbs")
865 fullPathScriptName = fullPathScriptName + ".bbs";
870 fullPathScriptName = fullPathScriptName + ".bbs";
873 if ( Utilities::FileExists(fullPathScriptName))
881 // =============================================================== iterate on the paths
884 std::vector<std::string>::iterator i;
885 for (i=script_paths.begin();i!=script_paths.end();++i)
889 // we *really* want '.' to be the current working directory
891 char buf[2048]; // for getcwd
892 char * currentDir = getcwd(buf, 2048);
893 std::string cwd(currentDir);
897 // fullPathScriptName = Utilities::MakePkgnameFromPath(path, name, true); //pkgname);
899 fullPathScriptName = Utilities::MakePkgnameFromPath(path, name, true);
900 //std::cout << "FULL PATH = "<<fullPathScriptName<<std::endl;
902 // Check if library exists
903 if ( ! Utilities::FileExists(fullPathScriptName) )
905 // The following is *NOT* a debug time message :
906 // It's a user intended message.
907 // Please don't remove it.
909 std::cout <<" [" <<fullPathScriptName <<"] : doesn't exist" <<std::endl;
910 continue; // try next path
913 std::cout <<" [" <<fullPathScriptName <<"] : found" <<std::endl;
915 break; // a script was found; we stop iterating
917 } //------------------ // end for ( package_paths.begin();i!=package_paths.end() )
923 if(fullPathScriptName == "")
924 bbtkError("Path ["<<upath<<"] doesn't exist");
926 bbtkError("Script ["<<fullPathScriptName<<"] not found");
928 bbtkError("No ["<<pkgname<<".bbs] script found");
932 LoadScript(fullPathScriptName);
938 //=======================================================================
940 void Interpreter::LoadScript( std::string fullPathScriptName)
942 bbtkMessage("Interpreter",1,fullPathScriptName<<" found"<<std::endl);
945 s = new std::ifstream;
946 s->open(fullPathScriptName.c_str());
949 bbtkError("Could not open file ["<<fullPathScriptName<<"]");
954 std::cout << " -->[" << fullPathScriptName << "] found" << std::endl;
957 mFileName.push_back(fullPathScriptName);
962 //=======================================================================
966 void Interpreter::CloseCurrentFile()
968 bbtkDebugMessage("Interpreter",9,"Interpreter::CloseCurrentFile()"
973 bbtkDebugMessage("Interpreter",9," -> no file left open"<<std::endl);
977 mFile.back()->close();
980 bbtkDebugMessage("Interpreter",9,
981 " Closing file '"<<mFileName.back()<<"'"<<std::endl);
983 mFileName.pop_back();
985 bbtkDebugMessage("Interpreter",9," Remains "
987 <<" open"<<std::endl);
988 bbtkDebugMessage("Interpreter",9,"EO Interpreter::CloseCurrentFile()"
991 //=======================================================================
993 //=======================================================================
997 void Interpreter::CloseAllFiles()
999 bbtkDebugMessage("Interpreter",9,"Interpreter::CloseAllFiles()"
1002 while (mFile.size() != 0)
1004 mFile.back()->close();
1005 delete mFile.back();
1007 bbtkDebugMessage("Interpreter",9,
1008 " Closing file '"<<mFileName.back()<<"'"<<std::endl);
1009 mFileName.pop_back();
1012 bbtkDebugMessage("Interpreter",9,"EO Interpreter::CloseAllFiles()"
1015 //=======================================================================
1019 //=======================================================================
1023 void Interpreter::InterpretCommand( const std::vector<std::string>& words,
1024 CommandInfoType& info )
1026 bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretCommand(...)"<<std::endl);
1028 // searches the command keyword
1029 CommandDictType::iterator c;
1030 c = mCommandDict.find(words[0]);
1031 if ( c == mCommandDict.end() ) {
1032 bbtkError(words[0]<<" : unknown command");
1035 // tests the number of args
1036 if ( ( words.size()-1 < c->second.argmin ) ||
1037 ( words.size()-1 > c->second.argmax ) )
1039 HelpCommand(words[0]);
1040 bbtkError(words[0]<<" : wrong number of arguments");
1044 bbtkDecTab("Interpreter",9);
1046 //=======================================================================
1049 //=======================================================================
1050 /// Displays help on all the commands
1051 void Interpreter::Help(const std::vector<std::string>& words)
1053 unsigned int nbarg = words.size()-1;
1061 if (words[1]=="packages")
1063 PrintPackages(true);
1068 HelpCommand(words[1]);
1070 catch (bbtk::Exception e)
1074 HelpPackage(words[1]);
1076 catch (bbtk::Exception f)
1080 HelpBlackBox(words[1]);
1082 catch (bbtk::Exception g)
1086 this->mExecuter->ShowRelations(words[1],"0","9999");
1088 catch (bbtk::Exception h){
1089 bbtkError("\""<<words[1].c_str()
1090 <<"\" is not a known command, package, black box type or black box name");
1098 if (words[2]=="all")
1100 if ( words[1]=="packages" )
1102 PrintPackages(true,true);
1107 HelpPackage(words[1],true);
1109 catch (bbtk::Exception f)
1115 HelpCommand(words[0]);
1116 bbtkError(words[0]<<" : syntax error");
1121 bbtkError("Should not reach here !!!");
1124 //=======================================================================
1126 //===================================================================
1127 /// Displays the Configuration
1128 void Interpreter::Config( bool verbose ) const
1130 bbtkDebugMessageInc("Core",9,"Factory::Config"<<std::endl);
1132 ConfigurationFile cf = ConfigurationFile::GetInstance();
1134 const std::string config_xml_full_path = cf.Get_config_xml_full_path();
1135 const std::string description = cf.Get_description();
1136 const std::string url = cf.Get_url();
1137 const std::string data_path = cf.Get_data_path();
1138 const std::string default_doc_tmp = cf.Get_default_doc_tmp();
1139 const std::string file_separator = cf.Get_file_separator();
1140 const std::vector<std::string>bbs_paths = cf.Get_bbs_paths();
1141 const std::vector<std::string>package_paths = cf.Get_package_paths();
1143 bbtkMessage("Help",1, "=============" << std::endl);
1144 bbtkMessage("Help",1, "Configuration" << std::endl);
1145 bbtkMessage("Help",1, "=============" << std::endl);
1146 bbtkMessage("Help",1, "bbtk_config.xml : [" << config_xml_full_path << "]" << std::endl);
1147 bbtkMessage("Help",1, "Documentation Url : [" << url << "]" << std::endl);
1148 bbtkMessage("Help",1, "Data Path : [" << data_path << "]" << std::endl);
1149 bbtkMessage("Help",1, "Default Doc_tmp : [" << default_doc_tmp << "]" << std::endl);
1150 bbtkMessage("Help",1, "File Separator : [" << file_separator << "]" << std::endl);
1152 std::vector<std::string>::const_iterator i;
1154 bbtkMessage("Help",1, "BBS Paths " << std::endl);
1155 for (i = bbs_paths.begin(); i!=bbs_paths.end(); ++i )
1157 bbtkMessage("Help",1,"--- ["<<*i<<"]"<<std::endl);
1160 bbtkMessage("Help",1, "PACKAGE Paths : " << std::endl);
1161 for (i = package_paths.begin(); i!=package_paths.end(); ++i )
1163 bbtkMessage("Help",1,"--- ["<<*i<<"]"<<std::endl);
1166 bbtkDebugDecTab("Core",9);
1169 //=======================================================================
1170 /// Displays help on all the commands
1171 void Interpreter::HelpCommands()
1173 std::cout << "Available commands :" << std::endl;
1174 CommandDictType::iterator i;
1175 for ( i = mCommandDict.begin();
1176 i != mCommandDict.end();
1178 std::cout << " " << i->first << std::endl;
1179 // std::cout << " usage : " << i->second.syntax << std::endl;
1180 // std::cout << " " << i->second.help << std::endl;
1184 //=======================================================================
1187 //=======================================================================
1188 /// Displays help on a particular commands
1189 void Interpreter::HelpCommand(const std::string& s)
1191 CommandDictType::iterator c;
1192 c = mCommandDict.find(s);
1193 if ( c == mCommandDict.end() ) {
1194 bbtkError(s<<" : Unknown command");
1196 // std::cout << " " << s << " : "<< std::endl;
1197 // CommandParamDictType::iterator i;
1198 // for ( i = c->second.begin();
1199 // i != c->second.end();
1201 std::cout << " usage : " << c->second.syntax << std::endl;
1202 std::cout << " " << c->second.help << std::endl;
1205 //=======================================================================
1208 //=======================================================================
1209 /// Fills the vector commands with the commands which
1210 /// have the first n chars of buf for prefix
1211 /// TODO : skip initial spaces in buf and also return the position of first
1212 /// non blank char in buf
1213 void Interpreter::FindCommandsWithPrefix( char* buf,
1215 std::vector<std::string>& commands )
1217 CommandDictType::const_iterator i;
1218 for (i=mCommandDict.begin(); i!=mCommandDict.end(); ++i)
1220 if ((i->first).find(buf,0,n) == 0)
1221 commands.push_back(i->first);
1224 //=======================================================================
1228 //=======================================================================
1229 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1231 inline void PrintChar(char c) { write(STDOUT_FILENO,&c,1); }
1232 inline void BackSpace() { write(STDOUT_FILENO,"\b \b",3); }
1234 // LG : KEYBOARD CODES AS SCANNED ON MY TTY : UNIVERSAL ?
1235 // IF NOT THE USER SHOULD BE ABLE TO CONFIGURE IT
1236 // E.G. STORE THIS IN bbtk_config.xml
1237 #define BBTK_UP_ARROW_KBCODE 0x00415B1B
1238 #define BBTK_DOWN_ARROW_KBCODE 0x00425B1B
1239 #define BBTK_RIGHT_ARROW_KBCODE 0x00435B1B
1240 #define BBTK_LEFT_ARROW_KBCODE 0x00445B1B
1241 #define BBTK_BACKSPACE_KBCODE 0x00000008
1242 #define BBTK_DEL_KBCODE 0x0000007F
1243 #define BBTK_SPACE_KBCODE 0x00000020
1245 //=======================================================================
1246 void Interpreter::GetLineFromPrompt(std::string& s)
1251 int MAX_LINE_SIZE = 160;
1252 int MAX_HISTORY_SIZE = 100;
1254 char* newline = new char[MAX_LINE_SIZE];
1255 memset(newline,0,MAX_LINE_SIZE);
1256 char* histline = new char[MAX_LINE_SIZE];
1257 memset(histline,0,MAX_LINE_SIZE);
1259 char* line = newline;
1260 int hist = mHistory.size();
1267 read ( STDIN_FILENO, &c, 4) ;
1269 bbtkDebugMessage("Debug",9,"[0x"<<std::hex<<c<<"]\n");
1271 // Printable character
1272 if ( (ind<MAX_LINE_SIZE-1) &&
1273 ( c >= BBTK_SPACE_KBCODE ) &&
1274 ( c < BBTK_DEL_KBCODE ))
1282 // delete the unused line
1288 // empty lines are not stored in from history
1291 // if history too long : delete oldest command
1292 if (mHistory.size()>MAX_HISTORY_SIZE)
1294 delete mHistory.front();
1295 mHistory.pop_front();
1297 mHistory.push_back(line);
1302 else if ( (ind>0) &&
1303 ((c == BBTK_BACKSPACE_KBCODE) ||
1304 (c == BBTK_DEL_KBCODE)) )
1312 // TODO : Command completion
1313 std::vector<std::string> commands;
1314 FindCommandsWithPrefix( line,ind,commands);
1315 if (commands.size()==1)
1317 std::string com = *commands.begin();
1318 for (; ind<com.size(); ++ind)
1320 PrintChar(com[ind]);
1326 else if (commands.size()>1)
1328 std::vector<std::string>::iterator i;
1330 for (i=commands.begin();i!=commands.end();++i)
1332 write(STDOUT_FILENO,(*i).c_str(),strlen((*i).c_str()));
1335 write(STDOUT_FILENO,"\n> ",3);
1336 //for (int j=0;j<ind;++j)
1338 write(STDOUT_FILENO,line,ind);
1342 // Arrow up : back in history
1343 else if (c==BBTK_UP_ARROW_KBCODE)
1347 // erase current line
1348 while (ind--) BackSpace();
1352 strcpy(histline,mHistory[hist]);
1356 write(STDOUT_FILENO,line,ind);
1359 // Arrow down : down in history
1360 else if (c==BBTK_DOWN_ARROW_KBCODE)
1362 if (hist<mHistory.size()-1)
1364 // erase current line
1365 while (ind--) BackSpace();
1369 strcpy(histline,mHistory[hist]);
1373 write(STDOUT_FILENO,line,ind);
1375 // end of history : switch back to newline
1376 else if (hist==mHistory.size()-1)
1378 // erase current line
1379 while (ind--) BackSpace();
1386 write(STDOUT_FILENO,line,ind);
1390 else if (line[ind]!=0 && c==BBTK_RIGHT_ARROW_KBCODE)
1392 PrintChar(line[ind]);
1397 else if (ind>0 && c==BBTK_LEFT_ARROW_KBCODE)
1405 write(STDOUT_FILENO,"\n\r",2);
1413 //=======================================================================
1414 void Interpreter::GetLineFromPrompt(std::string& s)
1440 //=======================================================================
1446 //=======================================================================
1447 void Interpreter::CommandLineInterpreter()
1449 bbtkDebugMessageInc("Interpreter",9,
1450 "Interpreter::CommandLineInterpreter()"<<std::endl);
1452 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1453 // Initialise the tty in non canonical mode with no echo
1454 // oter remembers the previous settings to restore them after
1455 struct termios ter,oter;
1458 ter.c_lflag &= ~ECHO;
1459 ter.c_lflag &= ~ICANON;
1462 tcsetattr(0,TCSANOW,&ter);
1465 mCommandLine = true;
1467 bool insideComment = false; // for multiline comment
1473 GetLineFromPrompt(line);
1474 InterpretLine(line, insideComment);
1476 catch (QuitException e)
1480 catch (bbtk::Exception e)
1484 catch (std::exception& e)
1486 std::cerr << "* ERROR :: "<<e.what()<<" (not in bbtk)"<<std::endl;
1490 std::cerr << "* UNDEFINED ERROR (not a bbtk nor a std exception)"<<std::endl;
1495 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1496 tcsetattr(0,TCSANOW,&oter);
1499 std::cout << "Good bye !" << std::endl;
1501 bbtkDebugDecTab("Interpreter",9);
1504 //=======================================================================
1505 void Interpreter::Graph(const std::vector<std::string>& words)
1508 bool system_display = true;
1510 #ifdef _USE_WXWIDGETS_
1511 if ( WxConsole::GetInstance() != 0 ) system_display = false;
1514 if (words.size()==1)
1516 page = mExecuter->ShowGraph(".","0","0","","","",system_display);
1518 else if (words.size()==2)
1520 page = mExecuter->ShowGraph(words[1],"0","0","","","",system_display);
1522 else if (words.size()==3)
1524 page = mExecuter->ShowGraph(words[1],words[2],"0","","","",system_display);
1526 else if (words.size()==4)
1528 page = mExecuter->ShowGraph(words[1],words[2],words[3],"","","",system_display);
1530 else if (words.size()==5)
1532 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],"","",system_display);
1534 else if (words.size()==6)
1536 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],"",system_display);
1538 else if (words.size()==7)
1540 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],words[6],system_display);
1543 #ifdef _USE_WXWIDGETS_
1544 if ( WxConsole::GetInstance() != 0 )
1545 WxConsole::GetInstance()->ShowHtmlPage(page);
1548 //=======================================================================
1551 //=======================================================================
1552 void Interpreter::Index(const std::string& filename,
1553 const std::string& type)
1555 Factory::IndexEntryType t;
1556 if (type=="Initials") t = Factory::Initials;
1557 else if (type=="Keywords") t = Factory::Keywords;
1558 else if (type=="Packages") t = Factory::Packages;
1560 GetGlobalFactory()->CreateHtmlIndex(t,filename);
1562 //=======================================================================