1 /*=========================================================================
4 Module: $RCSfile: bbtkInterpreter.cxx,v $ $
6 Date: $Date: 2008/03/10 06:24:13 $
7 Version: $Revision: 1.42 $
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);
317 printf("EED Interpreter::InterpretFile 0001\n" );
318 int ii,ssize = mFileName.size();
319 for (ii=0;ii<ssize;ii++)
321 printf("EED RRR Interpreter::InterpretFile %s\n", mFileName[ii].c_str() );
324 bool insideComment = false; // for multiline comment
325 while (mFile.size()>0)
327 printf("EED --- %s --- Interpreter::InterpretFile \n", mFileName[0].c_str() );
328 while ((mFile.size()>0) &&
329 (!mFile.back()->eof()))
330 //EED3 (!mFile[0]->eof()))
334 mFile.back()->getline(buf,500);
335 //EED3 mFile[0]->getline(buf,500);
337 std::string str(buf);
338 int size=str.length();
339 if ( str[ size-1 ]==13 )
344 InterpretLine(str, insideComment);
345 printf("EED Interpreter::InterpretFile %s\n", str.c_str() );
347 //if (mFile.size()>0)
351 catch (QuitException e)
354 catch (bbtk::Exception e)
356 std::cerr << "* ERROR : "<<e.GetMessage()<<std::endl;
357 if (mFileName.size()) {
358 std::cerr << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
359 std::cerr << "* LINE : "<<mLine.back()<<std::endl;
362 catch (std::exception& e)
364 std::cerr << "* ERROR : "<<e.what()<<" (not in bbtk)"<<std::endl;
365 if (mFileName.size()) {
366 std::cerr << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
367 std::cerr << "* LINE : "<<mLine.back()<<std::endl;
372 std::cout << "* UNDEFINED ERROR (not a bbtk nor a std exception)"<<std::endl;
373 if (mFileName.size()) {
374 std::cout << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
375 std::cout << "* LINE : "<<mLine.back()<<std::endl;
380 bbtkDebugMessage("Interpreter",9,"EO Interpreter::InterpretFile(\""<<filename<<"\")"<<std::endl);
381 bbtkDecTab("Interpreter",9);
385 //=======================================================================
389 //=======================================================================
393 void Interpreter::InterpretLine( const std::string& line, bool &insideComment )
396 bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretLine(\""<<line<<"\")"<<std::endl);
397 bbtkMessage("Echo",2,"\""<<line<<"\""<<std::endl);
399 std::vector<std::string> words;
400 SplitLine(line,words);
405 bbtkDebugDecTab("Interpreter",9);
409 // Single line comment : # or //
410 if ( words[0][0]=='#' || (words[0][0]=='/' && words[0][1]=='/') )
412 bbtkDebugDecTab("Interpreter",9);
413 bbtkMessage("Interpreter",9,"Comment"<<std::endl);
417 // Multi line comment ( /* ... */ ) -delimiters on different lines !-
419 if (words[0][0]=='/' && words[0][1]=='*')
421 bbtkDebugDecTab("Interpreter",9);
422 bbtkMessage("Interpreter",9,"In multiline comment"<<std::endl);
423 insideComment = true;
427 if (words[0][0]=='*' && words[0][1]=='/')
429 bbtkDebugDecTab("Interpreter",9);
430 bbtkMessage("Interpreter",9,"Out multiline comment"<<std::endl);
431 if ( !insideComment ) {
432 bbtkDebugDecTab("Interpreter",9);
433 bbtkMessage("Interpreter",9,"Comment mismatch : '*/' with no matching '/*'"<<std::endl);
435 insideComment = false;
441 bbtkDebugDecTab("Interpreter",9);
442 bbtkMessage("Interpreter",9,"Multiline Comment"<<std::endl);
447 CommandInfoType command;
448 InterpretCommand(words,command);
450 bbtkDebugMessage("Interpreter",9,
451 "Command='"<<command.category
452 <<"' code="<<command.code<<std::endl);
454 std::string left,right,left2,right2;
455 std::string filename;
456 switch (command.code)
459 mExecuter->Create(words[1],words[2]);
464 // mExecuter->Remove(words[1]);
468 Utilities::SplitAroundFirstDot(words[1],left,right);
469 Utilities::SplitAroundFirstDot(words[2],left2,right2);
470 mExecuter->Connect(left,right,left2,right2);
474 mExecuter->BeginPackage(words[1]);
478 mExecuter->EndPackage();
482 if (mFileName.size()>0)
484 filename = mIncludeFileName.back(); //Utilities::get_file_name(mFileName.back());
488 mExecuter->Define(words[1],"",filename);
492 mExecuter->Define(words[1],words[2],filename);
497 mExecuter->EndDefine();
501 Print(words[1]); /// \todo use generate command
505 if (words[1]=="freeze")
506 mExecuter->SetNoExecMode(true);
507 else if (words[1]=="unfreeze")
508 mExecuter->SetNoExecMode(false);
510 mExecuter->Update(words[1]);
514 Utilities::SplitAroundFirstDot(words[2],left,right);
515 mExecuter->DefineInput(words[1],left,right,words[3]);
519 Utilities::SplitAroundFirstDot(words[2],left,right);
520 mExecuter->DefineOutput(words[1],left,right,words[3]);
524 Utilities::SplitAroundFirstDot(words[1],left,right);
525 mExecuter->Set(left,right,words[2]);
529 mExecuter->Author(words[1]);
533 mExecuter->Category(words[1]);
538 Index("tmp_index.html");
539 else if (words.size()==2)
541 else if (words.size()==3)
542 Index(words[1],words[2]);
546 mExecuter->Description(words[1]);
556 bbtk::MessageManager::PrintInfo();
560 sscanf(words[2].c_str(),"%d",&level);
561 bbtk::MessageManager::SetMessageLevel(words[1],level);
574 this->mExecuter->Reset();
580 InterpretFile(words[1]);
584 SwitchToFile(words[1]);
586 // if 'source' was given
589 GetExecuter()->SetCurrentFileName(words[1]);
594 GetExecuter()->GetFactory()->LoadPackage(words[1]);
598 GetExecuter()->GetFactory()->UnLoadPackage(words[1]);
603 throw QuitException();
607 if (words.size() == 2)
609 if (words[1]=="freeze") mExecuter->SetNoExecMode(true);
610 else if (words[1]=="unfreeze") mExecuter->SetNoExecMode(false);
614 mExecuter->SetWorkspaceName(words[2]);
619 bbtkInternalError("should not reach here !!!");
622 bbtkDecTab("Interpreter",9);
624 //=======================================================================
630 //=======================================================================
634 void Interpreter::SplitLine ( const std::string& str, std::vector<std::string>& tokens)
636 bbtkDebugMessageInc("Interpreter",9,"Interpreter::SplitLine(\""<<str<<"\")"<<std::endl);
638 std::string delimiters = "\"";
639 std::vector<std::string> quote;
640 Utilities::SplitString(str,delimiters,quote);
643 std::vector<std::string>::iterator i;
644 for (i=quote.begin(); i!=quote.end(); )
646 Utilities::SplitString(*i,delimiters,tokens);
650 // bbtkDebugMessage("Interpreter",0,"\""<<*i<<"\""<<std::endl);
651 tokens.push_back(*i);
656 for (i=tokens.begin(); i!=tokens.end(); ++i)
658 bbtkDebugMessage("Interpreter",9,"["<<*i<<"] ");
660 bbtkDebugMessageCont("Interpreter",9,std::endl);
662 bbtkDebugDecTab("Interpreter",9);
664 //=======================================================================
667 //=======================================================================
668 // Replaces substrings "\\n" by a real carriage return "\n"
669 void SubsBackslashN ( std::string& s )
671 std::string ss("\\n");
672 std::string::size_type pos = 0;
675 while ( pos != std::string::npos )
677 s.replace(pos,2,cr,1);
678 pos = s.find(ss, pos-1);
681 //=======================================================================
684 //=======================================================================
688 void Interpreter::Print( const std::string& str)
690 if (mExecuter->GetNoExecMode()) return;
692 bbtkDebugMessageInc("Interpreter",9,"Interpreter::Print(\""<<str<<"\")"<<std::endl);
695 // InterpretLine ("load std")
696 // InterpretLine("new ConcatStrings _C_ ") -> trouver un nom unique : # commande
697 // InterpretLine("new Print _P_")
698 // InterpretLine("connect _C_.Out _P_.In")
702 std::vector<std::string> chains;
703 std::string delimiters("$");
705 // Skip delimiters at beginning.
706 std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
708 if (lastPos>0) is_text = false;
710 // Find first delimiter.
711 std::string::size_type pos = str.find_first_of(delimiters, lastPos);
713 while (std::string::npos != pos || std::string::npos != lastPos)
717 // Found a text token, add it to the vector.
718 chains.push_back(str.substr(lastPos, pos - lastPos));
719 // std::string token = str.substr(lastPos, pos - lastPos)
720 // InterpretLine("set _C_.In%num% %token%")
726 // is an output (between $$) : decode
727 std::string tok,box,output;
728 tok = str.substr(lastPos, pos - lastPos);
729 Utilities::SplitAroundFirstDot(tok,box,output);
730 chains.push_back( mExecuter->Get(box,output) );
732 // InterpretLine("connect %tok% _C_.In%num%")
735 // Skip delimiters. Note the "not_of"
736 lastPos = str.find_first_not_of(delimiters, pos);
737 // Find next delimiter
738 pos = str.find_first_of(delimiters, lastPos);
743 // InterpretLine("exec _P_")
744 // if (IS_IN_WORKSPACE) InterpretLine("delete _C_; delete _P_");
746 std::vector<std::string>::iterator i;
747 for (i= chains.begin(); i!=chains.end(); ++i)
749 // bbtkMessage("Echo",1,*i);
753 std::cout << std::endl;
754 bbtkDebugDecTab("Interpreter",9);
757 //=======================================================================
762 // ===================================================================================
764 void Interpreter::SwitchToFile( const std::string& name )
766 // Note : in the following :
767 // name : the user supplied name
768 // - abreviated name e.g. scr scr.bbs
769 // - relative full name e.g. ./scr.bbs ../../scr.bbs
770 // - absolute full name e.g. /home/usrname/proj/dir/scr.bbs
771 // same for Windows, with c:, d: ...
773 // use ./directory/subdir/scrname.bbs
776 bbtkDebugMessageInc("Interpreter",9,"Interpreter::SwitchToFile( \""
777 <<name<<"\")"<<std::endl);
779 std::vector<std::string> script_paths;
780 std::string fullPathScriptName; // full path script name
781 std::string pkgname; // e.g. <scriptname>.bbs
782 std::vector<std::string> Filenames;
784 // The following is *NOT* a debug time message :
785 // It's a user intended message.
786 // Please don't remove it.
787 bbtkMessage("Interpreter",1,
788 "look for : [" << name
789 << "]" << std::endl);
790 script_paths = ConfigurationFile::GetInstance().Get_bbs_paths();
793 pkgname = Utilities::ExtractScriptName(name,upath);
795 bool fullnameGiven = false;
796 bool foundFile = false;
798 if(pkgname == "*") // =========================================== load all boxes (e.g. std/boxes/*)
802 if (upath[0]=='/' || upath[1] == ':' ) // ==== absolute name, load all .bbs files
804 int nbFiles = Utilities::Explore(upath, false, Filenames);
806 for (std::vector<std::string>::iterator i = Filenames.begin(); i!= Filenames.end(); ++i)
808 if ((*i).substr((*i).size()-4, 4) != ".bbs")
809 continue; // ignore non .bbs files
810 std::string command("include ");
812 // LoadScript(*i,name);
814 InterpretLine(command,tmp);
818 bbtkMessage("Interpreter",2,
819 "WARNING : No '.bbs' file found in ["
820 << upath << "]" << std::endl);
825 std::vector<std::string>::iterator i;
826 std::string fullDirectoryName;
827 for (i=script_paths.begin();i!=script_paths.end();i++)// ==== relative name, iterate + load all .bbs files
831 // we *really* want '.' to be the current working directory
833 char buf[2048]; // for getcwd
834 char * currentDir = getcwd(buf, 2048);
835 std::string cwd(currentDir);
839 fullDirectoryName = Utilities::MakePkgnameFromPath(path, upath, false);
842 // without last slash "\"
843 std::string fullDirectoryNameClean = fullDirectoryName.substr(0,fullDirectoryName.size()-1);
845 // Check if library exists
846 if ( ! Utilities::IsDirectory( fullDirectoryNameClean ) )
848 // The following is *NOT* a debug time message :
849 // It's a user intended message.
850 // Please don't remove it.
851 bbtkMessage("Interpreter",1," [" <<fullDirectoryName
852 <<"] : doesn't exist" <<std::endl);
853 continue; // try next path
858 int nbFiles = Utilities::Explore(fullDirectoryName, false, Filenames);
861 for (std::vector<std::string>::iterator i = Filenames.begin(); i!= Filenames.end(); ++i)
863 //EEDprintf("EED Interpreter::SwitchToFile %s\n",(*i).c_str() );
864 if ((*i).substr((*i).size()-4, 4) != ".bbs")
865 continue; // ignore non .bbs files
866 std::string command("include ");
869 InterpretLine(command,tmp);
870 // LoadScript(*i,name);
874 bbtkMessage("Interpreter",1,
875 "WARNING : No '.bbs' file found in ["
876 << fullDirectoryName << "]" << std::endl);
878 //break; // a directory was found; we stop iterating
879 // LG : No! We want all files included !
884 //std::string::size_type slash_position = name.find_last_of("/\\");
886 // if name starts with a / or a . or contains : user is assumed to have passed a relative/absolute name
887 // (not only a plain script name)
888 // we trust him, and try to expland the directory name
889 // WARNING : starting from current local directory : ./whatYouWant (./ mandatory!)
891 if (name[0]=='/' || name[1] == ':' || name[0]=='.') // absolute path (linux/windows) or relative path
894 // ===========================================================check user supplied location
895 fullnameGiven = true;
897 fullPathScriptName = Utilities::ExpandLibName(name, false);
899 // allow user to always forget ".bbs"
900 int l = fullPathScriptName.size();
906 if (fullPathScriptName.substr(l-4, 4) != ".bbs")
908 fullPathScriptName = fullPathScriptName + ".bbs";
913 fullPathScriptName = fullPathScriptName + ".bbs";
916 if ( Utilities::FileExists(fullPathScriptName))
924 // =============================================================== iterate on the paths
927 std::vector<std::string>::iterator i;
928 for (i=script_paths.begin();i!=script_paths.end();++i)
932 // we *really* want '.' to be the current working directory
934 char buf[2048]; // for getcwd
935 char * currentDir = getcwd(buf, 2048);
936 std::string cwd(currentDir);
940 // fullPathScriptName = Utilities::MakePkgnameFromPath(path, name, true); //pkgname);
942 fullPathScriptName = Utilities::MakePkgnameFromPath(path, name, true);
945 // Check if library exists
946 if ( ! Utilities::FileExists(fullPathScriptName) )
948 // The following is *NOT* a debug time message :
949 // It's a user intended message.
950 // Please don't remove it.
951 bbtkMessage("Interpreter",2,
952 " [" <<fullPathScriptName <<"] : doesn't exist"
954 continue; // try next path
956 bbtkMessage("Interpreter",2,
957 " [" <<fullPathScriptName
958 <<"] : found" <<std::endl);
960 break; // a script was found; we stop iterating
962 } //------------------ // end for ( package_paths.begin();i!=package_paths.end() )
968 if(fullPathScriptName == "")
969 bbtkError("Path ["<<upath<<"] doesn't exist");
971 bbtkError("Script ["<<fullPathScriptName<<"] not found");
973 bbtkError("No ["<<pkgname<<".bbs] script found");
977 LoadScript(fullPathScriptName,name);
983 //=======================================================================
985 void Interpreter::LoadScript( std::string fullPathScriptName,
986 std::string includeScriptName)
988 //EED printf("EED Interpreter::LoadScript >>01\n");
989 Utilities::replace( fullPathScriptName , INVALID_FILE_SEPARATOR , VALID_FILE_SEPARATOR);
991 bool okScriptExist=false;
992 int iStrScript,sizeVecStricpt=mFileName.size();
993 for ( iStrScript=0;iStrScript<sizeVecStricpt;iStrScript++)
995 //EED printf(" EED %d Interpreter::LoadScript %s __>>__ %s\n", iStrScript,mFileName[iStrScript].c_str(),fullPathScriptName.c_str() );
996 if (mFileName[iStrScript] == fullPathScriptName )
998 printf(" EED %d Interpreter::LoadScript iguales\n",iStrScript );
1003 if (find(mFileName.begin(),mFileName.end(),fullPathScriptName)!=mFileName.end())
1004 // if (okScriptExist==true)
1006 //EED printf("EED Interpreter::LoadScript Exit method\n");
1007 bbtkMessage("Interpreter",1,"file '"<<fullPathScriptName
1008 <<"' already open : I do not open it once more to prevent recursive inclusion"<<std::endl);
1013 s = new std::ifstream;
1014 s->open(fullPathScriptName.c_str());
1017 bbtkError("Could not open file ["<<fullPathScriptName<<"]");
1021 bbtkMessage("Interpreter",1," -->[" << fullPathScriptName
1022 << "] found" << std::endl);
1025 mFileName.push_back(fullPathScriptName);
1026 mIncludeFileName.push_back(includeScriptName);
1028 //EED printf("EED Interpreter::LoadScript >>02\n");
1032 //=======================================================================
1036 void Interpreter::CloseCurrentFile()
1038 bbtkDebugMessage("Interpreter",9,"Interpreter::CloseCurrentFile()"
1041 if (mFile.size()==0)
1043 bbtkDebugMessage("Interpreter",9," -> no file left open"<<std::endl);
1047 bbtkDebugMessage("Interpreter",9," Closing file '"<<mFileName.back()<<"'"<<std::endl);
1048 mFile.back()->close();
1049 delete mFile.back();
1051 mFileName.pop_back();
1052 mIncludeFileName.pop_back();
1055 bbtkDebugMessage("Interpreter",9," Closing file '"<<mFileName[0]<<"'"<<std::endl);
1058 mFile.erase( mFile.begin() );
1059 mFileName.erase( mFileName.begin() );
1060 mIncludeFileName.erase( mIncludeFileName.begin() );
1061 mLine.erase( mLine.begin() );
1064 bbtkDebugMessage("Interpreter",9," Remains "
1066 <<" open"<<std::endl);
1067 bbtkDebugMessage("Interpreter",9,"EO Interpreter::CloseCurrentFile()"
1070 //=======================================================================
1072 //=======================================================================
1076 void Interpreter::CloseAllFiles()
1078 bbtkDebugMessage("Interpreter",9,"Interpreter::CloseAllFiles()"
1081 while (mFile.size() != 0)
1083 mFile.back()->close();
1084 delete mFile.back();
1086 bbtkDebugMessage("Interpreter",9,
1087 " Closing file '"<<mFileName.back()<<"'"<<std::endl);
1088 mFileName.pop_back();
1089 mIncludeFileName.pop_back();
1092 bbtkDebugMessage("Interpreter",9,"EO Interpreter::CloseAllFiles()"
1095 //=======================================================================
1099 //=======================================================================
1103 void Interpreter::InterpretCommand( const std::vector<std::string>& words,
1104 CommandInfoType& info )
1106 bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretCommand(...)"<<std::endl);
1108 // searches the command category
1109 CommandDictType::iterator c;
1110 c = mCommandDict.find(words[0]);
1111 if ( c == mCommandDict.end() ) {
1112 bbtkError(words[0]<<" : unknown command");
1115 // tests the number of args
1116 if ( ( words.size()-1 < c->second.argmin ) ||
1117 ( words.size()-1 > c->second.argmax ) )
1119 HelpCommand(words[0]);
1120 bbtkError(words[0]<<" : wrong number of arguments");
1124 bbtkDecTab("Interpreter",9);
1126 //=======================================================================
1129 //=======================================================================
1130 /// Displays help on all the commands
1131 void Interpreter::Help(const std::vector<std::string>& words)
1133 unsigned int nbarg = words.size()-1;
1141 if (words[1]=="packages")
1143 GetExecuter()->GetFactory()->PrintPackages(true);
1148 HelpCommand(words[1]);
1150 catch (bbtk::Exception e)
1154 GetExecuter()->GetFactory()->HelpPackage(words[1]);
1155 #ifdef _USE_WXWIDGETS_
1156 if ( mWxConsole != 0 )
1159 ConfigurationFile::GetInstance().Get_doc_path();
1160 url += "/bbdoc/" + words[1] + "/index.html";
1161 if (Utilities::FileExists(url))
1163 mWxConsole->ShowHtmlPage(url);
1168 catch (bbtk::Exception f)
1172 std::string package;
1173 GetExecuter()->GetFactory()->HelpBlackBox(words[1],package);
1174 #ifdef _USE_WXWIDGETS_
1175 if ( mWxConsole != 0 )
1178 ConfigurationFile::GetInstance().Get_doc_path();
1179 url += "/bbdoc/" + package + "/index.html";
1180 if (Utilities::FileExists(url))
1182 url += "#" + words[1];
1183 mWxConsole->ShowHtmlPage(url);
1188 catch (bbtk::Exception g)
1192 GetExecuter()->ShowRelations(words[1],"0","9999");
1194 catch (bbtk::Exception h){
1195 bbtkError("\""<<words[1].c_str()
1196 <<"\" is not a known command, package, black box type or black box name");
1204 if (words[2]=="all")
1206 if ( words[1]=="packages" )
1208 GetExecuter()->GetFactory()->PrintPackages(true,true);
1213 GetExecuter()->GetFactory()->HelpPackage(words[1],true);
1215 catch (bbtk::Exception f)
1221 HelpCommand(words[0]);
1222 bbtkError(words[0]<<" : syntax error");
1227 bbtkError("Should not reach here !!!");
1230 //=======================================================================
1232 //===================================================================
1233 /// Displays the Configuration
1234 void Interpreter::Config() const
1236 ConfigurationFile::GetInstance().GetHelp(1);
1238 //===================================================================
1240 //=======================================================================
1241 /// Displays help on all the commands
1242 void Interpreter::HelpCommands()
1244 std::cout << "Available commands :" << std::endl;
1245 CommandDictType::iterator i;
1246 for ( i = mCommandDict.begin();
1247 i != mCommandDict.end();
1249 std::cout << " " << i->first << std::endl;
1250 // std::cout << " usage : " << i->second.syntax << std::endl;
1251 // std::cout << " " << i->second.help << std::endl;
1255 //=======================================================================
1258 //=======================================================================
1259 /// Displays help on a particular commands
1260 void Interpreter::HelpCommand(const std::string& s)
1262 CommandDictType::iterator c;
1263 c = mCommandDict.find(s);
1264 if ( c == mCommandDict.end() ) {
1265 bbtkError(s<<" : Unknown command");
1267 // std::cout << " " << s << " : "<< std::endl;
1268 // CommandParamDictType::iterator i;
1269 // for ( i = c->second.begin();
1270 // i != c->second.end();
1272 std::cout << " usage : " << c->second.syntax << std::endl;
1273 std::cout << " " << c->second.help << std::endl;
1276 //=======================================================================
1279 //=======================================================================
1280 /// Fills the vector commands with the commands which
1281 /// have the first n chars of buf for prefix
1282 /// TODO : skip initial spaces in buf and also return the position of first
1283 /// non blank char in buf
1284 void Interpreter::FindCommandsWithPrefix( char* buf,
1286 std::vector<std::string>& commands )
1288 CommandDictType::const_iterator i;
1289 for (i=mCommandDict.begin(); i!=mCommandDict.end(); ++i)
1291 if ((i->first).find(buf,0,n) == 0)
1292 commands.push_back(i->first);
1295 //=======================================================================
1299 //=======================================================================
1300 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1302 inline void PrintChar(char c) { write(STDOUT_FILENO,&c,1); }
1303 inline void BackSpace() { write(STDOUT_FILENO,"\b \b",3); }
1305 // LG : KEYBOARD CODES AS SCANNED ON MY TTY : UNIVERSAL ?
1306 // IF NOT THE USER SHOULD BE ABLE TO CONFIGURE IT
1307 // E.G. STORE THIS IN bbtk_config.xml
1308 #define BBTK_UP_ARROW_KBCODE 0x00415B1B
1309 #define BBTK_DOWN_ARROW_KBCODE 0x00425B1B
1310 #define BBTK_RIGHT_ARROW_KBCODE 0x00435B1B
1311 #define BBTK_LEFT_ARROW_KBCODE 0x00445B1B
1312 #define BBTK_BACKSPACE_KBCODE 0x00000008
1313 #define BBTK_DEL_KBCODE 0x0000007F
1314 #define BBTK_SPACE_KBCODE 0x00000020
1316 //=======================================================================
1317 void Interpreter::GetLineFromPrompt(std::string& s)
1322 int MAX_LINE_SIZE = 160;
1323 int MAX_HISTORY_SIZE = 100;
1325 char* newline = new char[MAX_LINE_SIZE];
1326 memset(newline,0,MAX_LINE_SIZE);
1327 char* histline = new char[MAX_LINE_SIZE];
1328 memset(histline,0,MAX_LINE_SIZE);
1330 char* line = newline;
1331 int hist = mHistory.size();
1337 read ( STDIN_FILENO, &c, 4) ;
1339 bbtkDebugMessage("Debug",9,"[0x"<<std::hex<<c<<"]\n");
1341 // Printable character
1342 if ( (ind<MAX_LINE_SIZE-1) &&
1343 ( c >= BBTK_SPACE_KBCODE ) &&
1344 ( c < BBTK_DEL_KBCODE ))
1352 // delete the unused line
1358 // empty lines are not stored in from history
1361 // if history too long : delete oldest command
1362 if (mHistory.size()>MAX_HISTORY_SIZE)
1364 delete mHistory.front();
1365 mHistory.pop_front();
1367 mHistory.push_back(line);
1372 else if ( (ind>0) &&
1373 ((c == BBTK_BACKSPACE_KBCODE) ||
1374 (c == BBTK_DEL_KBCODE)) )
1382 // TODO : Command completion
1383 std::vector<std::string> commands;
1384 FindCommandsWithPrefix( line,ind,commands);
1385 if (commands.size()==1)
1387 std::string com = *commands.begin();
1388 for (; ind<com.size(); ++ind)
1390 PrintChar(com[ind]);
1396 else if (commands.size()>1)
1398 std::vector<std::string>::iterator i;
1400 for (i=commands.begin();i!=commands.end();++i)
1402 write(STDOUT_FILENO,(*i).c_str(),strlen((*i).c_str()));
1405 write(STDOUT_FILENO,"\n> ",3);
1406 //for (int j=0;j<ind;++j)
1408 write(STDOUT_FILENO,line,ind);
1412 // Arrow up : back in history
1413 else if (c==BBTK_UP_ARROW_KBCODE)
1417 // erase current line
1418 while (ind--) BackSpace();
1422 strcpy(histline,mHistory[hist]);
1426 write(STDOUT_FILENO,line,ind);
1429 // Arrow down : down in history
1430 else if (c==BBTK_DOWN_ARROW_KBCODE)
1432 if (hist<mHistory.size()-1)
1434 // erase current line
1435 while (ind--) BackSpace();
1439 strcpy(histline,mHistory[hist]);
1443 write(STDOUT_FILENO,line,ind);
1445 // end of history : switch back to newline
1446 else if (hist==mHistory.size()-1)
1448 // erase current line
1449 while (ind--) BackSpace();
1456 write(STDOUT_FILENO,line,ind);
1460 else if (line[ind]!=0 && c==BBTK_RIGHT_ARROW_KBCODE)
1462 PrintChar(line[ind]);
1467 else if (ind>0 && c==BBTK_LEFT_ARROW_KBCODE)
1475 write(STDOUT_FILENO,"\n\r",2);
1483 //=======================================================================
1484 void Interpreter::GetLineFromPrompt(std::string& s)
1510 //=======================================================================
1516 //=======================================================================
1517 void Interpreter::CommandLineInterpreter()
1519 bbtkDebugMessageInc("Interpreter",9,
1520 "Interpreter::CommandLineInterpreter()"<<std::endl);
1522 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1523 // Initialise the tty in non canonical mode with no echo
1524 // oter remembers the previous settings to restore them after
1525 struct termios ter,oter;
1528 ter.c_lflag &= ~ECHO;
1529 ter.c_lflag &= ~ICANON;
1532 tcsetattr(0,TCSANOW,&ter);
1535 mCommandLine = true;
1537 bool insideComment = false; // for multiline comment
1543 GetLineFromPrompt(line);
1544 InterpretLine(line, insideComment);
1546 catch (QuitException e)
1550 catch (bbtk::Exception e)
1554 catch (std::exception& e)
1556 std::cerr << "* ERROR :: "<<e.what()<<" (not in bbtk)"<<std::endl;
1560 std::cerr << "* UNDEFINED ERROR (not a bbtk nor a std exception)"<<std::endl;
1565 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1566 tcsetattr(0,TCSANOW,&oter);
1569 std::cout << "Good bye !" << std::endl;
1571 bbtkDebugDecTab("Interpreter",9);
1574 //=======================================================================
1575 void Interpreter::Graph(const std::vector<std::string>& words)
1578 bool system_display = true;
1580 #ifdef _USE_WXWIDGETS_
1581 if ( mWxConsole != 0 ) system_display = false;
1584 if (words.size()==1)
1586 page = mExecuter->ShowGraph(".","0","0","","","",system_display);
1588 else if (words.size()==2)
1590 page = mExecuter->ShowGraph(words[1],"0","0","","","",system_display);
1592 else if (words.size()==3)
1594 page = mExecuter->ShowGraph(words[1],words[2],"0","","","",system_display);
1596 else if (words.size()==4)
1598 page = mExecuter->ShowGraph(words[1],words[2],words[3],"","","",system_display);
1600 else if (words.size()==5)
1602 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],"","",system_display);
1604 else if (words.size()==6)
1606 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],"",system_display);
1608 else if (words.size()==7)
1610 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],words[6],system_display);
1613 #ifdef _USE_WXWIDGETS_
1614 if ( mWxConsole != 0 )
1615 mWxConsole->ShowHtmlPage(page);
1618 //=======================================================================
1621 //=======================================================================
1622 void Interpreter::Index(const std::string& filename,
1623 const std::string& type)
1625 Factory::IndexEntryType t;
1626 if (type=="Initials") t = Factory::Initials;
1627 else if (type=="Categories") t = Factory::Categories;
1628 else if (type=="Packages") t = Factory::Packages;
1629 else if (type=="Adaptors") t = Factory::Adaptors;
1631 GetExecuter()->GetFactory()->CreateHtmlIndex(t,filename);
1633 //=======================================================================