1 /*=========================================================================
4 Module: $RCSfile: bbtkInterpreter.cxx,v $ $
6 Date: $Date: 2008/03/07 11:15:15 $
7 Version: $Revision: 1.41 $
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()
48 #ifdef _USE_WXWIDGETS_
53 bbtk::MessageManager::RegisterMessageType("Echo","Level>0 : Prints the 'echo' commands of the user.\n\tLevel>1 : Prints the command being interpreted",1);
54 bbtk::MessageManager::RegisterMessageType("Interpreter","Messages of the interpreter",0);
55 bbtkDebugMessageInc("Interpreter",9,"Interpreter::Interpreter()" <<std::endl);
57 mExecuter = new bbtk::Executer();
58 mExecuter->SetInterpreter(this);
60 // For the time being, comment out previous line, and
61 // uncomment next line to check Transcriptor
63 //mExecuter = new bbtk::Transcriptor("GeneratedProgram.txt");
65 // Builds the commands dict
68 info.category = "new";
72 info.syntax = "new <type> <name>";
73 info.help = "Creates a new black box of type <type> with name <name>";
74 mCommandDict[info.category] = info;
76 info.category = "delete";
80 info.syntax = "delete <box>";
81 info.help = "Deletes the black box of name <box>";
82 mCommandDict[info.category] = info;
84 info.category = "connect";
88 info.syntax = "connect <box1.output> <box2.input>";
89 info.help = "Connects the ouput <output> of black box <box1> to the input <input> of black box <box2>";
90 mCommandDict[info.category] = info;
92 info.category = "print";
96 info.syntax = "print <string>";
97 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').";
98 mCommandDict[info.category] = info;
100 info.category = "exec";
104 info.syntax = "exec <box | 'freeze' | 'unfreeze' >";
105 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.";
106 mCommandDict[info.category] = info;
108 info.category = "package";
111 info.code = cPackage;
112 info.syntax = "package <name>";
113 info.help = "Begins the definition of a package.";
114 mCommandDict[info.category] = info;
116 info.category = "endpackage";
119 info.code = cEndPackage;
120 info.syntax = "endpackage";
121 info.help = "Ends the definition of a package.";
122 mCommandDict[info.category] = info;
124 info.category = "define";
128 info.syntax = "define <type> [<package>]";
129 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.";
130 mCommandDict[info.category] = info;
132 info.category = "endefine";
135 info.code = cEndDefine;
136 info.syntax = "endefine";
137 info.help = "Ends the definition of a new type of complex black box";
138 mCommandDict[info.category] = info;
140 info.category = "input";
144 info.syntax = "input <name> <box.input> <help>";
145 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";
146 mCommandDict[info.category] = info;
148 info.category = "output";
152 info.syntax = "output <name> <box.output> <help>";
153 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";
154 mCommandDict[info.category] = info;
156 info.category = "set";
160 info.syntax = "set <box.input> <value>";
161 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";
162 mCommandDict[info.category] = info;
164 info.category = "config"; // JPR
168 info.syntax = "config";
169 info.help = "Prints the value of all configuration parameters";
170 mCommandDict[info.category] = info;
172 info.category = "index"; // LG
177 info.syntax = "index [<filename> ['Initials'(default)|'Packages'|'Categories'|'Adaptors']]";
178 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. If 'Adaptors' is provided then an alphabetical index of all adaptors is created.";
179 mCommandDict[info.category] = info;
181 info.category = "reset"; //EED
185 info.syntax = "reset";
186 info.help = "Deletes all boxes and unloads all packages (bbi is reset to its start state)";
187 mCommandDict[info.category] = info;
189 info.category = "author";
193 info.syntax = "author <string>";
194 info.help = "Adds the string <string> to the author information of the black box being defined";
195 mCommandDict[info.category] = info;
197 info.category = "category"; //JP
200 info.code = cCategory;
201 info.syntax = "category <list of items, separated by ;>";
202 info.help = "Adds the string <string> to the category information of the black box being defined";
203 mCommandDict[info.category] = info;
205 info.category = "description";
208 info.code = cDescription;
209 info.syntax = "description <string>";
210 info.help = "Adds the string <string> to the descriptive information of the black box being defined";
211 mCommandDict[info.category] = info;
213 info.category = "help";
217 info.syntax = "help";
218 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>";
219 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.";
220 mCommandDict[info.category] = info;
222 info.category = "message";
225 info.code = cMessage;
226 info.syntax = "message <kind> <level>";
227 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;
229 info.category = "include";
232 info.code = cInclude;
233 info.syntax = "include <filename> [source]";
234 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).";
235 mCommandDict[info.category] = info;
237 info.category = "quit";
241 info.syntax = "quit";
242 info.help = "Quits the program (during script execution it stops the complete execution)";
243 mCommandDict[info.category] = info;
245 info.category = "load";
249 info.syntax = "load <packagename>";
250 info.help = "Loads the black box package <packagename>";
251 mCommandDict[info.category] = info;
253 info.category = "unload";
257 info.syntax = "unload <packagename>";
258 info.help = "Unloads the black box package <packagename>";
259 mCommandDict[info.category] = info;
261 info.category = "graph";
265 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 ]]]]]]";
266 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')";
267 mCommandDict[info.category] = info;
270 info.category = "workspace";
273 info.code = cWorkspace;
274 info.syntax = "workspace < ( freeze | unfreeze ) | ( rename <newname> ) >";
275 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.";
276 mCommandDict[info.category] = info;
279 bbtkDebugDecTab("Interpreter",9);
282 //=======================================================================
286 //=======================================================================
290 Interpreter::~Interpreter()
293 std::cout << "=========================================~Interpreter()" << std::endl;
294 bbtkDebugMessageInc("Interpreter",9,"Interpreter::~Interpreter()" <<std::endl);
297 bbtkDebugDecTab("Interpreter",9);
299 //=======================================================================
302 //=======================================================================
306 void Interpreter::InterpretFile( const std::string& filename )
308 bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretFile(\""<<filename<<"\")"<<std::endl);
310 bool exm = mCommandLine;
311 mCommandLine = false;
315 SwitchToFile(filename);
316 bool insideComment = false; // for multiline comment
317 while (mFile.size()>0)
319 while ((mFile.size()>0) &&
320 (!mFile.back()->eof()))
324 mFile.back()->getline(buf,500);
326 std::string str(buf);
327 int size=str.length();
328 if ( str[ size-1 ]==13 )
333 InterpretLine(str, insideComment);
335 //if (mFile.size()>0)
339 catch (QuitException e)
342 catch (bbtk::Exception e)
344 std::cerr << "* ERROR : "<<e.GetMessage()<<std::endl;
345 if (mFileName.size()) {
346 std::cerr << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
347 std::cerr << "* LINE : "<<mLine.back()<<std::endl;
350 catch (std::exception& e)
352 std::cerr << "* ERROR : "<<e.what()<<" (not in bbtk)"<<std::endl;
353 if (mFileName.size()) {
354 std::cerr << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
355 std::cerr << "* LINE : "<<mLine.back()<<std::endl;
360 std::cout << "* UNDEFINED ERROR (not a bbtk nor a std exception)"<<std::endl;
361 if (mFileName.size()) {
362 std::cout << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
363 std::cout << "* LINE : "<<mLine.back()<<std::endl;
368 bbtkDebugMessage("Interpreter",9,"EO Interpreter::InterpretFile(\""<<filename<<"\")"<<std::endl);
369 bbtkDecTab("Interpreter",9);
373 //=======================================================================
377 //=======================================================================
381 void Interpreter::InterpretLine( const std::string& line, bool &insideComment )
384 bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretLine(\""<<line<<"\")"<<std::endl);
385 bbtkMessage("Echo",2,"\""<<line<<"\""<<std::endl);
387 std::vector<std::string> words;
388 SplitLine(line,words);
393 bbtkDebugDecTab("Interpreter",9);
397 // Single line comment : # or //
398 if ( words[0][0]=='#' || (words[0][0]=='/' && words[0][1]=='/') )
400 bbtkDebugDecTab("Interpreter",9);
401 bbtkMessage("Interpreter",9,"Comment"<<std::endl);
405 // Multi line comment ( /* ... */ ) -delimiters on different lines !-
407 if (words[0][0]=='/' && words[0][1]=='*')
409 bbtkDebugDecTab("Interpreter",9);
410 bbtkMessage("Interpreter",9,"In multiline comment"<<std::endl);
411 insideComment = true;
415 if (words[0][0]=='*' && words[0][1]=='/')
417 bbtkDebugDecTab("Interpreter",9);
418 bbtkMessage("Interpreter",9,"Out multiline comment"<<std::endl);
419 if ( !insideComment ) {
420 bbtkDebugDecTab("Interpreter",9);
421 bbtkMessage("Interpreter",9,"Comment mismatch : '*/' with no matching '/*'"<<std::endl);
423 insideComment = false;
429 bbtkDebugDecTab("Interpreter",9);
430 bbtkMessage("Interpreter",9,"Multiline Comment"<<std::endl);
435 CommandInfoType command;
436 InterpretCommand(words,command);
438 bbtkDebugMessage("Interpreter",9,
439 "Command='"<<command.category
440 <<"' code="<<command.code<<std::endl);
442 std::string left,right,left2,right2;
443 std::string filename;
444 switch (command.code)
447 mExecuter->Create(words[1],words[2]);
452 // mExecuter->Remove(words[1]);
456 Utilities::SplitAroundFirstDot(words[1],left,right);
457 Utilities::SplitAroundFirstDot(words[2],left2,right2);
458 mExecuter->Connect(left,right,left2,right2);
462 mExecuter->BeginPackage(words[1]);
466 mExecuter->EndPackage();
470 if (mFileName.size()>0)
472 filename = mIncludeFileName.back(); //Utilities::get_file_name(mFileName.back());
476 mExecuter->Define(words[1],"",filename);
480 mExecuter->Define(words[1],words[2],filename);
485 mExecuter->EndDefine();
489 Print(words[1]); /// \todo use generate command
493 if (words[1]=="freeze")
494 mExecuter->SetNoExecMode(true);
495 else if (words[1]=="unfreeze")
496 mExecuter->SetNoExecMode(false);
498 mExecuter->Update(words[1]);
502 Utilities::SplitAroundFirstDot(words[2],left,right);
503 mExecuter->DefineInput(words[1],left,right,words[3]);
507 Utilities::SplitAroundFirstDot(words[2],left,right);
508 mExecuter->DefineOutput(words[1],left,right,words[3]);
512 Utilities::SplitAroundFirstDot(words[1],left,right);
513 mExecuter->Set(left,right,words[2]);
517 mExecuter->Author(words[1]);
521 mExecuter->Category(words[1]);
526 Index("tmp_index.html");
527 else if (words.size()==2)
529 else if (words.size()==3)
530 Index(words[1],words[2]);
534 mExecuter->Description(words[1]);
544 bbtk::MessageManager::PrintInfo();
548 sscanf(words[2].c_str(),"%d",&level);
549 bbtk::MessageManager::SetMessageLevel(words[1],level);
562 this->mExecuter->Reset();
568 InterpretFile(words[1]);
572 SwitchToFile(words[1]);
574 // if 'source' was given
577 GetExecuter()->SetCurrentFileName(words[1]);
582 GetExecuter()->GetFactory()->LoadPackage(words[1]);
586 GetExecuter()->GetFactory()->UnLoadPackage(words[1]);
591 throw QuitException();
595 if (words.size() == 2)
597 if (words[1]=="freeze") mExecuter->SetNoExecMode(true);
598 else if (words[1]=="unfreeze") mExecuter->SetNoExecMode(false);
602 mExecuter->SetWorkspaceName(words[2]);
607 bbtkInternalError("should not reach here !!!");
610 bbtkDecTab("Interpreter",9);
612 //=======================================================================
618 //=======================================================================
622 void Interpreter::SplitLine ( const std::string& str, std::vector<std::string>& tokens)
624 bbtkDebugMessageInc("Interpreter",9,"Interpreter::SplitLine(\""<<str<<"\")"<<std::endl);
626 std::string delimiters = "\"";
627 std::vector<std::string> quote;
628 Utilities::SplitString(str,delimiters,quote);
631 std::vector<std::string>::iterator i;
632 for (i=quote.begin(); i!=quote.end(); )
634 Utilities::SplitString(*i,delimiters,tokens);
638 // bbtkDebugMessage("Interpreter",0,"\""<<*i<<"\""<<std::endl);
639 tokens.push_back(*i);
644 for (i=tokens.begin(); i!=tokens.end(); ++i)
646 bbtkDebugMessage("Interpreter",9,"["<<*i<<"] ");
648 bbtkDebugMessageCont("Interpreter",9,std::endl);
650 bbtkDebugDecTab("Interpreter",9);
652 //=======================================================================
655 //=======================================================================
656 // Replaces substrings "\\n" by a real carriage return "\n"
657 void SubsBackslashN ( std::string& s )
659 std::string ss("\\n");
660 std::string::size_type pos = 0;
663 while ( pos != std::string::npos )
665 s.replace(pos,2,cr,1);
666 pos = s.find(ss, pos-1);
669 //=======================================================================
672 //=======================================================================
676 void Interpreter::Print( const std::string& str)
678 if (mExecuter->GetNoExecMode()) return;
680 bbtkDebugMessageInc("Interpreter",9,"Interpreter::Print(\""<<str<<"\")"<<std::endl);
683 // InterpretLine ("load std")
684 // InterpretLine("new ConcatStrings _C_ ") -> trouver un nom unique : # commande
685 // InterpretLine("new Print _P_")
686 // InterpretLine("connect _C_.Out _P_.In")
690 std::vector<std::string> chains;
691 std::string delimiters("$");
693 // Skip delimiters at beginning.
694 std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
696 if (lastPos>0) is_text = false;
698 // Find first delimiter.
699 std::string::size_type pos = str.find_first_of(delimiters, lastPos);
701 while (std::string::npos != pos || std::string::npos != lastPos)
705 // Found a text token, add it to the vector.
706 chains.push_back(str.substr(lastPos, pos - lastPos));
707 // std::string token = str.substr(lastPos, pos - lastPos)
708 // InterpretLine("set _C_.In%num% %token%")
714 // is an output (between $$) : decode
715 std::string tok,box,output;
716 tok = str.substr(lastPos, pos - lastPos);
717 Utilities::SplitAroundFirstDot(tok,box,output);
718 chains.push_back( mExecuter->Get(box,output) );
720 // InterpretLine("connect %tok% _C_.In%num%")
723 // Skip delimiters. Note the "not_of"
724 lastPos = str.find_first_not_of(delimiters, pos);
725 // Find next delimiter
726 pos = str.find_first_of(delimiters, lastPos);
731 // InterpretLine("exec _P_")
732 // if (IS_IN_WORKSPACE) InterpretLine("delete _C_; delete _P_");
734 std::vector<std::string>::iterator i;
735 for (i= chains.begin(); i!=chains.end(); ++i)
737 // bbtkMessage("Echo",1,*i);
741 std::cout << std::endl;
742 bbtkDebugDecTab("Interpreter",9);
745 //=======================================================================
750 // ===================================================================================
752 void Interpreter::SwitchToFile( const std::string& name )
754 // Note : in the following :
755 // name : the user supplied name
756 // - abreviated name e.g. scr scr.bbs
757 // - relative full name e.g. ./scr.bbs ../../scr.bbs
758 // - absolute full name e.g. /home/usrname/proj/dir/scr.bbs
759 // same for Windows, with c:, d: ...
761 // use ./directory/subdir/scrname.bbs
764 bbtkDebugMessageInc("Interpreter",9,"Interpreter::SwitchToFile( \""
765 <<name<<"\")"<<std::endl);
767 std::vector<std::string> script_paths;
768 std::string fullPathScriptName; // full path script name
769 std::string pkgname; // e.g. <scriptname>.bbs
770 std::vector<std::string> Filenames;
772 // The following is *NOT* a debug time message :
773 // It's a user intended message.
774 // Please don't remove it.
775 bbtkMessage("Interpreter",1,
776 "look for : [" << name
777 << "]" << std::endl);
778 script_paths = ConfigurationFile::GetInstance().Get_bbs_paths();
781 pkgname = Utilities::ExtractScriptName(name,upath);
783 bool fullnameGiven = false;
784 bool foundFile = false;
786 if(pkgname == "*") // =========================================== load all boxes (e.g. std/boxes/*)
790 if (upath[0]=='/' || upath[1] == ':' ) // ==== absolute name, load all .bbs files
792 int nbFiles = Utilities::Explore(upath, false, Filenames);
794 for (std::vector<std::string>::iterator i = Filenames.begin(); i!= Filenames.end(); ++i)
796 if ((*i).substr((*i).size()-4, 4) != ".bbs")
797 continue; // ignore non .bbs files
798 std::string command("include ");
800 // LoadScript(*i,name);
802 InterpretLine(command,tmp);
806 bbtkMessage("Interpreter",2,
807 "WARNING : No '.bbs' file found in ["
808 << upath << "]" << std::endl);
813 std::vector<std::string>::iterator i;
814 std::string fullDirectoryName;
815 for (i=script_paths.begin();i!=script_paths.end();i++)// ==== relative name, iterate + load all .bbs files
819 // we *really* want '.' to be the current working directory
821 char buf[2048]; // for getcwd
822 char * currentDir = getcwd(buf, 2048);
823 std::string cwd(currentDir);
827 fullDirectoryName = Utilities::MakePkgnameFromPath(path, upath, false);
830 // without last slash "\"
831 std::string fullDirectoryNameClean = fullDirectoryName.substr(0,fullDirectoryName.size()-1);
833 // Check if library exists
834 if ( ! Utilities::IsDirectory( fullDirectoryNameClean ) )
836 // The following is *NOT* a debug time message :
837 // It's a user intended message.
838 // Please don't remove it.
839 bbtkMessage("Interpreter",1," [" <<fullDirectoryName
840 <<"] : doesn't exist" <<std::endl);
841 continue; // try next path
846 int nbFiles = Utilities::Explore(fullDirectoryName, false, Filenames);
849 for (std::vector<std::string>::iterator i = Filenames.begin(); i!= Filenames.end(); ++i)
851 if ((*i).substr((*i).size()-4, 4) != ".bbs")
852 continue; // ignore non .bbs files
853 std::string command("include ");
856 InterpretLine(command,tmp);
857 // LoadScript(*i,name);
861 bbtkMessage("Interpreter",1,
862 "WARNING : No '.bbs' file found in ["
863 << fullDirectoryName << "]" << std::endl);
865 //break; // a directory was found; we stop iterating
866 // LG : No! We want all files included !
871 //std::string::size_type slash_position = name.find_last_of("/\\");
873 // if name starts with a / or a . or contains : user is assumed to have passed a relative/absolute name
874 // (not only a plain script name)
875 // we trust him, and try to expland the directory name
876 // WARNING : starting from current local directory : ./whatYouWant (./ mandatory!)
878 if (name[0]=='/' || name[1] == ':' || name[0]=='.') // absolute path (linux/windows) or relative path
881 // ===========================================================check user supplied location
882 fullnameGiven = true;
884 fullPathScriptName = Utilities::ExpandLibName(name, false);
886 // allow user to always forget ".bbs"
887 int l = fullPathScriptName.size();
893 if (fullPathScriptName.substr(l-4, 4) != ".bbs")
895 fullPathScriptName = fullPathScriptName + ".bbs";
900 fullPathScriptName = fullPathScriptName + ".bbs";
903 if ( Utilities::FileExists(fullPathScriptName))
911 // =============================================================== iterate on the paths
914 std::vector<std::string>::iterator i;
915 for (i=script_paths.begin();i!=script_paths.end();++i)
919 // we *really* want '.' to be the current working directory
921 char buf[2048]; // for getcwd
922 char * currentDir = getcwd(buf, 2048);
923 std::string cwd(currentDir);
927 // fullPathScriptName = Utilities::MakePkgnameFromPath(path, name, true); //pkgname);
929 fullPathScriptName = Utilities::MakePkgnameFromPath(path, name, true);
932 // Check if library exists
933 if ( ! Utilities::FileExists(fullPathScriptName) )
935 // The following is *NOT* a debug time message :
936 // It's a user intended message.
937 // Please don't remove it.
938 bbtkMessage("Interpreter",2,
939 " [" <<fullPathScriptName <<"] : doesn't exist"
941 continue; // try next path
943 bbtkMessage("Interpreter",2,
944 " [" <<fullPathScriptName
945 <<"] : found" <<std::endl);
947 break; // a script was found; we stop iterating
949 } //------------------ // end for ( package_paths.begin();i!=package_paths.end() )
955 if(fullPathScriptName == "")
956 bbtkError("Path ["<<upath<<"] doesn't exist");
958 bbtkError("Script ["<<fullPathScriptName<<"] not found");
960 bbtkError("No ["<<pkgname<<".bbs] script found");
964 LoadScript(fullPathScriptName,name);
970 //=======================================================================
972 void Interpreter::LoadScript( std::string fullPathScriptName,
973 std::string includeScriptName)
975 if (find(mFileName.begin(),mFileName.end(),fullPathScriptName)
978 bbtkMessage("Interpreter",1,"file '"<<fullPathScriptName
979 <<"' already open : I do not open it once more to prevent recursive inclusion"<<std::endl);
984 s = new std::ifstream;
985 s->open(fullPathScriptName.c_str());
988 bbtkError("Could not open file ["<<fullPathScriptName<<"]");
992 bbtkMessage("Interpreter",1," -->[" << fullPathScriptName
993 << "] found" << std::endl);
996 mFileName.push_back(fullPathScriptName);
997 mIncludeFileName.push_back(includeScriptName);
1002 //=======================================================================
1006 void Interpreter::CloseCurrentFile()
1008 bbtkDebugMessage("Interpreter",9,"Interpreter::CloseCurrentFile()"
1011 if (mFile.size()==0)
1013 bbtkDebugMessage("Interpreter",9," -> no file left open"<<std::endl);
1017 mFile.back()->close();
1018 delete mFile.back();
1020 bbtkDebugMessage("Interpreter",9,
1021 " Closing file '"<<mFileName.back()<<"'"<<std::endl);
1023 mFileName.pop_back();
1024 mIncludeFileName.pop_back();
1026 bbtkDebugMessage("Interpreter",9," Remains "
1028 <<" open"<<std::endl);
1029 bbtkDebugMessage("Interpreter",9,"EO Interpreter::CloseCurrentFile()"
1032 //=======================================================================
1034 //=======================================================================
1038 void Interpreter::CloseAllFiles()
1040 bbtkDebugMessage("Interpreter",9,"Interpreter::CloseAllFiles()"
1043 while (mFile.size() != 0)
1045 mFile.back()->close();
1046 delete mFile.back();
1048 bbtkDebugMessage("Interpreter",9,
1049 " Closing file '"<<mFileName.back()<<"'"<<std::endl);
1050 mFileName.pop_back();
1051 mIncludeFileName.pop_back();
1054 bbtkDebugMessage("Interpreter",9,"EO Interpreter::CloseAllFiles()"
1057 //=======================================================================
1061 //=======================================================================
1065 void Interpreter::InterpretCommand( const std::vector<std::string>& words,
1066 CommandInfoType& info )
1068 bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretCommand(...)"<<std::endl);
1070 // searches the command category
1071 CommandDictType::iterator c;
1072 c = mCommandDict.find(words[0]);
1073 if ( c == mCommandDict.end() ) {
1074 bbtkError(words[0]<<" : unknown command");
1077 // tests the number of args
1078 if ( ( words.size()-1 < c->second.argmin ) ||
1079 ( words.size()-1 > c->second.argmax ) )
1081 HelpCommand(words[0]);
1082 bbtkError(words[0]<<" : wrong number of arguments");
1086 bbtkDecTab("Interpreter",9);
1088 //=======================================================================
1091 //=======================================================================
1092 /// Displays help on all the commands
1093 void Interpreter::Help(const std::vector<std::string>& words)
1095 unsigned int nbarg = words.size()-1;
1103 if (words[1]=="packages")
1105 GetExecuter()->GetFactory()->PrintPackages(true);
1110 HelpCommand(words[1]);
1112 catch (bbtk::Exception e)
1116 GetExecuter()->GetFactory()->HelpPackage(words[1]);
1117 #ifdef _USE_WXWIDGETS_
1118 if ( mWxConsole != 0 )
1121 ConfigurationFile::GetInstance().Get_doc_path();
1122 url += "/bbdoc/" + words[1] + "/index.html";
1123 if (Utilities::FileExists(url))
1125 mWxConsole->ShowHtmlPage(url);
1130 catch (bbtk::Exception f)
1134 std::string package;
1135 GetExecuter()->GetFactory()->HelpBlackBox(words[1],package);
1136 #ifdef _USE_WXWIDGETS_
1137 if ( mWxConsole != 0 )
1140 ConfigurationFile::GetInstance().Get_doc_path();
1141 url += "/bbdoc/" + package + "/index.html";
1142 if (Utilities::FileExists(url))
1144 url += "#" + words[1];
1145 mWxConsole->ShowHtmlPage(url);
1150 catch (bbtk::Exception g)
1154 GetExecuter()->ShowRelations(words[1],"0","9999");
1156 catch (bbtk::Exception h){
1157 bbtkError("\""<<words[1].c_str()
1158 <<"\" is not a known command, package, black box type or black box name");
1166 if (words[2]=="all")
1168 if ( words[1]=="packages" )
1170 GetExecuter()->GetFactory()->PrintPackages(true,true);
1175 GetExecuter()->GetFactory()->HelpPackage(words[1],true);
1177 catch (bbtk::Exception f)
1183 HelpCommand(words[0]);
1184 bbtkError(words[0]<<" : syntax error");
1189 bbtkError("Should not reach here !!!");
1192 //=======================================================================
1194 //===================================================================
1195 /// Displays the Configuration
1196 void Interpreter::Config() const
1198 ConfigurationFile::GetInstance().GetHelp(1);
1200 //===================================================================
1202 //=======================================================================
1203 /// Displays help on all the commands
1204 void Interpreter::HelpCommands()
1206 std::cout << "Available commands :" << std::endl;
1207 CommandDictType::iterator i;
1208 for ( i = mCommandDict.begin();
1209 i != mCommandDict.end();
1211 std::cout << " " << i->first << std::endl;
1212 // std::cout << " usage : " << i->second.syntax << std::endl;
1213 // std::cout << " " << i->second.help << std::endl;
1217 //=======================================================================
1220 //=======================================================================
1221 /// Displays help on a particular commands
1222 void Interpreter::HelpCommand(const std::string& s)
1224 CommandDictType::iterator c;
1225 c = mCommandDict.find(s);
1226 if ( c == mCommandDict.end() ) {
1227 bbtkError(s<<" : Unknown command");
1229 // std::cout << " " << s << " : "<< std::endl;
1230 // CommandParamDictType::iterator i;
1231 // for ( i = c->second.begin();
1232 // i != c->second.end();
1234 std::cout << " usage : " << c->second.syntax << std::endl;
1235 std::cout << " " << c->second.help << std::endl;
1238 //=======================================================================
1241 //=======================================================================
1242 /// Fills the vector commands with the commands which
1243 /// have the first n chars of buf for prefix
1244 /// TODO : skip initial spaces in buf and also return the position of first
1245 /// non blank char in buf
1246 void Interpreter::FindCommandsWithPrefix( char* buf,
1248 std::vector<std::string>& commands )
1250 CommandDictType::const_iterator i;
1251 for (i=mCommandDict.begin(); i!=mCommandDict.end(); ++i)
1253 if ((i->first).find(buf,0,n) == 0)
1254 commands.push_back(i->first);
1257 //=======================================================================
1261 //=======================================================================
1262 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1264 inline void PrintChar(char c) { write(STDOUT_FILENO,&c,1); }
1265 inline void BackSpace() { write(STDOUT_FILENO,"\b \b",3); }
1267 // LG : KEYBOARD CODES AS SCANNED ON MY TTY : UNIVERSAL ?
1268 // IF NOT THE USER SHOULD BE ABLE TO CONFIGURE IT
1269 // E.G. STORE THIS IN bbtk_config.xml
1270 #define BBTK_UP_ARROW_KBCODE 0x00415B1B
1271 #define BBTK_DOWN_ARROW_KBCODE 0x00425B1B
1272 #define BBTK_RIGHT_ARROW_KBCODE 0x00435B1B
1273 #define BBTK_LEFT_ARROW_KBCODE 0x00445B1B
1274 #define BBTK_BACKSPACE_KBCODE 0x00000008
1275 #define BBTK_DEL_KBCODE 0x0000007F
1276 #define BBTK_SPACE_KBCODE 0x00000020
1278 //=======================================================================
1279 void Interpreter::GetLineFromPrompt(std::string& s)
1284 int MAX_LINE_SIZE = 160;
1285 int MAX_HISTORY_SIZE = 100;
1287 char* newline = new char[MAX_LINE_SIZE];
1288 memset(newline,0,MAX_LINE_SIZE);
1289 char* histline = new char[MAX_LINE_SIZE];
1290 memset(histline,0,MAX_LINE_SIZE);
1292 char* line = newline;
1293 int hist = mHistory.size();
1299 read ( STDIN_FILENO, &c, 4) ;
1301 bbtkDebugMessage("Debug",9,"[0x"<<std::hex<<c<<"]\n");
1303 // Printable character
1304 if ( (ind<MAX_LINE_SIZE-1) &&
1305 ( c >= BBTK_SPACE_KBCODE ) &&
1306 ( c < BBTK_DEL_KBCODE ))
1314 // delete the unused line
1320 // empty lines are not stored in from history
1323 // if history too long : delete oldest command
1324 if (mHistory.size()>MAX_HISTORY_SIZE)
1326 delete mHistory.front();
1327 mHistory.pop_front();
1329 mHistory.push_back(line);
1334 else if ( (ind>0) &&
1335 ((c == BBTK_BACKSPACE_KBCODE) ||
1336 (c == BBTK_DEL_KBCODE)) )
1344 // TODO : Command completion
1345 std::vector<std::string> commands;
1346 FindCommandsWithPrefix( line,ind,commands);
1347 if (commands.size()==1)
1349 std::string com = *commands.begin();
1350 for (; ind<com.size(); ++ind)
1352 PrintChar(com[ind]);
1358 else if (commands.size()>1)
1360 std::vector<std::string>::iterator i;
1362 for (i=commands.begin();i!=commands.end();++i)
1364 write(STDOUT_FILENO,(*i).c_str(),strlen((*i).c_str()));
1367 write(STDOUT_FILENO,"\n> ",3);
1368 //for (int j=0;j<ind;++j)
1370 write(STDOUT_FILENO,line,ind);
1374 // Arrow up : back in history
1375 else if (c==BBTK_UP_ARROW_KBCODE)
1379 // erase current line
1380 while (ind--) BackSpace();
1384 strcpy(histline,mHistory[hist]);
1388 write(STDOUT_FILENO,line,ind);
1391 // Arrow down : down in history
1392 else if (c==BBTK_DOWN_ARROW_KBCODE)
1394 if (hist<mHistory.size()-1)
1396 // erase current line
1397 while (ind--) BackSpace();
1401 strcpy(histline,mHistory[hist]);
1405 write(STDOUT_FILENO,line,ind);
1407 // end of history : switch back to newline
1408 else if (hist==mHistory.size()-1)
1410 // erase current line
1411 while (ind--) BackSpace();
1418 write(STDOUT_FILENO,line,ind);
1422 else if (line[ind]!=0 && c==BBTK_RIGHT_ARROW_KBCODE)
1424 PrintChar(line[ind]);
1429 else if (ind>0 && c==BBTK_LEFT_ARROW_KBCODE)
1437 write(STDOUT_FILENO,"\n\r",2);
1445 //=======================================================================
1446 void Interpreter::GetLineFromPrompt(std::string& s)
1472 //=======================================================================
1478 //=======================================================================
1479 void Interpreter::CommandLineInterpreter()
1481 bbtkDebugMessageInc("Interpreter",9,
1482 "Interpreter::CommandLineInterpreter()"<<std::endl);
1484 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1485 // Initialise the tty in non canonical mode with no echo
1486 // oter remembers the previous settings to restore them after
1487 struct termios ter,oter;
1490 ter.c_lflag &= ~ECHO;
1491 ter.c_lflag &= ~ICANON;
1494 tcsetattr(0,TCSANOW,&ter);
1497 mCommandLine = true;
1499 bool insideComment = false; // for multiline comment
1505 GetLineFromPrompt(line);
1506 InterpretLine(line, insideComment);
1508 catch (QuitException e)
1512 catch (bbtk::Exception e)
1516 catch (std::exception& e)
1518 std::cerr << "* ERROR :: "<<e.what()<<" (not in bbtk)"<<std::endl;
1522 std::cerr << "* UNDEFINED ERROR (not a bbtk nor a std exception)"<<std::endl;
1527 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1528 tcsetattr(0,TCSANOW,&oter);
1531 std::cout << "Good bye !" << std::endl;
1533 bbtkDebugDecTab("Interpreter",9);
1536 //=======================================================================
1537 void Interpreter::Graph(const std::vector<std::string>& words)
1540 bool system_display = true;
1542 #ifdef _USE_WXWIDGETS_
1543 if ( mWxConsole != 0 ) system_display = false;
1546 if (words.size()==1)
1548 page = mExecuter->ShowGraph(".","0","0","","","",system_display);
1550 else if (words.size()==2)
1552 page = mExecuter->ShowGraph(words[1],"0","0","","","",system_display);
1554 else if (words.size()==3)
1556 page = mExecuter->ShowGraph(words[1],words[2],"0","","","",system_display);
1558 else if (words.size()==4)
1560 page = mExecuter->ShowGraph(words[1],words[2],words[3],"","","",system_display);
1562 else if (words.size()==5)
1564 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],"","",system_display);
1566 else if (words.size()==6)
1568 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],"",system_display);
1570 else if (words.size()==7)
1572 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],words[6],system_display);
1575 #ifdef _USE_WXWIDGETS_
1576 if ( mWxConsole != 0 )
1577 mWxConsole->ShowHtmlPage(page);
1580 //=======================================================================
1583 //=======================================================================
1584 void Interpreter::Index(const std::string& filename,
1585 const std::string& type)
1587 Factory::IndexEntryType t;
1588 if (type=="Initials") t = Factory::Initials;
1589 else if (type=="Categories") t = Factory::Categories;
1590 else if (type=="Packages") t = Factory::Packages;
1591 else if (type=="Adaptors") t = Factory::Adaptors;
1593 GetExecuter()->GetFactory()->CreateHtmlIndex(t,filename);
1595 //=======================================================================