1 /*=========================================================================
4 Module: $RCSfile: bbtkInterpreter.cxx,v $ $
6 Date: $Date: 2008/02/18 10:41:02 $
7 Version: $Revision: 1.33 $
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;
314 printf("EED: Interpreter::InterpretFile 01\n");
315 InterpretLine("message ALL 9", exm);
316 SwitchToFile(filename, use_configuration_file);
317 bool insideComment = false; // for multiline comment
318 while (mFile.size()>0)
320 while ((mFile.size()>0) &&
321 (!mFile.back()->eof()))
325 mFile.back()->getline(buf,500);
327 std::string str(buf);
328 int size=str.length();
329 if ( str[ size-1 ]==13 )
334 InterpretLine(str, insideComment);
336 //if (mFile.size()>0)
340 catch (QuitException e)
343 catch (bbtk::Exception e)
345 std::cerr << "* ERROR : "<<e.GetMessage()<<std::endl;
346 if (mFileName.size()) {
347 std::cerr << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
348 std::cerr << "* LINE : "<<mLine.back()<<std::endl;
351 catch (std::exception& e)
353 std::cerr << "* ERROR : "<<e.what()<<" (not in bbtk)"<<std::endl;
354 if (mFileName.size()) {
355 std::cerr << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
356 std::cerr << "* LINE : "<<mLine.back()<<std::endl;
361 std::cout << "* UNDEFINED ERROR (not a bbtk nor a std exception)"<<std::endl;
362 if (mFileName.size()) {
363 std::cout << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
364 std::cout << "* LINE : "<<mLine.back()<<std::endl;
369 bbtkDebugMessage("Interpreter",9,"EO Interpreter::InterpretFile(\""<<filename<<"\")"<<std::endl);
370 bbtkDecTab("Interpreter",9);
373 printf("EED: Interpreter::InterpretFile 02\n");
375 //=======================================================================
379 //=======================================================================
383 void Interpreter::InterpretLine( const std::string& line, bool &insideComment )
386 bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretLine(\""<<line<<"\")"<<std::endl);
387 bbtkMessage("Echo",2,"\""<<line<<"\""<<std::endl);
389 std::vector<std::string> words;
390 SplitLine(line,words);
395 bbtkDebugDecTab("Interpreter",9);
399 // Single line comment : # or //
400 if ( words[0][0]=='#' || (words[0][0]=='/' && words[0][1]=='/') )
402 bbtkDebugDecTab("Interpreter",9);
403 bbtkMessage("Interpreter",9,"Comment"<<std::endl);
407 // Multi line comment ( /* ... */ ) -delimiters on different lines !-
409 if (words[0][0]=='/' && words[0][1]=='*')
411 bbtkDebugDecTab("Interpreter",9);
412 bbtkMessage("Interpreter",9,"In multiline comment"<<std::endl);
413 insideComment = true;
417 if (words[0][0]=='*' && words[0][1]=='/')
419 bbtkDebugDecTab("Interpreter",9);
420 bbtkMessage("Interpreter",9,"Out multiline comment"<<std::endl);
421 if ( !insideComment ) {
422 bbtkDebugDecTab("Interpreter",9);
423 bbtkMessage("Interpreter",9,"Comment mismatch : '*/' with no matching '/*'"<<std::endl);
425 insideComment = false;
431 bbtkDebugDecTab("Interpreter",9);
432 bbtkMessage("Interpreter",9,"Multiline Comment"<<std::endl);
437 CommandInfoType command;
438 InterpretCommand(words,command);
440 bbtkDebugMessage("Interpreter",9,
441 "Command='"<<command.category
442 <<"' code="<<command.code<<std::endl);
444 std::string left,right,left2,right2;
445 std::string filename;
446 switch (command.code)
449 mExecuter->Create(words[1],words[2]);
454 // mExecuter->Remove(words[1]);
458 Utilities::SplitAroundFirstDot(words[1],left,right);
459 Utilities::SplitAroundFirstDot(words[2],left2,right2);
460 mExecuter->Connect(left,right,left2,right2);
464 mExecuter->BeginPackage(words[1]);
468 mExecuter->EndPackage();
472 if (mFileName.size()>0)
474 filename = mIncludeFileName.back(); //Utilities::get_file_name(mFileName.back());
478 mExecuter->Define(words[1],"",filename);
482 mExecuter->Define(words[1],words[2],filename);
487 mExecuter->EndDefine();
491 Print(words[1]); /// \todo use mExecuter
495 if (words[1]=="freeze")
496 mExecuter->SetNoExecMode(true);
497 else if (words[1]=="unfreeze")
498 mExecuter->SetNoExecMode(false);
500 mExecuter->Update(words[1]);
504 Utilities::SplitAroundFirstDot(words[2],left,right);
505 mExecuter->DefineInput(words[1],left,right,words[3]);
509 Utilities::SplitAroundFirstDot(words[2],left,right);
510 mExecuter->DefineOutput(words[1],left,right,words[3]);
514 Utilities::SplitAroundFirstDot(words[1],left,right);
515 mExecuter->Set(left,right,words[2]);
519 mExecuter->Author(words[1]);
523 mExecuter->Category(words[1]);
528 Index("tmp_index.html");
529 else if (words.size()==2)
531 else if (words.size()==3)
532 Index(words[1],words[2]);
536 mExecuter->Description(words[1]);
546 bbtk::MessageManager::PrintInfo();
550 sscanf(words[2].c_str(),"%d",&level);
551 bbtk::MessageManager::SetMessageLevel(words[1],level);
564 this->mExecuter->Reset();
570 InterpretFile(words[1], true ); // true : better pass use_config_file
574 SwitchToFile(words[1], true ); // true : better pass use_config_file
576 // if 'source' was given
579 this->mExecuter->SetCurrentFileName(words[1]);
584 LoadPackage(words[1], true ); // true : better pass use_config_file
588 UnLoadPackage(words[1]);
593 throw QuitException();
597 if (words.size() == 2)
599 if (words[1]=="freeze") mExecuter->SetNoExecMode(true);
600 else if (words[1]=="unfreeze") mExecuter->SetNoExecMode(false);
604 mExecuter->SetWorkspaceName(words[2]);
609 bbtkInternalError("should not reach here !!!");
612 bbtkDecTab("Interpreter",9);
614 //=======================================================================
620 //=======================================================================
624 void Interpreter::SplitLine ( const std::string& str, std::vector<std::string>& tokens)
626 bbtkDebugMessageInc("Interpreter",9,"Interpreter::SplitLine(\""<<str<<"\")"<<std::endl);
628 std::string delimiters = "\"";
629 std::vector<std::string> quote;
630 Utilities::SplitString(str,delimiters,quote);
633 std::vector<std::string>::iterator i;
634 for (i=quote.begin(); i!=quote.end(); )
636 Utilities::SplitString(*i,delimiters,tokens);
640 // bbtkDebugMessage("Interpreter",0,"\""<<*i<<"\""<<std::endl);
641 tokens.push_back(*i);
646 for (i=tokens.begin(); i!=tokens.end(); ++i)
648 bbtkDebugMessage("Interpreter",9,"["<<*i<<"] ");
650 bbtkDebugMessageCont("Interpreter",9,std::endl);
652 bbtkDebugDecTab("Interpreter",9);
654 //=======================================================================
657 //=======================================================================
658 // Replaces substrings "\\n" by a real carriage return "\n"
659 void SubsBackslashN ( std::string& s )
661 std::string ss("\\n");
662 std::string::size_type pos = 0;
665 while ( pos != std::string::npos )
667 s.replace(pos,2,cr,1);
668 pos = s.find(ss, pos-1);
671 //=======================================================================
674 //=======================================================================
678 void Interpreter::Print( const std::string& str)
680 if (mExecuter->GetNoExecMode()) return;
682 bbtkDebugMessageInc("Interpreter",9,"Interpreter::SplitLine(\""<<str<<"\")"<<std::endl);
684 std::vector<std::string> chains;
685 std::string delimiters("$");
687 // Skip delimiters at beginning.
688 std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
690 if (lastPos>0) is_text = false;
692 // Find first delimiter.
693 std::string::size_type pos = str.find_first_of(delimiters, lastPos);
695 while (std::string::npos != pos || std::string::npos != lastPos)
699 // Found a text token, add it to the vector.
700 chains.push_back(str.substr(lastPos, pos - lastPos));
704 // is an output (between $$) : decode
705 std::string tok,box,output;
706 tok = str.substr(lastPos, pos - lastPos);
707 Utilities::SplitAroundFirstDot(tok,box,output);
708 chains.push_back( mExecuter->Get(box,output) );
710 // Skip delimiters. Note the "not_of"
711 lastPos = str.find_first_not_of(delimiters, pos);
712 // Find next delimiter
713 pos = str.find_first_of(delimiters, lastPos);
717 std::vector<std::string>::iterator i;
718 for (i= chains.begin(); i!=chains.end(); ++i)
720 // bbtkMessage("Echo",1,*i);
724 std::cout << std::endl;
725 bbtkDebugDecTab("Interpreter",9);
728 //=======================================================================
733 // ===================================================================================
735 void Interpreter::SwitchToFile( const std::string& name,
736 bool use_configuration_file )
738 // Note : in the following :
739 // name : the user supplied name
740 // - abreviated name e.g. scr scr.bbs
741 // - relative full name e.g. ./scr.bbs ../../scr.bbs
742 // - absolute full name e.g. /home/usrname/proj/dir/scr.bbs
743 // same for Windows, with c:, d: ...
745 // use ./directory/subdir/scrname.bbs
748 bbtkDebugMessageInc("Interpreter",9,"Interpreter::SwitchToFile( \""
749 <<name<<"\")"<<std::endl);
751 std::vector<std::string> script_paths;
752 std::string fullPathScriptName; // full path script name
753 std::string pkgname; // e.g. <scriptname>.bbs
754 std::vector<std::string> Filenames;
756 if (use_configuration_file)
758 // The following is *NOT* a debug time message :
759 // It's a user intended message.
760 // Please don't remove it.
761 bbtkMessage("Interpreter",1,
762 "look for : [" << name
763 << "] (use_configuration_file == TRUE)" << std::endl);
764 script_paths = ConfigurationFile::GetInstance().Get_bbs_paths();
767 pkgname = Utilities::ExtractScriptName(name,upath);
769 bool fullnameGiven = false;
770 bool foundFile = false;
772 if(pkgname == "*") // =========================================== load all boxes (e.g. std/boxes/*)
776 if (upath[0]=='/' || upath[1] == ':' ) // ==== absolute name, load all .bbs files
778 int nbFiles = Utilities::Explore(upath, false, Filenames);
780 for (std::vector<std::string>::iterator i = Filenames.begin(); i!= Filenames.end(); ++i)
782 if ((*i).substr((*i).size()-4, 4) != ".bbs")
783 continue; // ignore non .bbs files
788 bbtkMessage("Interpreter",2,
789 "WARNING : No '.bbs' file found in ["
790 << upath << "]" << std::endl);
795 std::vector<std::string>::iterator i;
796 std::string fullDirectoryName;
797 for (i=script_paths.begin();i!=script_paths.end();i++)// ==== relative name, iterate + load all .bbs files
801 // we *really* want '.' to be the current working directory
803 char buf[2048]; // for getcwd
804 char * currentDir = getcwd(buf, 2048);
805 std::string cwd(currentDir);
809 fullDirectoryName = Utilities::MakePkgnameFromPath(path, upath, false);
812 // without last slash "\"
813 std::string fullDirectoryNameClean = fullDirectoryName.substr(0,fullDirectoryName.size()-1);
815 // Check if library exists
816 if ( ! Utilities::IsDirectory( fullDirectoryNameClean ) )
818 // The following is *NOT* a debug time message :
819 // It's a user intended message.
820 // Please don't remove it.
821 bbtkMessage("Interpreter",1," [" <<fullDirectoryName
822 <<"] : doesn't exist" <<std::endl);
823 continue; // try next path
828 int nbFiles = Utilities::Explore(fullDirectoryName, false, Filenames);
831 for (std::vector<std::string>::iterator i = Filenames.begin(); i!= Filenames.end(); ++i)
833 if ((*i).substr((*i).size()-4, 4) != ".bbs")
834 continue; // ignore non .bbs files
839 bbtkMessage("Interpreter",1,
840 "WARNING : No '.bbs' file found in ["
841 << fullDirectoryName << "]" << std::endl);
843 //break; // a directory was found; we stop iterating
844 // LG : No! We want all files included !
849 //std::string::size_type slash_position = name.find_last_of("/\\");
851 // if name starts with a / or a . or contains : user is assumed to have passed a relative/absolute name
852 // (not only a plain script name)
853 // we trust him, and try to expland the directory name
854 // WARNING : starting from current local directory : ./whatYouWant (./ mandatory!)
856 if (name[0]=='/' || name[1] == ':' || name[0]=='.') // absolute path (linux/windows) or relative path
859 // ===========================================================check user supplied location
860 fullnameGiven = true;
862 fullPathScriptName = Utilities::ExpandLibName(name, false);
864 // allow user to always forget ".bbs"
865 int l = fullPathScriptName.size();
871 if (fullPathScriptName.substr(l-4, 4) != ".bbs")
873 fullPathScriptName = fullPathScriptName + ".bbs";
878 fullPathScriptName = fullPathScriptName + ".bbs";
881 if ( Utilities::FileExists(fullPathScriptName))
889 // =============================================================== iterate on the paths
892 std::vector<std::string>::iterator i;
893 for (i=script_paths.begin();i!=script_paths.end();++i)
897 // we *really* want '.' to be the current working directory
899 char buf[2048]; // for getcwd
900 char * currentDir = getcwd(buf, 2048);
901 std::string cwd(currentDir);
905 // fullPathScriptName = Utilities::MakePkgnameFromPath(path, name, true); //pkgname);
907 fullPathScriptName = Utilities::MakePkgnameFromPath(path, name, true);
910 // Check if library exists
911 if ( ! Utilities::FileExists(fullPathScriptName) )
913 // The following is *NOT* a debug time message :
914 // It's a user intended message.
915 // Please don't remove it.
916 bbtkMessage("Interpreter",2,
917 " [" <<fullPathScriptName <<"] : doesn't exist"
919 continue; // try next path
921 bbtkMessage("Interpreter",2,
922 " [" <<fullPathScriptName
923 <<"] : found" <<std::endl);
925 break; // a script was found; we stop iterating
927 } //------------------ // end for ( package_paths.begin();i!=package_paths.end() )
933 if(fullPathScriptName == "")
934 bbtkError("Path ["<<upath<<"] doesn't exist");
936 bbtkError("Script ["<<fullPathScriptName<<"] not found");
938 bbtkError("No ["<<pkgname<<".bbs] script found");
942 LoadScript(fullPathScriptName,name);
948 //=======================================================================
950 void Interpreter::LoadScript( std::string fullPathScriptName,
951 std::string includeScriptName)
953 if (find(mFileName.begin(),mFileName.end(),fullPathScriptName)
956 bbtkMessage("Interpreter",1,"file '"<<fullPathScriptName
957 <<"' already open : I do not open it once more to prevent recursive inclusion"<<std::endl);
962 s = new std::ifstream;
963 s->open(fullPathScriptName.c_str());
966 bbtkError("Could not open file ["<<fullPathScriptName<<"]");
970 bbtkMessage("Interpreter",1," -->[" << fullPathScriptName
971 << "] found" << std::endl);
974 mFileName.push_back(fullPathScriptName);
975 mIncludeFileName.push_back(includeScriptName);
980 //=======================================================================
984 void Interpreter::CloseCurrentFile()
986 bbtkDebugMessage("Interpreter",9,"Interpreter::CloseCurrentFile()"
991 bbtkDebugMessage("Interpreter",9," -> no file left open"<<std::endl);
995 mFile.back()->close();
998 bbtkDebugMessage("Interpreter",9,
999 " Closing file '"<<mFileName.back()<<"'"<<std::endl);
1001 mFileName.pop_back();
1002 mIncludeFileName.pop_back();
1004 bbtkDebugMessage("Interpreter",9," Remains "
1006 <<" open"<<std::endl);
1007 bbtkDebugMessage("Interpreter",9,"EO Interpreter::CloseCurrentFile()"
1010 //=======================================================================
1012 //=======================================================================
1016 void Interpreter::CloseAllFiles()
1018 bbtkDebugMessage("Interpreter",9,"Interpreter::CloseAllFiles()"
1021 while (mFile.size() != 0)
1023 mFile.back()->close();
1024 delete mFile.back();
1026 bbtkDebugMessage("Interpreter",9,
1027 " Closing file '"<<mFileName.back()<<"'"<<std::endl);
1028 mFileName.pop_back();
1029 mIncludeFileName.pop_back();
1032 bbtkDebugMessage("Interpreter",9,"EO Interpreter::CloseAllFiles()"
1035 //=======================================================================
1039 //=======================================================================
1043 void Interpreter::InterpretCommand( const std::vector<std::string>& words,
1044 CommandInfoType& info )
1046 bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretCommand(...)"<<std::endl);
1048 // searches the command category
1049 CommandDictType::iterator c;
1050 c = mCommandDict.find(words[0]);
1051 if ( c == mCommandDict.end() ) {
1052 bbtkError(words[0]<<" : unknown command");
1055 // tests the number of args
1056 if ( ( words.size()-1 < c->second.argmin ) ||
1057 ( words.size()-1 > c->second.argmax ) )
1059 HelpCommand(words[0]);
1060 bbtkError(words[0]<<" : wrong number of arguments");
1064 bbtkDecTab("Interpreter",9);
1066 //=======================================================================
1069 //=======================================================================
1070 /// Displays help on all the commands
1071 void Interpreter::Help(const std::vector<std::string>& words)
1073 unsigned int nbarg = words.size()-1;
1081 if (words[1]=="packages")
1083 PrintPackages(true);
1088 HelpCommand(words[1]);
1090 catch (bbtk::Exception e)
1094 HelpPackage(words[1]);
1095 #ifdef _USE_WXWIDGETS_
1096 if ( WxConsole::GetInstance() != 0 )
1099 ConfigurationFile::GetInstance().Get_doc_path();
1100 url += "/bbdoc/" + words[1] + "/index.html";
1101 if (Utilities::FileExists(url))
1103 WxConsole::GetInstance()->ShowHtmlPage(url);
1108 catch (bbtk::Exception f)
1112 std::string package;
1113 HelpBlackBox(words[1],package);
1114 #ifdef _USE_WXWIDGETS_
1115 if ( WxConsole::GetInstance() != 0 )
1118 ConfigurationFile::GetInstance().Get_doc_path();
1119 url += "/bbdoc/" + package + "/index.html";
1120 if (Utilities::FileExists(url))
1122 url += "#" + words[1];
1123 WxConsole::GetInstance()->ShowHtmlPage(url);
1128 catch (bbtk::Exception g)
1132 this->mExecuter->ShowRelations(words[1],"0","9999");
1134 catch (bbtk::Exception h){
1135 bbtkError("\""<<words[1].c_str()
1136 <<"\" is not a known command, package, black box type or black box name");
1144 if (words[2]=="all")
1146 if ( words[1]=="packages" )
1148 PrintPackages(true,true);
1153 HelpPackage(words[1],true);
1155 catch (bbtk::Exception f)
1161 HelpCommand(words[0]);
1162 bbtkError(words[0]<<" : syntax error");
1167 bbtkError("Should not reach here !!!");
1170 //=======================================================================
1172 //===================================================================
1173 /// Displays the Configuration
1174 void Interpreter::Config() const
1176 ConfigurationFile::GetInstance().GetHelp(1);
1178 //===================================================================
1180 //=======================================================================
1181 /// Displays help on all the commands
1182 void Interpreter::HelpCommands()
1184 std::cout << "Available commands :" << std::endl;
1185 CommandDictType::iterator i;
1186 for ( i = mCommandDict.begin();
1187 i != mCommandDict.end();
1189 std::cout << " " << i->first << std::endl;
1190 // std::cout << " usage : " << i->second.syntax << std::endl;
1191 // std::cout << " " << i->second.help << std::endl;
1195 //=======================================================================
1198 //=======================================================================
1199 /// Displays help on a particular commands
1200 void Interpreter::HelpCommand(const std::string& s)
1202 CommandDictType::iterator c;
1203 c = mCommandDict.find(s);
1204 if ( c == mCommandDict.end() ) {
1205 bbtkError(s<<" : Unknown command");
1207 // std::cout << " " << s << " : "<< std::endl;
1208 // CommandParamDictType::iterator i;
1209 // for ( i = c->second.begin();
1210 // i != c->second.end();
1212 std::cout << " usage : " << c->second.syntax << std::endl;
1213 std::cout << " " << c->second.help << std::endl;
1216 //=======================================================================
1219 //=======================================================================
1220 /// Fills the vector commands with the commands which
1221 /// have the first n chars of buf for prefix
1222 /// TODO : skip initial spaces in buf and also return the position of first
1223 /// non blank char in buf
1224 void Interpreter::FindCommandsWithPrefix( char* buf,
1226 std::vector<std::string>& commands )
1228 CommandDictType::const_iterator i;
1229 for (i=mCommandDict.begin(); i!=mCommandDict.end(); ++i)
1231 if ((i->first).find(buf,0,n) == 0)
1232 commands.push_back(i->first);
1235 //=======================================================================
1239 //=======================================================================
1240 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1242 inline void PrintChar(char c) { write(STDOUT_FILENO,&c,1); }
1243 inline void BackSpace() { write(STDOUT_FILENO,"\b \b",3); }
1245 // LG : KEYBOARD CODES AS SCANNED ON MY TTY : UNIVERSAL ?
1246 // IF NOT THE USER SHOULD BE ABLE TO CONFIGURE IT
1247 // E.G. STORE THIS IN bbtk_config.xml
1248 #define BBTK_UP_ARROW_KBCODE 0x00415B1B
1249 #define BBTK_DOWN_ARROW_KBCODE 0x00425B1B
1250 #define BBTK_RIGHT_ARROW_KBCODE 0x00435B1B
1251 #define BBTK_LEFT_ARROW_KBCODE 0x00445B1B
1252 #define BBTK_BACKSPACE_KBCODE 0x00000008
1253 #define BBTK_DEL_KBCODE 0x0000007F
1254 #define BBTK_SPACE_KBCODE 0x00000020
1256 //=======================================================================
1257 void Interpreter::GetLineFromPrompt(std::string& s)
1262 int MAX_LINE_SIZE = 160;
1263 int MAX_HISTORY_SIZE = 100;
1265 char* newline = new char[MAX_LINE_SIZE];
1266 memset(newline,0,MAX_LINE_SIZE);
1267 char* histline = new char[MAX_LINE_SIZE];
1268 memset(histline,0,MAX_LINE_SIZE);
1270 char* line = newline;
1271 int hist = mHistory.size();
1277 read ( STDIN_FILENO, &c, 4) ;
1279 bbtkDebugMessage("Debug",9,"[0x"<<std::hex<<c<<"]\n");
1281 // Printable character
1282 if ( (ind<MAX_LINE_SIZE-1) &&
1283 ( c >= BBTK_SPACE_KBCODE ) &&
1284 ( c < BBTK_DEL_KBCODE ))
1292 // delete the unused line
1298 // empty lines are not stored in from history
1301 // if history too long : delete oldest command
1302 if (mHistory.size()>MAX_HISTORY_SIZE)
1304 delete mHistory.front();
1305 mHistory.pop_front();
1307 mHistory.push_back(line);
1312 else if ( (ind>0) &&
1313 ((c == BBTK_BACKSPACE_KBCODE) ||
1314 (c == BBTK_DEL_KBCODE)) )
1322 // TODO : Command completion
1323 std::vector<std::string> commands;
1324 FindCommandsWithPrefix( line,ind,commands);
1325 if (commands.size()==1)
1327 std::string com = *commands.begin();
1328 for (; ind<com.size(); ++ind)
1330 PrintChar(com[ind]);
1336 else if (commands.size()>1)
1338 std::vector<std::string>::iterator i;
1340 for (i=commands.begin();i!=commands.end();++i)
1342 write(STDOUT_FILENO,(*i).c_str(),strlen((*i).c_str()));
1345 write(STDOUT_FILENO,"\n> ",3);
1346 //for (int j=0;j<ind;++j)
1348 write(STDOUT_FILENO,line,ind);
1352 // Arrow up : back in history
1353 else if (c==BBTK_UP_ARROW_KBCODE)
1357 // erase current line
1358 while (ind--) BackSpace();
1362 strcpy(histline,mHistory[hist]);
1366 write(STDOUT_FILENO,line,ind);
1369 // Arrow down : down in history
1370 else if (c==BBTK_DOWN_ARROW_KBCODE)
1372 if (hist<mHistory.size()-1)
1374 // erase current line
1375 while (ind--) BackSpace();
1379 strcpy(histline,mHistory[hist]);
1383 write(STDOUT_FILENO,line,ind);
1385 // end of history : switch back to newline
1386 else if (hist==mHistory.size()-1)
1388 // erase current line
1389 while (ind--) BackSpace();
1396 write(STDOUT_FILENO,line,ind);
1400 else if (line[ind]!=0 && c==BBTK_RIGHT_ARROW_KBCODE)
1402 PrintChar(line[ind]);
1407 else if (ind>0 && c==BBTK_LEFT_ARROW_KBCODE)
1415 write(STDOUT_FILENO,"\n\r",2);
1423 //=======================================================================
1424 void Interpreter::GetLineFromPrompt(std::string& s)
1450 //=======================================================================
1456 //=======================================================================
1457 void Interpreter::CommandLineInterpreter()
1459 bbtkDebugMessageInc("Interpreter",9,
1460 "Interpreter::CommandLineInterpreter()"<<std::endl);
1462 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1463 // Initialise the tty in non canonical mode with no echo
1464 // oter remembers the previous settings to restore them after
1465 struct termios ter,oter;
1468 ter.c_lflag &= ~ECHO;
1469 ter.c_lflag &= ~ICANON;
1472 tcsetattr(0,TCSANOW,&ter);
1475 mCommandLine = true;
1477 bool insideComment = false; // for multiline comment
1483 GetLineFromPrompt(line);
1484 InterpretLine(line, insideComment);
1486 catch (QuitException e)
1490 catch (bbtk::Exception e)
1494 catch (std::exception& e)
1496 std::cerr << "* ERROR :: "<<e.what()<<" (not in bbtk)"<<std::endl;
1500 std::cerr << "* UNDEFINED ERROR (not a bbtk nor a std exception)"<<std::endl;
1505 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1506 tcsetattr(0,TCSANOW,&oter);
1509 std::cout << "Good bye !" << std::endl;
1511 bbtkDebugDecTab("Interpreter",9);
1514 //=======================================================================
1515 void Interpreter::Graph(const std::vector<std::string>& words)
1518 bool system_display = true;
1520 #ifdef _USE_WXWIDGETS_
1521 if ( WxConsole::GetInstance() != 0 ) system_display = false;
1524 if (words.size()==1)
1526 page = mExecuter->ShowGraph(".","0","0","","","",system_display);
1528 else if (words.size()==2)
1530 page = mExecuter->ShowGraph(words[1],"0","0","","","",system_display);
1532 else if (words.size()==3)
1534 page = mExecuter->ShowGraph(words[1],words[2],"0","","","",system_display);
1536 else if (words.size()==4)
1538 page = mExecuter->ShowGraph(words[1],words[2],words[3],"","","",system_display);
1540 else if (words.size()==5)
1542 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],"","",system_display);
1544 else if (words.size()==6)
1546 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],"",system_display);
1548 else if (words.size()==7)
1550 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],words[6],system_display);
1553 #ifdef _USE_WXWIDGETS_
1554 if ( WxConsole::GetInstance() != 0 )
1555 WxConsole::GetInstance()->ShowHtmlPage(page);
1558 //=======================================================================
1561 //=======================================================================
1562 void Interpreter::Index(const std::string& filename,
1563 const std::string& type)
1565 Factory::IndexEntryType t;
1566 if (type=="Initials") t = Factory::Initials;
1567 else if (type=="Categories") t = Factory::Categories;
1568 else if (type=="Packages") t = Factory::Packages;
1570 GetGlobalFactory()->CreateHtmlIndex(t,filename);
1572 //=======================================================================