1 /*=========================================================================
4 Module: $RCSfile: bbtkInterpreter.cxx,v $ $
6 Date: $Date: 2008/03/11 12:27:21 $
7 Version: $Revision: 1.43 $
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()))
333 mFile.back()->getline(buf,500);
334 std::string str(buf);
335 int size=str.length();
336 if ( str[ size-1 ]==13 )
341 InterpretLine(str, insideComment);
342 //printf("EED Interpreter::InterpretFile %s\n", str.c_str() );
344 //if (mFile.size()>0)
348 catch (QuitException e)
351 catch (bbtk::Exception e)
353 std::cerr << "* ERROR : "<<e.GetMessage()<<std::endl;
354 if (mFileName.size()) {
355 std::cerr << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
356 std::cerr << "* LINE : "<<mLine.back()<<std::endl;
359 catch (std::exception& e)
361 std::cerr << "* ERROR : "<<e.what()<<" (not in bbtk)"<<std::endl;
362 if (mFileName.size()) {
363 std::cerr << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
364 std::cerr << "* LINE : "<<mLine.back()<<std::endl;
369 std::cout << "* UNDEFINED ERROR (not a bbtk nor a std exception)"<<std::endl;
370 if (mFileName.size()) {
371 std::cout << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
372 std::cout << "* LINE : "<<mLine.back()<<std::endl;
377 bbtkDebugMessage("Interpreter",9,"EO Interpreter::InterpretFile(\""<<filename<<"\")"<<std::endl);
378 bbtkDecTab("Interpreter",9);
382 //=======================================================================
386 //=======================================================================
390 void Interpreter::InterpretLine( const std::string& line, bool &insideComment )
393 bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretLine(\""<<line<<"\")"<<std::endl);
394 bbtkMessage("Echo",2,"\""<<line<<"\""<<std::endl);
396 std::vector<std::string> words;
397 SplitLine(line,words);
402 bbtkDebugDecTab("Interpreter",9);
406 // Single line comment : # or //
407 if ( words[0][0]=='#' || (words[0][0]=='/' && words[0][1]=='/') )
409 bbtkDebugDecTab("Interpreter",9);
410 bbtkMessage("Interpreter",9,"Comment"<<std::endl);
414 // Multi line comment ( /* ... */ ) -delimiters on different lines !-
416 if (words[0][0]=='/' && words[0][1]=='*')
418 bbtkDebugDecTab("Interpreter",9);
419 bbtkMessage("Interpreter",9,"In multiline comment"<<std::endl);
420 insideComment = true;
424 if (words[0][0]=='*' && words[0][1]=='/')
426 bbtkDebugDecTab("Interpreter",9);
427 bbtkMessage("Interpreter",9,"Out multiline comment"<<std::endl);
428 if ( !insideComment ) {
429 bbtkDebugDecTab("Interpreter",9);
430 bbtkMessage("Interpreter",9,"Comment mismatch : '*/' with no matching '/*'"<<std::endl);
432 insideComment = false;
438 bbtkDebugDecTab("Interpreter",9);
439 bbtkMessage("Interpreter",9,"Multiline Comment"<<std::endl);
444 CommandInfoType command;
445 InterpretCommand(words,command);
447 bbtkDebugMessage("Interpreter",9,
448 "Command='"<<command.category
449 <<"' code="<<command.code<<std::endl);
451 std::string left,right,left2,right2;
452 std::string filename;
453 switch (command.code)
456 mExecuter->Create(words[1],words[2]);
461 // mExecuter->Remove(words[1]);
465 Utilities::SplitAroundFirstDot(words[1],left,right);
466 Utilities::SplitAroundFirstDot(words[2],left2,right2);
467 mExecuter->Connect(left,right,left2,right2);
471 mExecuter->BeginPackage(words[1]);
475 mExecuter->EndPackage();
479 if (mFileName.size()>0)
481 filename = mIncludeFileName.back(); //Utilities::get_file_name(mFileName.back());
485 mExecuter->Define(words[1],"",filename);
489 mExecuter->Define(words[1],words[2],filename);
494 mExecuter->EndDefine();
498 Print(words[1]); /// \todo use generate command
502 if (words[1]=="freeze")
503 mExecuter->SetNoExecMode(true);
504 else if (words[1]=="unfreeze")
505 mExecuter->SetNoExecMode(false);
507 mExecuter->Update(words[1]);
511 Utilities::SplitAroundFirstDot(words[2],left,right);
512 mExecuter->DefineInput(words[1],left,right,words[3]);
516 Utilities::SplitAroundFirstDot(words[2],left,right);
517 mExecuter->DefineOutput(words[1],left,right,words[3]);
521 Utilities::SplitAroundFirstDot(words[1],left,right);
522 mExecuter->Set(left,right,words[2]);
526 mExecuter->Author(words[1]);
530 mExecuter->Category(words[1]);
535 Index("tmp_index.html");
536 else if (words.size()==2)
538 else if (words.size()==3)
539 Index(words[1],words[2]);
543 mExecuter->Description(words[1]);
553 bbtk::MessageManager::PrintInfo();
557 sscanf(words[2].c_str(),"%d",&level);
558 bbtk::MessageManager::SetMessageLevel(words[1],level);
571 this->mExecuter->Reset();
577 InterpretFile(words[1]);
581 SwitchToFile(words[1]);
583 // if 'source' was given
586 GetExecuter()->SetCurrentFileName(words[1]);
591 GetExecuter()->GetFactory()->LoadPackage(words[1]);
595 GetExecuter()->GetFactory()->UnLoadPackage(words[1]);
600 throw QuitException();
604 if (words.size() == 2)
606 if (words[1]=="freeze") mExecuter->SetNoExecMode(true);
607 else if (words[1]=="unfreeze") mExecuter->SetNoExecMode(false);
611 mExecuter->SetWorkspaceName(words[2]);
616 bbtkInternalError("should not reach here !!!");
619 bbtkDecTab("Interpreter",9);
621 //=======================================================================
627 //=======================================================================
631 void Interpreter::SplitLine ( const std::string& str, std::vector<std::string>& tokens)
633 bbtkDebugMessageInc("Interpreter",9,"Interpreter::SplitLine(\""<<str<<"\")"<<std::endl);
635 std::string delimiters = "\"";
636 std::vector<std::string> quote;
637 Utilities::SplitString(str,delimiters,quote);
640 std::vector<std::string>::iterator i;
641 for (i=quote.begin(); i!=quote.end(); )
643 Utilities::SplitString(*i,delimiters,tokens);
647 // bbtkDebugMessage("Interpreter",0,"\""<<*i<<"\""<<std::endl);
648 tokens.push_back(*i);
653 for (i=tokens.begin(); i!=tokens.end(); ++i)
655 bbtkDebugMessage("Interpreter",9,"["<<*i<<"] ");
657 bbtkDebugMessageCont("Interpreter",9,std::endl);
659 bbtkDebugDecTab("Interpreter",9);
661 //=======================================================================
664 //=======================================================================
665 // Replaces substrings "\\n" by a real carriage return "\n"
666 void SubsBackslashN ( std::string& s )
668 std::string ss("\\n");
669 std::string::size_type pos = 0;
672 while ( pos != std::string::npos )
674 s.replace(pos,2,cr,1);
675 pos = s.find(ss, pos-1);
678 //=======================================================================
681 //=======================================================================
685 void Interpreter::Print( const std::string& str)
687 if (mExecuter->GetNoExecMode()) return;
689 bbtkDebugMessageInc("Interpreter",9,"Interpreter::Print(\""<<str<<"\")"<<std::endl);
692 // InterpretLine ("load std")
693 // InterpretLine("new ConcatStrings _C_ ") -> trouver un nom unique : # commande
694 // InterpretLine("new Print _P_")
695 // InterpretLine("connect _C_.Out _P_.In")
699 std::vector<std::string> chains;
700 std::string delimiters("$");
702 // Skip delimiters at beginning.
703 std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
705 if (lastPos>0) is_text = false;
707 // Find first delimiter.
708 std::string::size_type pos = str.find_first_of(delimiters, lastPos);
710 while (std::string::npos != pos || std::string::npos != lastPos)
714 // Found a text token, add it to the vector.
715 chains.push_back(str.substr(lastPos, pos - lastPos));
716 // std::string token = str.substr(lastPos, pos - lastPos)
717 // InterpretLine("set _C_.In%num% %token%")
723 // is an output (between $$) : decode
724 std::string tok,box,output;
725 tok = str.substr(lastPos, pos - lastPos);
726 Utilities::SplitAroundFirstDot(tok,box,output);
727 chains.push_back( mExecuter->Get(box,output) );
729 // InterpretLine("connect %tok% _C_.In%num%")
732 // Skip delimiters. Note the "not_of"
733 lastPos = str.find_first_not_of(delimiters, pos);
734 // Find next delimiter
735 pos = str.find_first_of(delimiters, lastPos);
740 // InterpretLine("exec _P_")
741 // if (IS_IN_WORKSPACE) InterpretLine("delete _C_; delete _P_");
743 std::vector<std::string>::iterator i;
744 for (i= chains.begin(); i!=chains.end(); ++i)
746 // bbtkMessage("Echo",1,*i);
750 std::cout << std::endl;
751 bbtkDebugDecTab("Interpreter",9);
754 //=======================================================================
759 // ===================================================================================
761 void Interpreter::SwitchToFile( const std::string& name )
763 // Note : in the following :
764 // name : the user supplied name
765 // - abreviated name e.g. scr scr.bbs
766 // - relative full name e.g. ./scr.bbs ../../scr.bbs
767 // - absolute full name e.g. /home/usrname/proj/dir/scr.bbs
768 // same for Windows, with c:, d: ...
770 // use ./directory/subdir/scrname.bbs
773 bbtkDebugMessageInc("Interpreter",9,"Interpreter::SwitchToFile( \""
774 <<name<<"\")"<<std::endl);
776 std::vector<std::string> script_paths;
777 std::string fullPathScriptName; // full path script name
778 std::string pkgname; // e.g. <scriptname>.bbs
779 std::vector<std::string> Filenames;
781 // The following is *NOT* a debug time message :
782 // It's a user intended message.
783 // Please don't remove it.
784 bbtkMessage("Interpreter",1,
785 "look for : [" << name
786 << "]" << std::endl);
787 script_paths = ConfigurationFile::GetInstance().Get_bbs_paths();
790 pkgname = Utilities::ExtractScriptName(name,upath);
792 bool fullnameGiven = false;
793 bool foundFile = false;
795 if(pkgname == "*") // =========================================== load all boxes (e.g. std/boxes/*)
799 if (upath[0]=='/' || upath[1] == ':' ) // ==== absolute name, load all .bbs files
801 int nbFiles = Utilities::Explore(upath, false, Filenames);
803 for (std::vector<std::string>::iterator i = Filenames.begin(); i!= Filenames.end(); ++i)
805 if ((*i).substr((*i).size()-4, 4) != ".bbs")
806 continue; // ignore non .bbs files
807 std::string command("include ");
809 // LoadScript(*i,name);
811 InterpretLine(command,tmp);
815 bbtkMessage("Interpreter",2,
816 "WARNING : No '.bbs' file found in ["
817 << upath << "]" << std::endl);
822 std::vector<std::string>::iterator i;
823 std::string fullDirectoryName;
824 for (i=script_paths.begin();i!=script_paths.end();i++)// ==== relative name, iterate + load all .bbs files
828 // we *really* want '.' to be the current working directory
830 char buf[2048]; // for getcwd
831 char * currentDir = getcwd(buf, 2048);
832 std::string cwd(currentDir);
836 fullDirectoryName = Utilities::MakePkgnameFromPath(path, upath, false);
839 // without last slash "\"
840 std::string fullDirectoryNameClean = fullDirectoryName.substr(0,fullDirectoryName.size()-1);
842 // Check if library exists
843 if ( ! Utilities::IsDirectory( fullDirectoryNameClean ) )
845 // The following is *NOT* a debug time message :
846 // It's a user intended message.
847 // Please don't remove it.
848 bbtkMessage("Interpreter",1," [" <<fullDirectoryName
849 <<"] : doesn't exist" <<std::endl);
850 continue; // try next path
855 int nbFiles = Utilities::Explore(fullDirectoryName, false, Filenames);
858 for (std::vector<std::string>::iterator i = Filenames.begin(); i!= Filenames.end(); ++i)
860 //EEDprintf("EED Interpreter::SwitchToFile %s\n",(*i).c_str() );
861 if ((*i).substr((*i).size()-4, 4) != ".bbs")
862 continue; // ignore non .bbs files
863 std::string command("include ");
866 InterpretLine(command,tmp);
867 // LoadScript(*i,name);
871 bbtkMessage("Interpreter",1,
872 "WARNING : No '.bbs' file found in ["
873 << fullDirectoryName << "]" << std::endl);
875 //break; // a directory was found; we stop iterating
876 // LG : No! We want all files included !
881 //std::string::size_type slash_position = name.find_last_of("/\\");
883 // if name starts with a / or a . or contains : user is assumed to have passed a relative/absolute name
884 // (not only a plain script name)
885 // we trust him, and try to expland the directory name
886 // WARNING : starting from current local directory : ./whatYouWant (./ mandatory!)
888 if (name[0]=='/' || name[1] == ':' || name[0]=='.') // absolute path (linux/windows) or relative path
891 // ===========================================================check user supplied location
892 fullnameGiven = true;
894 fullPathScriptName = Utilities::ExpandLibName(name, false);
896 // allow user to always forget ".bbs"
897 int l = fullPathScriptName.size();
903 if (fullPathScriptName.substr(l-4, 4) != ".bbs")
905 fullPathScriptName = fullPathScriptName + ".bbs";
910 fullPathScriptName = fullPathScriptName + ".bbs";
913 if ( Utilities::FileExists(fullPathScriptName))
921 // =============================================================== iterate on the paths
924 std::vector<std::string>::iterator i;
925 for (i=script_paths.begin();i!=script_paths.end();++i)
929 // we *really* want '.' to be the current working directory
931 char buf[2048]; // for getcwd
932 char * currentDir = getcwd(buf, 2048);
933 std::string cwd(currentDir);
937 // fullPathScriptName = Utilities::MakePkgnameFromPath(path, name, true); //pkgname);
939 fullPathScriptName = Utilities::MakePkgnameFromPath(path, name, true);
942 // Check if library exists
943 if ( ! Utilities::FileExists(fullPathScriptName) )
945 // The following is *NOT* a debug time message :
946 // It's a user intended message.
947 // Please don't remove it.
948 bbtkMessage("Interpreter",2,
949 " [" <<fullPathScriptName <<"] : doesn't exist"
951 continue; // try next path
953 bbtkMessage("Interpreter",2,
954 " [" <<fullPathScriptName
955 <<"] : found" <<std::endl);
957 break; // a script was found; we stop iterating
959 } //------------------ // end for ( package_paths.begin();i!=package_paths.end() )
965 if(fullPathScriptName == "")
966 bbtkError("Path ["<<upath<<"] doesn't exist");
968 bbtkError("Script ["<<fullPathScriptName<<"] not found");
970 bbtkError("No ["<<pkgname<<".bbs] script found");
974 LoadScript(fullPathScriptName,name);
980 //=======================================================================
982 void Interpreter::LoadScript( std::string fullPathScriptName,
983 std::string includeScriptName)
985 //EED printf("EED Interpreter::LoadScript >>01\n");
986 Utilities::replace( fullPathScriptName , INVALID_FILE_SEPARATOR , VALID_FILE_SEPARATOR);
988 bool okScriptExist=false;
989 int iStrScript,sizeVecStricpt=mFileName.size();
990 for ( iStrScript=0;iStrScript<sizeVecStricpt;iStrScript++)
992 //EED printf(" EED %d Interpreter::LoadScript %s __>>__ %s\n", iStrScript,mFileName[iStrScript].c_str(),fullPathScriptName.c_str() );
993 if (mFileName[iStrScript] == fullPathScriptName )
995 // printf(" EED %d Interpreter::LoadScript iguales\n",iStrScript );
1000 if (find(mFileName.begin(),mFileName.end(),fullPathScriptName)!=mFileName.end())
1001 // if (okScriptExist==true)
1003 //EED printf("EED Interpreter::LoadScript Exit method\n");
1004 bbtkMessage("Interpreter",1,"file '"<<fullPathScriptName
1005 <<"' already open : I do not open it once more to prevent recursive inclusion"<<std::endl);
1010 s = new std::ifstream;
1011 s->open(fullPathScriptName.c_str());
1014 bbtkError("Could not open file ["<<fullPathScriptName<<"]");
1018 bbtkMessage("Interpreter",1," -->[" << fullPathScriptName
1019 << "] found" << std::endl);
1022 mFileName.push_back(fullPathScriptName);
1023 mIncludeFileName.push_back(includeScriptName);
1025 //EED printf("EED Interpreter::LoadScript >>02\n");
1029 //=======================================================================
1033 void Interpreter::CloseCurrentFile()
1035 bbtkDebugMessage("Interpreter",9,"Interpreter::CloseCurrentFile()"
1038 if (mFile.size()==0)
1040 bbtkDebugMessage("Interpreter",9," -> no file left open"<<std::endl);
1044 bbtkDebugMessage("Interpreter",9," Closing file '"<<mFileName.back()<<"'"<<std::endl);
1045 mFile.back()->close();
1046 delete mFile.back();
1048 mFileName.pop_back();
1049 mIncludeFileName.pop_back();
1052 bbtkDebugMessage("Interpreter",9," Closing file '"<<mFileName[0]<<"'"<<std::endl);
1055 mFile.erase( mFile.begin() );
1056 mFileName.erase( mFileName.begin() );
1057 mIncludeFileName.erase( mIncludeFileName.begin() );
1058 mLine.erase( mLine.begin() );
1061 bbtkDebugMessage("Interpreter",9," Remains "
1063 <<" open"<<std::endl);
1064 bbtkDebugMessage("Interpreter",9,"EO Interpreter::CloseCurrentFile()"
1067 //=======================================================================
1069 //=======================================================================
1073 void Interpreter::CloseAllFiles()
1075 bbtkDebugMessage("Interpreter",9,"Interpreter::CloseAllFiles()"
1078 while (mFile.size() != 0)
1080 mFile.back()->close();
1081 delete mFile.back();
1083 bbtkDebugMessage("Interpreter",9,
1084 " Closing file '"<<mFileName.back()<<"'"<<std::endl);
1085 mFileName.pop_back();
1086 mIncludeFileName.pop_back();
1089 bbtkDebugMessage("Interpreter",9,"EO Interpreter::CloseAllFiles()"
1092 //=======================================================================
1096 //=======================================================================
1100 void Interpreter::InterpretCommand( const std::vector<std::string>& words,
1101 CommandInfoType& info )
1103 bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretCommand(...)"<<std::endl);
1105 // searches the command category
1106 CommandDictType::iterator c;
1107 c = mCommandDict.find(words[0]);
1108 if ( c == mCommandDict.end() ) {
1109 bbtkError(words[0]<<" : unknown command");
1112 // tests the number of args
1113 if ( ( words.size()-1 < c->second.argmin ) ||
1114 ( words.size()-1 > c->second.argmax ) )
1116 HelpCommand(words[0]);
1117 bbtkError(words[0]<<" : wrong number of arguments");
1121 bbtkDecTab("Interpreter",9);
1123 //=======================================================================
1126 //=======================================================================
1127 /// Displays help on all the commands
1128 void Interpreter::Help(const std::vector<std::string>& words)
1130 unsigned int nbarg = words.size()-1;
1138 if (words[1]=="packages")
1140 GetExecuter()->GetFactory()->PrintPackages(true);
1145 HelpCommand(words[1]);
1147 catch (bbtk::Exception e)
1151 GetExecuter()->GetFactory()->HelpPackage(words[1]);
1152 #ifdef _USE_WXWIDGETS_
1153 if ( mWxConsole != 0 )
1156 ConfigurationFile::GetInstance().Get_doc_path();
1157 url += "/bbdoc/" + words[1] + "/index.html";
1158 if (Utilities::FileExists(url))
1160 mWxConsole->ShowHtmlPage(url);
1165 catch (bbtk::Exception f)
1169 std::string package;
1170 GetExecuter()->GetFactory()->HelpBlackBox(words[1],package);
1171 #ifdef _USE_WXWIDGETS_
1172 if ( mWxConsole != 0 )
1175 ConfigurationFile::GetInstance().Get_doc_path();
1176 url += "/bbdoc/" + package + "/index.html";
1177 if (Utilities::FileExists(url))
1179 url += "#" + words[1];
1180 mWxConsole->ShowHtmlPage(url);
1185 catch (bbtk::Exception g)
1189 GetExecuter()->ShowRelations(words[1],"0","9999");
1191 catch (bbtk::Exception h){
1192 bbtkError("\""<<words[1].c_str()
1193 <<"\" is not a known command, package, black box type or black box name");
1201 if (words[2]=="all")
1203 if ( words[1]=="packages" )
1205 GetExecuter()->GetFactory()->PrintPackages(true,true);
1210 GetExecuter()->GetFactory()->HelpPackage(words[1],true);
1212 catch (bbtk::Exception f)
1218 HelpCommand(words[0]);
1219 bbtkError(words[0]<<" : syntax error");
1224 bbtkError("Should not reach here !!!");
1227 //=======================================================================
1229 //===================================================================
1230 /// Displays the Configuration
1231 void Interpreter::Config() const
1233 ConfigurationFile::GetInstance().GetHelp(1);
1235 //===================================================================
1237 //=======================================================================
1238 /// Displays help on all the commands
1239 void Interpreter::HelpCommands()
1241 std::cout << "Available commands :" << std::endl;
1242 CommandDictType::iterator i;
1243 for ( i = mCommandDict.begin();
1244 i != mCommandDict.end();
1246 std::cout << " " << i->first << std::endl;
1247 // std::cout << " usage : " << i->second.syntax << std::endl;
1248 // std::cout << " " << i->second.help << std::endl;
1252 //=======================================================================
1255 //=======================================================================
1256 /// Displays help on a particular commands
1257 void Interpreter::HelpCommand(const std::string& s)
1259 CommandDictType::iterator c;
1260 c = mCommandDict.find(s);
1261 if ( c == mCommandDict.end() ) {
1262 bbtkError(s<<" : Unknown command");
1264 // std::cout << " " << s << " : "<< std::endl;
1265 // CommandParamDictType::iterator i;
1266 // for ( i = c->second.begin();
1267 // i != c->second.end();
1269 std::cout << " usage : " << c->second.syntax << std::endl;
1270 std::cout << " " << c->second.help << std::endl;
1273 //=======================================================================
1276 //=======================================================================
1277 /// Fills the vector commands with the commands which
1278 /// have the first n chars of buf for prefix
1279 /// TODO : skip initial spaces in buf and also return the position of first
1280 /// non blank char in buf
1281 void Interpreter::FindCommandsWithPrefix( char* buf,
1283 std::vector<std::string>& commands )
1285 CommandDictType::const_iterator i;
1286 for (i=mCommandDict.begin(); i!=mCommandDict.end(); ++i)
1288 if ((i->first).find(buf,0,n) == 0)
1289 commands.push_back(i->first);
1292 //=======================================================================
1296 //=======================================================================
1297 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1299 inline void PrintChar(char c) { write(STDOUT_FILENO,&c,1); }
1300 inline void BackSpace() { write(STDOUT_FILENO,"\b \b",3); }
1302 // LG : KEYBOARD CODES AS SCANNED ON MY TTY : UNIVERSAL ?
1303 // IF NOT THE USER SHOULD BE ABLE TO CONFIGURE IT
1304 // E.G. STORE THIS IN bbtk_config.xml
1305 #define BBTK_UP_ARROW_KBCODE 0x00415B1B
1306 #define BBTK_DOWN_ARROW_KBCODE 0x00425B1B
1307 #define BBTK_RIGHT_ARROW_KBCODE 0x00435B1B
1308 #define BBTK_LEFT_ARROW_KBCODE 0x00445B1B
1309 #define BBTK_BACKSPACE_KBCODE 0x00000008
1310 #define BBTK_DEL_KBCODE 0x0000007F
1311 #define BBTK_SPACE_KBCODE 0x00000020
1313 //=======================================================================
1314 void Interpreter::GetLineFromPrompt(std::string& s)
1319 int MAX_LINE_SIZE = 160;
1320 int MAX_HISTORY_SIZE = 100;
1322 char* newline = new char[MAX_LINE_SIZE];
1323 memset(newline,0,MAX_LINE_SIZE);
1324 char* histline = new char[MAX_LINE_SIZE];
1325 memset(histline,0,MAX_LINE_SIZE);
1327 char* line = newline;
1328 int hist = mHistory.size();
1334 read ( STDIN_FILENO, &c, 4) ;
1336 bbtkDebugMessage("Debug",9,"[0x"<<std::hex<<c<<"]\n");
1338 // Printable character
1339 if ( (ind<MAX_LINE_SIZE-1) &&
1340 ( c >= BBTK_SPACE_KBCODE ) &&
1341 ( c < BBTK_DEL_KBCODE ))
1349 // delete the unused line
1355 // empty lines are not stored in from history
1358 // if history too long : delete oldest command
1359 if (mHistory.size()>MAX_HISTORY_SIZE)
1361 delete mHistory.front();
1362 mHistory.pop_front();
1364 mHistory.push_back(line);
1369 else if ( (ind>0) &&
1370 ((c == BBTK_BACKSPACE_KBCODE) ||
1371 (c == BBTK_DEL_KBCODE)) )
1379 // TODO : Command completion
1380 std::vector<std::string> commands;
1381 FindCommandsWithPrefix( line,ind,commands);
1382 if (commands.size()==1)
1384 std::string com = *commands.begin();
1385 for (; ind<com.size(); ++ind)
1387 PrintChar(com[ind]);
1393 else if (commands.size()>1)
1395 std::vector<std::string>::iterator i;
1397 for (i=commands.begin();i!=commands.end();++i)
1399 write(STDOUT_FILENO,(*i).c_str(),strlen((*i).c_str()));
1402 write(STDOUT_FILENO,"\n> ",3);
1403 //for (int j=0;j<ind;++j)
1405 write(STDOUT_FILENO,line,ind);
1409 // Arrow up : back in history
1410 else if (c==BBTK_UP_ARROW_KBCODE)
1414 // erase current line
1415 while (ind--) BackSpace();
1419 strcpy(histline,mHistory[hist]);
1423 write(STDOUT_FILENO,line,ind);
1426 // Arrow down : down in history
1427 else if (c==BBTK_DOWN_ARROW_KBCODE)
1429 if (hist<mHistory.size()-1)
1431 // erase current line
1432 while (ind--) BackSpace();
1436 strcpy(histline,mHistory[hist]);
1440 write(STDOUT_FILENO,line,ind);
1442 // end of history : switch back to newline
1443 else if (hist==mHistory.size()-1)
1445 // erase current line
1446 while (ind--) BackSpace();
1453 write(STDOUT_FILENO,line,ind);
1457 else if (line[ind]!=0 && c==BBTK_RIGHT_ARROW_KBCODE)
1459 PrintChar(line[ind]);
1464 else if (ind>0 && c==BBTK_LEFT_ARROW_KBCODE)
1472 write(STDOUT_FILENO,"\n\r",2);
1480 //=======================================================================
1481 void Interpreter::GetLineFromPrompt(std::string& s)
1507 //=======================================================================
1513 //=======================================================================
1514 void Interpreter::CommandLineInterpreter()
1516 bbtkDebugMessageInc("Interpreter",9,
1517 "Interpreter::CommandLineInterpreter()"<<std::endl);
1519 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1520 // Initialise the tty in non canonical mode with no echo
1521 // oter remembers the previous settings to restore them after
1522 struct termios ter,oter;
1525 ter.c_lflag &= ~ECHO;
1526 ter.c_lflag &= ~ICANON;
1529 tcsetattr(0,TCSANOW,&ter);
1532 mCommandLine = true;
1534 bool insideComment = false; // for multiline comment
1540 GetLineFromPrompt(line);
1541 InterpretLine(line, insideComment);
1543 catch (QuitException e)
1547 catch (bbtk::Exception e)
1551 catch (std::exception& e)
1553 std::cerr << "* ERROR :: "<<e.what()<<" (not in bbtk)"<<std::endl;
1557 std::cerr << "* UNDEFINED ERROR (not a bbtk nor a std exception)"<<std::endl;
1562 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1563 tcsetattr(0,TCSANOW,&oter);
1566 std::cout << "Good bye !" << std::endl;
1568 bbtkDebugDecTab("Interpreter",9);
1571 //=======================================================================
1572 void Interpreter::Graph(const std::vector<std::string>& words)
1575 bool system_display = true;
1577 #ifdef _USE_WXWIDGETS_
1578 if ( mWxConsole != 0 ) system_display = false;
1581 if (words.size()==1)
1583 page = mExecuter->ShowGraph(".","0","0","","","",system_display);
1585 else if (words.size()==2)
1587 page = mExecuter->ShowGraph(words[1],"0","0","","","",system_display);
1589 else if (words.size()==3)
1591 page = mExecuter->ShowGraph(words[1],words[2],"0","","","",system_display);
1593 else if (words.size()==4)
1595 page = mExecuter->ShowGraph(words[1],words[2],words[3],"","","",system_display);
1597 else if (words.size()==5)
1599 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],"","",system_display);
1601 else if (words.size()==6)
1603 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],"",system_display);
1605 else if (words.size()==7)
1607 page = mExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],words[6],system_display);
1610 #ifdef _USE_WXWIDGETS_
1611 if ( mWxConsole != 0 )
1612 mWxConsole->ShowHtmlPage(page);
1615 //=======================================================================
1618 //=======================================================================
1619 void Interpreter::Index(const std::string& filename,
1620 const std::string& type)
1622 Factory::IndexEntryType t;
1623 if (type=="Initials") t = Factory::Initials;
1624 else if (type=="Categories") t = Factory::Categories;
1625 else if (type=="Packages") t = Factory::Packages;
1626 else if (type=="Adaptors") t = Factory::Adaptors;
1628 GetExecuter()->GetFactory()->CreateHtmlIndex(t,filename);
1630 //=======================================================================