1 /*=========================================================================
3 Module: $RCSfile: bbtkInterpreter.cxx,v $
5 Date: $Date: 2009/06/08 14:50:03 $
6 Version: $Revision: 1.86 $
7 =========================================================================*/
9 /* ---------------------------------------------------------------------
11 * Copyright (c) CREATIS-LRMN (Centre de Recherche en Imagerie Medicale)
12 * Authors : Eduardo Davila, Laurent Guigues, Jean-Pierre Roux
14 * This software is governed by the CeCILL-B license under French law and
15 * abiding by the rules of distribution of free software. You can use,
16 * modify and/ or redistribute the software under the terms of the CeCILL-B
17 * license as circulated by CEA, CNRS and INRIA at the following URL
18 * http://www.cecill.info/licences/Licence_CeCILL-B_V1-en.html
19 * or in the file LICENSE.txt.
21 * As a counterpart to the access to the source code and rights to copy,
22 * modify and redistribute granted by the license, users are provided only
23 * with a limited warranty and the software's author, the holder of the
24 * economic rights, and the successive licensors have only limited
27 * The fact that you are presently reading this means that you have had
28 * knowledge of the CeCILL-B license and that you accept its terms.
29 * ------------------------------------------------------------------------ */
33 * \brief class Interpreter :
36 #include "bbtkInterpreter.h"
37 #include "bbtkExecuter.h"
38 #include "bbtkTranscriptor.h"
39 #include "bbtkMessageManager.h"
40 #include "bbtkConfigurationFile.h"
41 #include "bbtkUtilities.h"
42 #include "bbtkAtomicBlackBox.h"
43 #include "bbtkWxBlackBox.h"
46 #ifdef CMAKE_HAVE_TERMIOS_H
48 #define BBTK_USE_TERMIOS_BASED_PROMPT
56 //=======================================================================
57 Interpreter::Pointer Interpreter::New(const std::string& cpp_file)
59 bbtkDebugMessage("kernel",9,"Interpreter::New('"<<cpp_file<<"')"<<std::endl);
60 return MakePointer(new Interpreter(cpp_file));
62 //=======================================================================
64 //=======================================================================
65 Interpreter::Pointer Interpreter::New(VirtualExec::Pointer e)
67 bbtkDebugMessage("kernel",9,"Interpreter::New(VirtualExec)"<<std::endl);
68 return MakePointer(new Interpreter(e));
70 //=======================================================================
72 //=======================================================================
73 Interpreter::Interpreter(const std::string& cpp_file)
75 bbtkDebugMessage("object",2,"==> Interpreter("<<cpp_file<<")"<<std::endl);
76 Init(VirtualExec::Pointer(), cpp_file);
77 bbtkDebugMessage("object",2,"<== Interpreter("<<cpp_file<<")"<<std::endl);
79 //=======================================================================
81 //=======================================================================
82 Interpreter::Interpreter(VirtualExec::Pointer e)
84 bbtkDebugMessage("object",2,"==> Interpreter(VirtualExec)"<<std::endl);
86 bbtkDebugMessage("object",2,"<== Interpreter(VirtualExec)"<<std::endl);
88 //=======================================================================
90 //=======================================================================
91 void Interpreter::Init(VirtualExec::Pointer e, const std::string& cpp_file)
97 bbtk::MessageManager::RegisterMessageType("echo","Level>0 : Prints the output of the 'print' commands of the user.\n\tLevel>1 : Prints the command being interpreted",1);
98 bbtk::MessageManager::RegisterMessageType("Interpreter","Messages of the interpreter",0);
99 bbtkDebugMessageInc("Interpreter",9,"Interpreter::Interpreter()" <<std::endl);
102 mVirtualExecuter = e;
104 else if (cpp_file.size()!=0)
106 mVirtualExecuter = boost::static_pointer_cast<VirtualExec>(bbtk::Transcriptor::New(cpp_file));
110 bbtk::Executer::Pointer exe = bbtk::Executer::New();
112 mVirtualExecuter = boost::static_pointer_cast<VirtualExec>(exe);
115 // Lock this pointer or will auto-destruct !!
116 if (!e) mVirtualExecuter->SetInterpreter(MakePointer(this,true));
118 // For the time being, comment out previous line, and
119 // uncomment next line to check Transcriptor
121 //mVirtualExecuter = new bbtk::Transcriptor("GeneratedProgram.txt");
123 // Builds the commands dict
124 CommandInfoType info;
126 info.keyword = "new";
130 info.syntax = "new <type> <name>";
131 info.help = "Creates a new black box of type <type> with name <name>";
132 mCommandDict[info.keyword] = info;
134 info.keyword = "delete";
138 info.syntax = "delete <box>";
139 info.help = "Deletes the black box of name <box>";
140 mCommandDict[info.keyword] = info;
142 info.keyword = "clear";
146 info.syntax = "clear";
147 info.help = "Clears the currently defined complex box (deletes all its boxes and connections)";
148 mCommandDict[info.keyword] = info;
150 info.keyword = "break";
154 info.syntax = "break";
155 info.help = "Breaks the current execution";
156 mCommandDict[info.keyword] = info;
158 info.keyword = "newgui";
162 info.syntax = "newgui <box> <name>";
163 info.help = "Automatically creates a graphical user interface with name <name> for the black box <box> and connects it to the box inputs";
164 mCommandDict[info.keyword] = info;
166 info.keyword = "connect";
169 info.code = cConnect;
170 info.syntax = "connect <box1.output> <box2.input>";
171 info.help = "Connects the ouput <output> of black box <box1> to the input <input> of black box <box2>";
172 mCommandDict[info.keyword] = info;
174 info.keyword = "print";
178 info.syntax = "print <string>";
179 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').";
180 mCommandDict[info.keyword] = info;
182 info.keyword = "exec";
186 info.syntax = "exec <box | 'freeze' | 'unfreeze' | 'freeze_no_error' >";
187 info.help = "Executes the black box of name <box> (and connected boxes if needed). If the special keyword 'freeze' is given then freezes any further execution command. 'unfreeze' reverts to normal execution mode. 'freeze_no_error' is like freeze but also skips any error.";
188 mCommandDict[info.keyword] = info;
190 info.keyword = "package";
193 info.code = cPackage;
194 info.syntax = "package <name>";
195 info.help = "Begins the definition of a package.";
196 mCommandDict[info.keyword] = info;
198 info.keyword = "endpackage";
201 info.code = cEndPackage;
202 info.syntax = "endpackage";
203 info.help = "Ends the definition of a package.";
204 mCommandDict[info.keyword] = info;
206 info.keyword = "define";
210 info.syntax = "define <type> [<package>]";
211 info.help = "Begins the definition of a new type of complex black box called <type>. If <package> is provided will create it in the given package.";
212 mCommandDict[info.keyword] = info;
214 info.keyword = "endefine";
217 info.code = cEndDefine;
218 info.syntax = "endefine";
219 info.help = "Ends the definition of a new type of complex black box";
220 mCommandDict[info.keyword] = info;
222 info.keyword = "kind";
226 info.syntax = "kind <ADAPTOR|DEFAULT_ADAPTOR|GUI|DEFAULT_GUI>";
227 info.help = "Sets the kind of the currently defined complex black box";
228 mCommandDict[info.keyword] = info;
230 info.keyword = "input";
234 info.syntax = "input <name> <box.input> <help>";
235 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";
236 mCommandDict[info.keyword] = info;
238 info.keyword = "output";
242 info.syntax = "output <name> <box.output> <help>";
243 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";
244 mCommandDict[info.keyword] = info;
246 info.keyword = "set";
250 info.syntax = "set <box.input> <value>";
251 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";
252 mCommandDict[info.keyword] = info;
254 info.keyword = "config"; // JPR
258 info.syntax = "config";
259 info.help = "Prints the value of all configuration parameters";
260 mCommandDict[info.keyword] = info;
262 info.keyword = "index"; // LG
267 info.syntax = "index [<filename> ['Initials'(default)|'Packages'|'Categories'|'Adaptors']]";
268 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.";
269 mCommandDict[info.keyword] = info;
271 info.keyword = "reset";
275 info.syntax = "reset";
276 info.help = "Deletes all boxes and unloads all packages (reset to start state)";
277 mCommandDict[info.keyword] = info;
279 info.keyword = "author";
283 info.syntax = "author <string>";
284 info.help = "Adds the string <string> to the author information of the black box being defined";
285 mCommandDict[info.keyword] = info;
287 info.keyword = "category"; //JP
290 info.code = cCategory;
291 info.syntax = "category <list of items, separated by ;>";
292 info.help = "Adds the string <string> to the category information of the black box being defined";
293 mCommandDict[info.keyword] = info;
295 info.keyword = "description";
298 info.code = cDescription;
299 info.syntax = "description <string>";
300 info.help = "Adds the string <string> to the descriptive information of the black box being defined";
301 mCommandDict[info.keyword] = info;
303 info.keyword = "help";
307 info.syntax = "help";
308 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>";
309 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.";
310 mCommandDict[info.keyword] = info;
312 info.keyword = "message";
315 info.code = cMessage;
316 info.syntax = "message <kind> <level>";
317 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.";
318 mCommandDict[info.keyword] = info;
320 info.keyword = "include";
323 info.code = cInclude;
324 info.syntax = "include <filename> [source]";
325 info.help = "Includes the file <filename>.\n 'source' : If the keyword 'source' is provided then informs the interpreter 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).";
326 mCommandDict[info.keyword] = info;
328 info.keyword = "quit";
332 info.syntax = "quit";
333 info.help = "Quits the program (during script execution it stops the complete execution)";
334 mCommandDict[info.keyword] = info;
336 info.keyword = "load";
340 info.syntax = "load <packagename>";
341 info.help = "Loads the black box package <packagename>";
342 mCommandDict[info.keyword] = info;
344 info.keyword = "unload";
348 info.syntax = "unload <packagename>";
349 info.help = "Unloads the black box package <packagename>";
350 mCommandDict[info.keyword] = info;
352 info.keyword = "graph";
356 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 ]]]]]]";
357 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')";
358 mCommandDict[info.keyword] = info;
360 info.keyword = "debug";
364 info.syntax = "debug [expr|-C|-D]";
365 info.help = "Prints debug info on living bbtk objects containing the string 'expr' (default expr=''). -C checks the factory integrity. -D turns on objects debug info after main ends";
366 mCommandDict[info.keyword] = info;
369 info.keyword = "workspace";
372 info.code = cWorkspace;
373 info.syntax = "workspace < ( freeze | unfreeze ) | ( rename <newname> ) >";
374 info.help = "Configures the workspace.\n 'freeze' allows 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.";
375 mCommandDict[info.keyword] = info;
381 //=======================================================================
385 //=======================================================================
389 Interpreter::~Interpreter()
391 bbtkDebugMessage("object",2,"==> ~Interpreter()" <<std::endl);
392 mVirtualExecuter = VirtualExec::Pointer();
393 bbtkDebugMessage("object",2,"<== ~Interpreter()" <<std::endl);
395 //=======================================================================
398 //=======================================================================
399 InterpreterException::InterpreterException( const std::string& message,
401 const std::string& script_file,
404 : Exception("interpreter",0,message),
405 mInScriptFile(in_script_file),
406 mScriptFile(script_file),
407 mScriptLine(script_line)
410 //=======================================================================
411 //=======================================================================
412 InterpreterException::InterpreterException( const Exception& excep,
414 const std::string& script_file,
418 mInScriptFile(in_script_file),
419 mScriptFile(script_file),
420 mScriptLine(script_line)
423 //=======================================================================
426 //=======================================================================
427 void Interpreter::CatchInterpreterException( const InterpreterException& e )
429 if (GetExecuter()->GetNoErrorMode())
431 bbtkWarning("ERROR :"<<e.GetErrorMessage()
432 <<" ("<<e.GetScriptFile()<<":"<<e.GetScriptLine()
439 if (e.GetErrorMessage()!="break")
441 mStatus = Interpreter_ERROR;
444 throw InterpreterException(e);
448 std::stringstream mess;
449 mess << "* ERROR : "<<e.GetErrorMessage()<<std::endl;
450 if (e.IsInScriptFile())
452 mess << "* FILE : \""<<e.GetScriptFile()<<"\""<<std::endl;
453 mess << "* LINE : "<<e.GetScriptLine()<<std::endl;
456 std::cerr << mess.str();
459 //=======================================================================
461 //=======================================================================
462 void Interpreter::CatchBbtkException( const bbtk::Exception& e )
464 if (GetExecuter()->GetNoErrorMode())
466 std::string file("?");
468 if (mFileName.size()) {
469 file = mFileName.back();
472 bbtkWarning("ERROR '"<<e.GetErrorMessage()
473 <<"' ("<<file<<":"<<line<<") skipped");
477 mStatus = Interpreter_ERROR;
480 bool in_script = false;
481 std::string file("");
483 if (mFileName.size()) {
484 std::ifstream* fs = dynamic_cast<std::ifstream*>(mFile.back());
485 if (fs!=0) in_script = true;
486 file = mFileName.back();
489 if (e.GetErrorMessage()!="break")
491 throw InterpreterException(e,in_script,file,line);
495 std::stringstream mess;
496 mess << "* ERROR : "<<e.GetErrorMessage()<<std::endl;
497 if (mFileName.size()) {
498 mess << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
499 mess << "* LINE : "<<mLine.back()<<std::endl;
502 std::cerr << mess.str();
505 //=======================================================================
507 //=======================================================================
508 void Interpreter::CatchStdException( const std::exception& e )
510 if (GetExecuter()->GetNoErrorMode())
512 std::string file("?");
514 if (mFileName.size()) {
515 file = mFileName.back();
518 bbtkWarning("ERROR '"<<e.what()
519 <<"' ("<<file<<":"<<line<<") skipped");
523 mStatus = Interpreter_ERROR;
526 bool in_script = false;
527 std::string file("");
529 if (mFileName.size()) {
530 std::ifstream* fs = dynamic_cast<std::ifstream*>(mFile.back());
531 if (fs!=0) in_script = true;
532 file = mFileName.back();
536 throw InterpreterException(e.what(),in_script,file,line);
540 std::stringstream mess;
541 mess << "* ERROR : "<<e.what()<<std::endl;
542 if (mFileName.size()) {
543 mess << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
544 mess << "* LINE : "<<mLine.back()<<std::endl;
547 std::cerr << mess.str();
550 //=======================================================================
552 //=======================================================================
553 void Interpreter::CatchUnknownException()
555 if (GetExecuter()->GetNoErrorMode())
557 std::string file("?");
559 if (mFileName.size()) {
560 file = mFileName.back();
563 bbtkWarning("UNDEFINED ERROR "
564 <<"("<<file<<":"<<line<<") skipped");
567 mStatus = Interpreter_ERROR;
570 bool in_script = false;
571 std::string file("");
573 if (mFileName.size()) {
574 std::ifstream* fs = dynamic_cast<std::ifstream*>(mFile.back());
575 if (fs!=0) in_script = true;
576 file = mFileName.back();
580 throw InterpreterException("Unknown exception caught",
581 in_script,file,line);
585 std::stringstream mess;
586 mess << "* UNDEFINED ERROR (not a bbtk nor a std exception)"
588 if (mFileName.size()) {
589 mess << "* FILE : \""<<mFileName.back()<<"\""<<std::endl;
590 mess << "* LINE : "<<mLine.back()<<std::endl;
593 std::cerr << mess.str();
596 //=======================================================================
598 //=======================================================================
600 #define CATCH_MACRO \
601 catch (InterpreterException e) \
603 CatchInterpreterException(e); \
605 catch (bbtk::Exception e) \
607 CatchBbtkException(e); \
609 catch (std::exception& e) \
611 CatchStdException(e); \
615 CatchUnknownException(); \
617 //=======================================================================
620 //=======================================================================
621 Interpreter::ExitStatus Interpreter::InterpretFile( const std::string& filename, bool source )
623 bbtkDebugMessage("interpreter",4,"==> Interpreter::InterpretFile(\""<<filename<<"\")"<<std::endl);
625 bool exm = mCommandLine;
626 mCommandLine = false;
630 mStatus = Interpreter_OK;
631 SwitchToFile(filename,source);
632 mInsideComment = false;
633 InterpretCurrentStreams();
637 bbtkDebugMessage("interpreter",4,
638 "<== Interpreter::InterpretFile(\""
639 <<filename<<"\")"<<std::endl);
646 //=======================================================================
649 //=======================================================================
650 Interpreter::ExitStatus
651 Interpreter::InterpretBuffer( std::stringstream* buffer )
653 bbtkDebugMessage("interpreter",4,"==> Interpreter::InterpretBuffer()"<<std::endl);
655 bool exm = mCommandLine;
656 mCommandLine = false;
660 mStatus = Interpreter_OK;
661 SwitchToStream(buffer);
662 mInsideComment = false;
663 InterpretCurrentStreams();
668 bbtkDebugMessage("interpreter",4,"<== Interpreter::InterpretBuffer()"<<std::endl);
674 //=======================================================================
676 //=======================================================================
677 /// Interprets the currently open streams
678 Interpreter::ExitStatus Interpreter::InterpretCurrentStreams()
680 bbtkDebugMessage("interpreter",4,
681 "==> Interpreter::InterpretCurrentStreams()"<<std::endl);
683 while (mFile.size()>0)
685 while (!mFile.back()->eof()) {
688 mFile.back()->getline(buf,500);
689 std::string str(buf);
691 int size=str.length();
692 if ( str[ size-1 ]==13 )
698 DoInterpretLine(str);
704 bbtkDebugMessage("interpreter",4,
705 "<== Interpreter::InterpretCurrentStreams()"<<std::endl);
709 //=======================================================================
711 //=======================================================================
712 /// Runs the interpretation of a command
713 Interpreter::ExitStatus Interpreter::InterpretLine( const std::string& line )
715 bbtkDebugMessage("interpreter",5,"==> Interpreter::InterpretLine('"<<line<<"')"<<std::endl);
719 mStatus = Interpreter_OK;
720 mInsideComment = false;
721 DoInterpretLine(line );
726 bbtkDebugMessage("interpreter",5,"<== Interpreter::InterpretLine('"<<line<<"')"<<std::endl);
730 //=======================================================================
733 //=======================================================================
734 void Interpreter::DoInterpretLine( const std::string& line )
736 bbtkDebugMessage("interpreter",6,"==> Interpreter::DoInterpretLine(\""
737 <<line<<"\")"<<std::endl);
739 std::vector<std::string> words;
740 SplitLine(line,words);
745 bbtkDebugDecTab("interpreter",9);
749 // Single line comment : # or //
750 if ( words[0][0]=='#' || (words[0][0]=='/' && words[0][1]=='/') )
752 bbtkDebugDecTab("interpreter",9);
753 bbtkMessage("interpreter",9,"Comment"<<std::endl);
757 // Multi line comment ( /* ... */ ) -delimiters on different lines !-
759 if (words[0][0]=='/' && words[0][1]=='*')
761 bbtkDebugDecTab("interpreter",9);
762 bbtkMessage("interpreter",9,"In multiline comment"<<std::endl);
763 mInsideComment = true;
767 if (words[0][0]=='*' && words[0][1]=='/')
769 bbtkDebugDecTab("interpreter",9);
770 bbtkMessage("interpreter",9,"Out multiline comment"<<std::endl);
771 if ( !mInsideComment ) {
772 bbtkDebugDecTab("interpreter",9);
773 bbtkMessage("interpreter",9,"Comment mismatch : '*/' with no matching '/*'"<<std::endl);
775 mInsideComment = false;
781 bbtkDebugDecTab("interpreter",9);
782 bbtkMessage("interpreter",9,"Multiline Comment"<<std::endl);
787 CommandInfoType command;
788 InterpretCommand(words,command);
790 bbtkDebugMessage("interpreter",9,
791 "Command='"<<command.keyword
792 <<"' code="<<command.code<<std::endl);
794 std::string left,right,left2,right2;
795 std::string filename;
798 if (command.code==cMessage)
802 mVirtualExecuter->HelpMessages();
806 sscanf(words[2].c_str(),"%d",&level);
807 mVirtualExecuter->SetMessageLevel(words[1],level);
813 bbtkMessage("echo",2,line<<std::endl);
816 // break and quit commands
817 if ((command.code==cBreak) || (command.code==cQuit))
819 bool in_script = false;
820 std::string file("");
822 if (mFileName.size())
824 std::ifstream* fs = dynamic_cast<std::ifstream*>(mFile.back());
825 if (fs!=0) in_script = true;
826 file = mFileName.back();
829 if (command.code==cBreak)
832 std::cout << "BreakException("
835 <<line<<")"<<std::endl;
837 bbtkError("break");//,in_script,file,line);
838 // throw BreakException(in_script,file,line);
842 bbtkError("quit");//,in_script,file,line);
843 //throw QuitException(in_script,file,line);
849 switch (command.code)
852 mVirtualExecuter->Create(words[1],words[2]);
856 mVirtualExecuter->Destroy(words[1]);
860 Utilities::SplitAroundFirstDot(words[1],left,right);
861 Utilities::SplitAroundFirstDot(words[2],left2,right2);
862 mVirtualExecuter->Connect(left,right,left2,right2);
866 mVirtualExecuter->BeginPackage(words[1]);
870 mVirtualExecuter->EndPackage();
874 if (mFileName.size()>0)
876 filename = mFileName.back(); //mIncludeFileName.back(); //Utilities::get_file_name(mFileName.back());
880 mVirtualExecuter->Define(words[1],"",filename);
884 mVirtualExecuter->Define(words[1],words[2],filename);
889 mVirtualExecuter->EndDefine();
893 mVirtualExecuter->Kind(words[1]);
897 mVirtualExecuter->Print(words[1]);
901 if (words[1]=="freeze")
903 mVirtualExecuter->SetNoExecMode(true);
906 else if (words[1]=="freeze_no_error")
908 mVirtualExecuter->SetNoExecMode(true);
909 mVirtualExecuter->SetNoErrorMode(true);
912 else if (words[1]=="unfreeze")
914 mVirtualExecuter->SetNoExecMode(false);
915 mVirtualExecuter->SetNoErrorMode(false);
919 mVirtualExecuter->Execute(words[1]);
924 Utilities::SplitAroundFirstDot(words[2],left,right);
925 mVirtualExecuter->DefineInput(words[1],left,right,words[3]);
929 Utilities::SplitAroundFirstDot(words[2],left,right);
930 mVirtualExecuter->DefineOutput(words[1],left,right,words[3]);
934 Utilities::SplitAroundFirstDot(words[1],left,right);
935 mVirtualExecuter->Set(left,right,words[2]);
939 mVirtualExecuter->Author(words[1]);
943 NewGUI(words[1],words[2]);
947 mVirtualExecuter->Category(words[1]);
952 Index("tmp_index.html");
953 else if (words.size()==2)
955 else if (words.size()==3)
956 Index(words[1],words[2]);
960 mVirtualExecuter->Description(words[1]);
981 mVirtualExecuter->Clear();
985 // if 'source' was given (words.size()==3) then tell to set the
986 // source file name of the current complex box with the full file name included
989 InterpretFile(words[1],(words.size()==3));
993 SwitchToFile(words[1],(words.size()==3) );
998 GetExecuter()->LoadPackage(words[1]);
1002 GetExecuter()->UnLoadPackage(words[1]);
1006 if (words.size()==2) Debug(words[1]);
1011 if (words.size() == 2)
1013 if (words[1]=="freeze") mVirtualExecuter->SetNoExecMode(true);
1014 else if (words[1]=="unfreeze") mVirtualExecuter->SetNoExecMode(false);
1018 mVirtualExecuter->SetWorkspaceName(words[2]);
1023 bbtkInternalError("should not reach here !!!");
1026 bbtkDebugMessage("interpreter",6,"<== Interpreter::DoInterpretLine(\""
1027 <<line<<"\")"<<std::endl);
1030 //=======================================================================
1036 //=======================================================================
1037 void Interpreter::SplitLine ( const std::string& str, std::vector<std::string>& tokens)
1039 bbtkDebugMessage("interpreter",9,"==> Interpreter::SplitLine(\""<<str<<"\")"<<std::endl);
1041 std::string delimiters = "\"";
1042 std::vector<std::string> quote;
1043 Utilities::SplitString(str,delimiters,quote);
1046 std::vector<std::string>::iterator i;
1047 for (i=quote.begin(); i!=quote.end(); )
1049 Utilities::SplitString(*i,delimiters,tokens);
1053 // bbtkDebugMessage("interpreter",0,"\""<<*i<<"\""<<std::endl);
1054 tokens.push_back(*i);
1059 for (i=tokens.begin(); i!=tokens.end(); ++i)
1061 bbtkDebugMessage("interpreter",9,"--["<<*i<<"]"<<std::endl);
1063 bbtkDebugMessage("interpreter",9,"<== Interpreter::SplitLine(\""<<str<<"\")"<<std::endl);
1066 //=======================================================================
1069 //=======================================================================
1070 void Interpreter::Reset()
1072 // Cannot close all files if the reset command is read from a file !
1074 mFileNameHistory.clear();
1075 this->mVirtualExecuter->Reset();
1077 //=======================================================================
1079 //=======================================================================
1084 void Interpreter::Print( const std::string& str)
1086 if (mVirtualExecuter->GetNoExecMode()) return;
1088 bbtkDebugMessageInc("interpreter",9,"Interpreter::Print(\""<<str<<"\")"<<std::endl);
1091 // InterpretLine ("load std")
1092 // InterpretLine("new ConcatStrings _C_ ") -> trouver un nom unique : # commande
1093 // InterpretLine("new Print _P_")
1094 // InterpretLine("connect _C_.Out _P_.In")
1098 std::vector<std::string> chains;
1099 std::string delimiters("$");
1101 // Skip delimiters at beginning.
1102 std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
1103 bool is_text = true;
1104 if (lastPos>0) is_text = false;
1106 // Find first delimiter.
1107 std::string::size_type pos = str.find_first_of(delimiters, lastPos);
1109 while (std::string::npos != pos || std::string::npos != lastPos)
1113 // Found a text token, add it to the vector.
1114 chains.push_back(str.substr(lastPos, pos - lastPos));
1115 // std::string token = str.substr(lastPos, pos - lastPos)
1116 // InterpretLine("set _C_.In%num% %token%")
1122 // is an output (between $$) : decode
1123 std::string tok,box,output;
1124 tok = str.substr(lastPos, pos - lastPos);
1125 Utilities::SplitAroundFirstDot(tok,box,output);
1126 chains.push_back( mVirtualExecuter->Get(box,output) );
1128 // InterpretLine("connect %tok% _C_.In%num%")
1131 // Skip delimiters. Note the "not_of"
1132 lastPos = str.find_first_not_of(delimiters, pos);
1133 // Find next delimiter
1134 pos = str.find_first_of(delimiters, lastPos);
1139 // InterpretLine("exec _P_")
1140 // if (IS_IN_WORKSPACE) InterpretLine("delete _C_; delete _P_");
1142 std::vector<std::string>::iterator i;
1143 for (i= chains.begin(); i!=chains.end(); ++i)
1146 Utilities::SubsBackslashN(*i);
1149 std::cout << std::endl;
1150 bbtkDebugDecTab("interpreter",9);
1154 //=======================================================================
1159 // =========================================================================
1160 void Interpreter::SwitchToFile( const std::string& name , bool source )
1162 // Note : in the following :
1163 // name : the user supplied name
1164 // - abreviated name e.g. scr scr.bbs
1165 // - relative full name e.g. ./scr.bbs ../../scr.bbs
1166 // - absolute full name e.g. /home/usrname/proj/dir/scr.bbs
1167 // same for Windows, with c:, d: ...
1169 // use ./directory/subdir/scrname.bbs
1172 bbtkDebugMessage("interpreter",4,"==> Interpreter::SwitchToFile( \""
1173 <<name<<"\")"<<std::endl);
1175 std::vector<std::string> script_paths;
1176 std::string fullPathScriptName; // full path script name
1177 std::string pkgname; // e.g. <scriptname>.bbs
1178 std::vector<std::string> Filenames;
1180 // The following is *NOT* a debug time message :
1181 // It's a user intended message.
1182 // Please don't remove it.
1183 bbtkMessage("interpreter",1,
1184 "look for : [" << name
1185 << "]" << std::endl);
1189 pkgname = Utilities::ExtractScriptName(name,upath);
1191 bbtkMessage("interpreter",3,
1192 "package name:[" << pkgname
1193 << "] path:[" << upath << "]" << std::endl);
1194 bool fullnameGiven = false;
1195 bool foundFile = false;
1197 // ==== "*" provided : load all scripts in given path
1198 // relative (e.g. std/boxes/*) or absolute
1202 std::stringstream* stream = new std::stringstream;
1203 //if (upath.size()!=0) // avoid troubles for "*"
1205 // ==== no path provided : look in root bbs path
1206 if (upath.size()==0)
1208 // bbtkMessage("interpreter",1,
1209 // LG : add all bbs path
1210 // script_paths.push_back( ConfigurationFile::GetInstance().Get_root_bbs_path() );
1211 std::vector<std::string>::const_iterator i;
1212 for (i=ConfigurationFile::GetInstance().Get_bbs_paths().begin();
1213 i!=ConfigurationFile::GetInstance().Get_bbs_paths().end();
1216 script_paths.push_back(*i);
1219 // ==== absolute path provided
1220 else if (upath[0]=='/' || upath[1] == ':' )
1222 if ( Utilities::IsDirectory( upath ) )
1224 script_paths.push_back(upath);
1228 bbtkError("'"<<upath<<"' : directory does not exist");
1231 // ==== relative path provided : search all bbs path appended with
1232 // the relative path provided
1235 std::vector<std::string>::const_iterator i;
1236 for (i=ConfigurationFile::GetInstance().Get_bbs_paths().begin();
1237 i!=ConfigurationFile::GetInstance().Get_bbs_paths().end();
1240 std::string full_path(*i);
1241 // we *really* want '.' to be the current working directory
1242 if (full_path == ".")
1244 char buf[2048]; // for getcwd
1245 char * currentDir = getcwd(buf, 2048);
1246 std::string cwd(currentDir);
1247 full_path = currentDir;
1250 full_path += ConfigurationFile::GetInstance().Get_file_separator();
1253 if ( Utilities::IsDirectory( full_path ) )
1255 script_paths.push_back(full_path);
1258 if (script_paths.empty())
1260 bbtkError("no '"<<upath<<"' subdir found in search paths"
1266 // === search paths list complete : now explore it
1268 // ==== relative name, iterate + load all .bbs/.bbp files
1269 std::vector<std::string>::iterator i;
1270 for (i=script_paths.begin();i!=script_paths.end();i++)
1272 bbtkMessage("interpreter",1,
1273 "--> Looking in '" << *i << "'" << std::endl);
1277 Utilities::Explore(*i, false, Filenames);
1279 for (std::vector<std::string>::iterator j = Filenames.begin();
1280 j!= Filenames.end(); ++j)
1282 int lgr = (*j).size();
1283 if (lgr < 5) continue;
1284 // ignore non .bbp file
1285 if ( (*j).substr(lgr-4, 4) != ".bbp") continue;
1287 (*stream) << "include \"" << *j << "\"\n";
1288 bbtkMessage("interpreter",2," --> Found '" << *j << "'" << std::endl);
1291 } // for (std::vector...
1292 } // for (i=script_...
1297 bbtkMessage("interpreter",1,
1298 " --> No .bbp found"<< std::endl);
1302 bbtkMessage("interpreter",1,
1303 " --> "<<nbBssFiles<<" .bbp found"<< std::endl);
1304 SwitchToStream(stream);
1308 //=============== end pkgname=="*" ===========
1311 // if name starts with a / or a . or contains : user is assumed to have passed a relative/absolute name
1312 // (not only a plain script name)
1313 // we trust him, and try to expland the directory name
1314 // WARNING : starting from current local directory : ./whatYouWant (./ mandatory!)
1316 if (name[0]=='/' || name[1] == ':' || name[0]=='.') // absolute path (linux/windows) or relative path
1319 // ===========================================================check user supplied location
1320 fullnameGiven = true;
1322 fullPathScriptName = Utilities::ExpandLibName(name, false);
1324 // allow user to always forget ".bbs"
1325 int l = fullPathScriptName.size();
1329 if ((fullPathScriptName.substr(l-4, 4) != ".bbs")&&
1330 (fullPathScriptName.substr(l-4, 4) != ".bbp"))
1332 std::string tfullPathScriptName = fullPathScriptName + ".bbs";
1333 if ( Utilities::FileExists(tfullPathScriptName) )
1335 fullPathScriptName = tfullPathScriptName;
1340 tfullPathScriptName = fullPathScriptName + ".bbp";
1341 if ( Utilities::FileExists(tfullPathScriptName) )
1343 fullPathScriptName = tfullPathScriptName;
1350 if ( Utilities::FileExists(fullPathScriptName) )
1358 // =============================== iterate on the paths
1360 script_paths = ConfigurationFile::GetInstance().Get_bbs_paths();
1362 std::vector<std::string>::iterator i;
1363 for (i=script_paths.begin();i!=script_paths.end();++i)
1366 // we *really* want '.' to be the current working directory
1369 char buf[2048]; // for getcwd
1370 char * currentDir = getcwd(buf, 2048);
1371 std::string cwd(currentDir);
1375 std::string tfullPathScriptName = Utilities::MakePkgnameFromPath(path, name, false);
1376 if (tfullPathScriptName.substr(tfullPathScriptName.size()-4, 3)==".bb")
1378 fullPathScriptName = tfullPathScriptName;
1379 if ( ! Utilities::FileExists(fullPathScriptName) )
1381 // The following is *NOT* a debug time message :
1382 // It's a user intended message.
1383 // Please don't remove it.
1384 bbtkMessage("interpreter",2,
1385 " [" <<fullPathScriptName <<"] : does not exist"
1387 continue; // try next path
1389 bbtkMessage("interpreter",2,
1390 " [" <<fullPathScriptName
1391 <<"] : found" <<std::endl);
1393 break; // a script was found; we stop iterating
1397 fullPathScriptName = tfullPathScriptName + ".bbs";
1398 // Check if library exists
1399 if ( ! Utilities::FileExists(fullPathScriptName) )
1401 fullPathScriptName = tfullPathScriptName + ".bbp";
1402 if ( ! Utilities::FileExists(fullPathScriptName) )
1404 // The following is *NOT* a debug time message :
1405 // It's a user intended message.
1406 // Please don't remove it.
1407 bbtkMessage("interpreter",2,
1408 " [" <<tfullPathScriptName <<".bbs/.bbp] : do not exist"
1410 continue; // try next path
1413 bbtkMessage("interpreter",2,
1414 " [" <<fullPathScriptName
1415 <<"] : found" <<std::endl);
1417 break; // a script was found; we stop iterating
1419 } //------------------ // end for ( package_paths.begin();i!=package_paths.end() )
1425 if(fullPathScriptName == "")
1426 bbtkError("Path ["<<upath<<"] doesn't exist");
1428 bbtkError("Script ["<<fullPathScriptName<<"] not found");
1430 bbtkError("No ["<<pkgname<<".bbs/.bbp] script found");
1435 LoadScript(fullPathScriptName,name);
1436 if (source) GetExecuter()->SetCurrentFileName(fullPathScriptName);
1441 //=======================================================================
1444 //=======================================================================
1445 void Interpreter::SwitchToStream( std::stringstream* stream )
1447 bbtkDebugMessage("interpreter",4,"==> Interpreter::SwitchToStream()"
1449 mFile.push_back(stream);
1450 std::ostringstream buffer_name;
1452 buffer_name << "buffer_" ;
1454 if (mFileName.size()>0 )
1456 buffer_name << mFileName.back() << "_" << mLine.back();
1458 mFileName.push_back(buffer_name.str());
1459 mIncludeFileName.push_back(buffer_name.str());
1462 //=======================================================================
1464 //=======================================================================
1466 void Interpreter::LoadScript( std::string fullPathScriptName,
1467 std::string includeScriptName)
1469 bbtkDebugMessage("interpreter",4,"==> Interpreter::LoadScript("
1470 <<fullPathScriptName<<")"
1473 Utilities::replace( fullPathScriptName ,
1474 INVALID_FILE_SEPARATOR , VALID_FILE_SEPARATOR);
1476 if (find(mFileNameHistory.begin(),
1477 mFileNameHistory.end(),
1478 fullPathScriptName)!=mFileNameHistory.end())
1484 s = new std::ifstream;
1485 s->open(fullPathScriptName.c_str());
1488 bbtkError("Could not open file ["<<fullPathScriptName<<"]");
1492 bbtkMessage("interpreter",1," -->[" << fullPathScriptName
1493 << "] found" << std::endl);
1496 mFileName.push_back(fullPathScriptName);
1497 mFileNameHistory.push_back(fullPathScriptName);
1498 mIncludeFileName.push_back(includeScriptName);
1503 //=======================================================================
1505 //=======================================================================
1506 void Interpreter::CloseCurrentFile()
1508 bbtkDebugMessage("interpreter",9,"==> Interpreter::CloseCurrentFile()"
1511 if (mFile.size()==0)
1513 bbtkDebugMessage("interpreter",9," -> no file left open"<<std::endl);
1517 bbtkDebugMessage("interpreter",9," Closing file '"<<mFileName.back()<<"'"<<std::endl);
1519 std::ifstream* file = dynamic_cast<std::ifstream*>(mFile.back());
1520 if (file!=0) file->close();
1522 delete mFile.back();
1524 mFileName.pop_back();
1525 mIncludeFileName.pop_back();
1528 bbtkDebugMessage("interpreter",9," Remains "
1530 <<" open"<<std::endl);
1531 bbtkDebugMessage("interpreter",9,"<== Interpreter::CloseCurrentFile()"
1534 //=======================================================================
1536 //=======================================================================
1537 void Interpreter::CloseAllFiles()
1539 bbtkDebugMessage("interpreter",9,"==> Interpreter::CloseAllFiles()"
1542 while (mFile.size() != 0)
1546 bbtkDebugMessage("interpreter",9,"<== Interpreter::CloseAllFiles()"
1549 //=======================================================================
1553 //=======================================================================
1554 void Interpreter::InterpretCommand( const std::vector<std::string>& words,
1555 CommandInfoType& info )
1557 bbtkDebugMessage("interpreter",9,"==> Interpreter::InterpretCommand(...)"<<std::endl);
1559 // searches the command keyword
1560 CommandDictType::iterator c;
1561 c = mCommandDict.find(words[0]);
1562 if ( c == mCommandDict.end() ) {
1563 bbtkError(words[0]<<" : unknown command");
1566 // tests the number of args
1567 if ( ( ((int)words.size())-1 < c->second.argmin ) ||
1568 ( ((int)words.size())-1 > c->second.argmax ) )
1570 HelpCommand(words[0]);
1571 bbtkError(words[0]<<" : wrong number of arguments");
1576 bbtkDebugMessage("interpreter",9,"<== Interpreter::InterpretCommand(...)"<<std::endl);
1579 //=======================================================================
1582 //=======================================================================
1583 /// Displays help on all the commands
1584 void Interpreter::Help(const std::vector<std::string>& words)
1586 unsigned int nbarg = words.size()-1;
1594 if (words[1]=="packages")
1596 GetExecuter()->GetFactory()->PrintHelpListPackages(true);
1601 HelpCommand(words[1]);
1603 catch (bbtk::Exception e)
1607 GetExecuter()->GetFactory()->PrintHelpPackage(words[1]);
1611 ConfigurationFile::GetInstance().Get_doc_path();
1612 url += "/bbdoc/" + words[1] + "/index.html";
1613 if (Utilities::FileExists(url))
1615 mUser->InterpreterUserViewHtmlPage(url);
1619 catch (bbtk::Exception f)
1623 std::string package;
1624 GetExecuter()->GetFactory()->PrintHelpDescriptor(words[1],
1629 ConfigurationFile::GetInstance().Get_doc_path();
1630 url += "/bbdoc/" + package + "/index.html";
1631 if (Utilities::FileExists(url))
1633 url += "#" + words[1];
1634 mUser->InterpreterUserViewHtmlPage(url);
1638 catch (bbtk::Exception g)
1642 GetExecuter()->PrintHelpBlackBox(words[1],"0","9999");
1644 catch (bbtk::Exception h){
1645 bbtkError("\""<<words[1].c_str()
1646 <<"\" is not a known command, package, black box type or black box name");
1654 if (words[2]=="all")
1656 if ( words[1]=="packages" )
1658 GetExecuter()->GetFactory()->PrintHelpListPackages(true,true);
1663 GetExecuter()->GetFactory()->PrintHelpPackage(words[1],true);
1665 catch (bbtk::Exception f)
1671 HelpCommand(words[0]);
1672 bbtkError(words[0]<<" : syntax error");
1677 bbtkError("Should not reach here !!!");
1680 //=======================================================================
1682 //===================================================================
1683 /// Displays the Configuration
1684 void Interpreter::Config() const
1686 ConfigurationFile::GetInstance().GetHelp(1);
1688 //===================================================================
1690 //=======================================================================
1691 /// Displays help on all the commands
1692 void Interpreter::HelpCommands()
1694 std::cout << "Available commands :" << std::endl;
1695 CommandDictType::iterator i;
1696 for ( i = mCommandDict.begin();
1697 i != mCommandDict.end();
1699 std::cout << " " << i->first << std::endl;
1700 // std::cout << " usage : " << i->second.syntax << std::endl;
1701 // std::cout << " " << i->second.help << std::endl;
1705 //=======================================================================
1708 //=======================================================================
1709 /// Displays help on a particular commands
1710 void Interpreter::HelpCommand(const std::string& s)
1712 CommandDictType::iterator c;
1713 c = mCommandDict.find(s);
1714 if ( c == mCommandDict.end() ) {
1715 bbtkError(s<<" : Unknown command");
1717 // std::cout << " " << s << " : "<< std::endl;
1718 // CommandParamDictType::iterator i;
1719 // for ( i = c->second.begin();
1720 // i != c->second.end();
1722 std::cout << " usage : " << c->second.syntax << std::endl;
1723 std::cout << " " << c->second.help << std::endl;
1726 //=======================================================================
1729 //=======================================================================
1730 /// Fills the vector commands with the commands which
1731 /// have the first n chars of buf for prefix
1732 /// TODO : skip initial spaces in buf and also return the position of first
1733 /// non blank char in buf
1734 void Interpreter::FindCommandsWithPrefix( char* buf,
1736 std::vector<std::string>& commands )
1738 CommandDictType::const_iterator i;
1739 for (i=mCommandDict.begin(); i!=mCommandDict.end(); ++i)
1741 if ((i->first).find(buf,0,n) == 0)
1742 commands.push_back(i->first);
1745 //=======================================================================
1749 //=======================================================================
1750 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1752 inline void PrintChar(char c) { write(STDOUT_FILENO,&c,1); }
1753 inline void BackSpace() { write(STDOUT_FILENO,"\b \b",3); }
1755 // LG : KEYBOARD CODES AS SCANNED ON MY TTY : UNIVERSAL ?
1756 // IF NOT THE USER SHOULD BE ABLE TO CONFIGURE IT
1757 // E.G. STORE THIS IN bbtk_config.xml
1758 #define BBTK_UP_ARROW_KBCODE 0x00415B1B
1759 #define BBTK_DOWN_ARROW_KBCODE 0x00425B1B
1760 #define BBTK_RIGHT_ARROW_KBCODE 0x00435B1B
1761 #define BBTK_LEFT_ARROW_KBCODE 0x00445B1B
1762 #define BBTK_BACKSPACE_KBCODE 0x00000008
1763 #define BBTK_DEL_KBCODE 0x0000007F
1764 #define BBTK_SPACE_KBCODE 0x00000020
1766 //=======================================================================
1767 void Interpreter::GetLineFromPrompt(std::string& s)
1772 unsigned int MAX_LINE_SIZE = 160;
1773 unsigned int MAX_HISTORY_SIZE = 100;
1775 char* newline = new char[MAX_LINE_SIZE];
1776 memset(newline,0,MAX_LINE_SIZE);
1777 char* histline = new char[MAX_LINE_SIZE];
1778 memset(histline,0,MAX_LINE_SIZE);
1780 char* line = newline;
1781 unsigned int hist = mHistory.size();
1787 read ( STDIN_FILENO, &c, 4) ;
1789 bbtkDebugMessage("debug",9,"[0x"<<std::hex<<c<<"]\n");
1791 // Printable character
1792 if ( (ind<MAX_LINE_SIZE-1) &&
1793 ( c >= BBTK_SPACE_KBCODE ) &&
1794 ( c < BBTK_DEL_KBCODE ))
1802 // delete the unused line
1808 // empty lines are not stored in from history
1811 // if history too long : delete oldest command
1812 if (mHistory.size()>MAX_HISTORY_SIZE)
1814 delete mHistory.front();
1815 mHistory.pop_front();
1817 mHistory.push_back(line);
1822 else if ( (ind>0) &&
1823 ((c == BBTK_BACKSPACE_KBCODE) ||
1824 (c == BBTK_DEL_KBCODE)) )
1832 // TODO : Command completion
1833 std::vector<std::string> commands;
1834 FindCommandsWithPrefix( line,ind,commands);
1835 if (commands.size()==1)
1837 std::string com = *commands.begin();
1838 for (; ind<com.size(); ++ind)
1840 PrintChar(com[ind]);
1846 else if (commands.size()>1)
1848 std::vector<std::string>::iterator i;
1850 for (i=commands.begin();i!=commands.end();++i)
1852 write(STDOUT_FILENO,(*i).c_str(),strlen((*i).c_str()));
1855 write(STDOUT_FILENO,"\n> ",3);
1856 //for (int j=0;j<ind;++j)
1858 write(STDOUT_FILENO,line,ind);
1862 // Arrow up : back in history
1863 else if (c==BBTK_UP_ARROW_KBCODE)
1867 // erase current line
1868 while (ind--) BackSpace();
1872 strcpy(histline,mHistory[hist]);
1876 write(STDOUT_FILENO,line,ind);
1879 // Arrow down : down in history
1880 else if (c==BBTK_DOWN_ARROW_KBCODE)
1882 if (hist<mHistory.size()-1)
1884 // erase current line
1885 while (ind--) BackSpace();
1889 strcpy(histline,mHistory[hist]);
1893 write(STDOUT_FILENO,line,ind);
1895 // end of history : switch back to newline
1896 else if (hist==mHistory.size()-1)
1898 // erase current line
1899 while (ind--) BackSpace();
1906 write(STDOUT_FILENO,line,ind);
1910 else if (line[ind]!=0 && c==BBTK_RIGHT_ARROW_KBCODE)
1912 PrintChar(line[ind]);
1917 else if (ind>0 && c==BBTK_LEFT_ARROW_KBCODE)
1925 write(STDOUT_FILENO,"\n\r",2);
1933 //=======================================================================
1934 void Interpreter::GetLineFromPrompt(std::string& s)
1960 //=======================================================================
1966 //=======================================================================
1967 void Interpreter::CommandLineInterpreter()
1969 bbtkDebugMessageInc("interpreter",9,
1970 "Interpreter::CommandLineInterpreter()"<<std::endl);
1972 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1973 // Initialise the tty in non canonical mode with no echo
1974 // oter remembers the previous settings to restore them after
1975 struct termios ter,oter;
1978 ter.c_lflag &= ~ECHO;
1979 ter.c_lflag &= ~ICANON;
1982 tcsetattr(0,TCSANOW,&ter);
1985 mCommandLine = true;
1987 // bool insideComment = false; // for multiline comment
1988 mInsideComment = false;
1994 GetLineFromPrompt(line);
1995 DoInterpretLine(line); //, insideComment);
1998 catch (QuitException e)
2000 bbtkMessage("interpreter",1,"Interpreter : Quit"<<std::endl);
2004 catch (bbtk::Exception e)
2008 catch (std::exception& e)
2010 std::cerr << "* ERROR :: "<<e.what()<<" (not in bbtk)"<<std::endl;
2014 std::cerr << "* UNDEFINED ERROR (not a bbtk nor a std exception)"<<std::endl;
2019 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
2020 tcsetattr(0,TCSANOW,&oter);
2023 std::cout << "Good bye !" << std::endl;
2025 bbtkDebugDecTab("interpreter",9);
2028 //=======================================================================
2029 void Interpreter::Graph(const std::vector<std::string>& words)
2032 bool system_display = true;
2034 if ( ( mUser != 0 ) && ( mUser->InterpreterUserHasOwnHtmlPageViewer() ) )
2035 system_display = false;
2037 if (words.size()==1)
2039 page = mVirtualExecuter->ShowGraph(".","0","0","","","",system_display);
2041 else if (words.size()==2)
2043 page = mVirtualExecuter->ShowGraph(words[1],"0","0","","","",system_display);
2045 else if (words.size()==3)
2047 page = mVirtualExecuter->ShowGraph(words[1],words[2],"0","","","",system_display);
2049 else if (words.size()==4)
2051 page = mVirtualExecuter->ShowGraph(words[1],words[2],words[3],"","","",system_display);
2053 else if (words.size()==5)
2055 page = mVirtualExecuter->ShowGraph(words[1],words[2],words[3],words[4],"","",system_display);
2057 else if (words.size()==6)
2059 page = mVirtualExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],"",system_display);
2061 else if (words.size()==7)
2063 page = mVirtualExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],words[6],system_display);
2066 if ( ( mUser != 0 ) && ( mUser->InterpreterUserHasOwnHtmlPageViewer() ) )
2067 mUser->InterpreterUserViewHtmlPage(page);
2070 //=======================================================================
2073 //=======================================================================
2074 void Interpreter::Index(const std::string& filename,
2075 const std::string& type)
2077 Factory::IndexEntryType t;
2078 if (type=="Initials") t = Factory::Initials;
2079 else if (type=="Categories") t = Factory::Categories;
2080 else if (type=="Packages") t = Factory::Packages;
2081 else if (type=="Adaptors") t = Factory::Adaptors;
2083 GetExecuter()->GetFactory()->CreateHtmlIndex(t,filename);
2085 //=======================================================================
2088 //=======================================================================
2089 void Interpreter::NewGUI(const std::string& boxname,
2090 const std::string& instanceName)
2092 if (mRealExecuter.expired())
2094 bbtkError("command 'newgui' cannot be compiled yet");
2097 std::string typeName = instanceName+"Type";
2098 std::stringstream* s = new std::stringstream;
2099 // create the complex box
2100 (*s) << "define "<<typeName<<std::endl;
2101 // (*s) << " description 'Automatically generated user interface for the box "
2102 // << boxname << "'" <<std::endl;
2103 // create the Layout box
2104 (*s) << " load wx"<<std::endl;
2105 (*s) << " new LayoutLine layout"<<std::endl;
2106 // create the output 'Widget'
2107 (*s) << " output Widget layout.Widget Widget"<<std::endl;
2108 // the box change output
2109 (*s) << " new MultipleInputs change"<<std::endl;
2110 (*s) << " output BoxChange change.Out BoxChange"<<std::endl;
2112 // Browse the inputs of the box in order to find which ones are not
2113 // connected and can be adapted from a widget adaptor
2114 // vector which stores the list of inputs of the box which must be connected
2115 std::vector<std::string> in;
2117 Factory::Pointer F = mVirtualExecuter->GetFactory();
2119 Package::Pointer user = F->GetPackage("user");
2121 ComplexBlackBoxDescriptor::Pointer workspace =
2122 mRealExecuter.lock()->GetCurrentDescriptor();
2127 bbtkError("interpreter::CreateGUI : could not access the executer currently defined complex box");
2132 (ComplexBlackBoxDescriptor::Pointer)(user->GetBlackBoxMap().find("workspace")->second.get());
2135 BlackBox::Pointer box = workspace->GetPrototype()->bbGetBlackBox(boxname);
2136 // BlackBox::InputConnectorMapType incm = box->bbGetInputConnectorMap();
2138 BlackBox::InputConnectorMapType::iterator i;
2139 for (i=box->bbGetInputConnectorMap().begin();
2140 i!=box->bbGetInputConnectorMap().end();
2143 // If the input is connected : continue
2144 if (i->second->IsConnected()) continue;
2145 // Get the input descriptor
2146 const BlackBoxInputDescriptor* d = box->bbGetDescriptor()->GetInputDescriptor(i->first);
2147 // If it is a "system" input : skip it
2148 #ifdef USE_WXWIDGETS
2149 if ( ( d->GetCreatorTypeInfo() == typeid(AtomicBlackBoxDescriptor)) ||
2150 ( d->GetCreatorTypeInfo() == typeid(WxBlackBoxDescriptor)) )
2153 if ( ( d->GetCreatorTypeInfo() == typeid(AtomicBlackBoxDescriptor)) )
2157 std::string widget,adaptor;
2158 // try to find a widget adaptor
2159 if (F->FindWidgetAdaptor(DataInfo(d->GetTypeInfo(),""),
2163 // command to create the adaptor
2164 (*s) << " new "<<adaptor<<" "<<i->first<<std::endl;
2165 // Sets the label of the widget adaptor to the name of the input
2166 (*s) << " set "<<i->first<<".Label "<<i->first<<std::endl;
2167 // Sets the initial value of the widget to the value of the input
2168 (*s) << " set "<<i->first<<".In \" "
2169 <<box->bbGetInputAsString(i->first)<<"\""
2171 // store the input name
2172 in.push_back(i->first);
2173 (*s) << " connect "<<i->first<<".Widget layout.Widget"<<in.size()<<std::endl;
2174 //<i->first<<"'"<<std::endl;
2175 (*s) << " connect "<<i->first<<".BoxChange change.In"<<in.size()<<std::endl;
2177 // try to find a two pieces adaptor
2178 else if (F->FindWidgetAdaptor2(DataInfo(d->GetTypeInfo(),""),
2182 // command to create the widget
2183 (*s) << " new "<<widget<<" "<<i->first<<"Widget"<<std::endl;
2184 // command to create the adaptor
2185 (*s) << " new "<<adaptor<<" "<<i->first<<std::endl;
2187 (*s) << " connect "<<i->first<<"Widget.Out "
2188 <<i->first<<".In"<<std::endl;
2189 // Sets the label of the widget adaptor to the name of the input
2190 (*s) << " set "<<i->first<<"Widget.Label "<<i->first<<std::endl;
2191 // Sets the initial value of the widget to the value of the input
2192 (*s) << " set "<<i->first<<"Widget.In \" "
2193 <<box->bbGetInputAsString(i->first)<<"\""<< std::endl;
2194 // store the input name
2195 in.push_back(i->first);
2196 (*s) << " connect "<<i->first<<"Widget.Widget layout.Widget"<<in.size()<<std::endl;
2197 //<i->first<<"'"<<std::endl;
2198 (*s) << " connect "<<i->first<<"Widget.BoxChange change.In"<<in.size()<<std::endl;
2201 // try to find an adaptor from string
2202 // If found then can create a text input which
2203 // will be automatically adapted
2204 else if (F->FindAdaptor(DataInfo(typeid(std::string),""),
2208 // command to create the adaptor
2209 (*s) << " new InputText "<<i->first<<std::endl;
2210 // Sets the label of the widget adaptor to the name of the input
2211 (*s) << " set "<<i->first<<".Title "<<i->first<<std::endl;
2212 // Sets the initial value of the widget to the value of the input
2213 (*s) << " set "<<i->first<<".In \" "
2214 <<box->bbGetInputAsString(i->first)<<"\""<< std::endl;
2215 // store the input name
2216 in.push_back(i->first);
2217 (*s) << " connect "<<i->first<<".Widget layout.Widget"<<in.size()<<std::endl;
2218 //<i->first<<"'"<<std::endl;
2219 (*s) << " connect "<<i->first<<".BoxChange change.In"<<in.size()<<std::endl;
2228 // command to create the output
2229 (*s) << " output "<<i->first<<" "
2230 <<i->first<<".Out "<<i->first<<std::endl;
2231 // <<" Output of the widget which allows to set "
2235 // Inputs for window properties
2236 (*s) << " input WinTitle layout.WinTitle Title"<<std::endl;
2237 (*s) << " input WinWidth layout.WinWidth Width"<<std::endl;
2238 (*s) << " input WinHeight layout.WinHeight Height"<<std::endl;
2239 (*s) << " input WinDialog layout.WinDialog Dialog"<<std::endl;
2240 (*s) << " input WinHide layout.WinHide Hide"<<std::endl;
2244 // Execute the box executes the layout
2245 (*s) << " exec layout" << std::endl;
2246 (*s) << "endefine" << std::endl;
2247 // (*s) << "help "<< typeName<< std::endl;
2248 // instanciate the box and connect it
2249 (*s) << "new "<<typeName<<" "<<instanceName<<std::endl;
2251 std::vector<std::string>::iterator j;
2252 for (j=in.begin();j!=in.end();++j)
2255 (*s) << "connect "<<instanceName<<"."<<*j<<" "
2256 << boxname<<"."<<*j<<std::endl;
2258 // That's all folks ! now execute the commands :
2261 //=======================================================================
2265 //==========================================================================
2266 void Interpreter::Debug(const std::string& name)
2268 if ((name.length()==2)&&(name[0]=='-'))
2272 bbtk::StaticInitTime::PrintObjectListInfo = true;
2276 // int o = MessageManager::GetMessageLevel("debug");
2277 // if (o<2) MessageManager::SetMessageLevel("debug",2);
2278 mVirtualExecuter->GetFactory()->Check();
2279 // MessageManager::SetMessageLevel("debug",o);
2284 Object:: PrintObjectListInfo(name);
2287 //==========================================================================
2290 //==========================================================================
2291 // Adds a callback when 'break' command issued
2292 void Interpreter::AddBreakObserver( BreakCallbackType c )
2294 mBreakSignal.connect(c);
2296 //==========================================================================
2299 //==========================================================================
2300 std::string Interpreter::GetObjectName() const
2302 return std::string("Interpreter");
2304 //==========================================================================
2306 //==========================================================================
2307 std::string Interpreter::GetObjectInfo() const
2309 std::stringstream i;
2312 //==========================================================================
2314 //==========================================================================
2315 size_t Interpreter::GetObjectSize() const
2317 size_t s = Superclass::GetObjectSize();
2318 s += Interpreter::GetObjectInternalSize();
2321 //==========================================================================
2322 //==========================================================================
2323 size_t Interpreter::GetObjectInternalSize() const
2325 size_t s = sizeof(Interpreter);
2328 //==========================================================================
2329 //==========================================================================
2330 size_t Interpreter::GetObjectRecursiveSize() const
2332 size_t s = Superclass::GetObjectRecursiveSize();
2333 s += Interpreter::GetObjectInternalSize();
2334 s += mVirtualExecuter->GetObjectRecursiveSize();
2337 //==========================================================================