1 /*=========================================================================
3 Module: $RCSfile: bbtkInterpreter.cxx,v $
5 Date: $Date: 2009/05/28 08:12:06 $
6 Version: $Revision: 1.85 $
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()->PrintPackages(true);
1601 HelpCommand(words[1]);
1603 catch (bbtk::Exception e)
1607 GetExecuter()->GetFactory()->HelpPackage(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()->HelpBlackBox(words[1],package);
1628 ConfigurationFile::GetInstance().Get_doc_path();
1629 url += "/bbdoc/" + package + "/index.html";
1630 if (Utilities::FileExists(url))
1632 url += "#" + words[1];
1633 mUser->InterpreterUserViewHtmlPage(url);
1637 catch (bbtk::Exception g)
1641 GetExecuter()->ShowRelations(words[1],"0","9999");
1643 catch (bbtk::Exception h){
1644 bbtkError("\""<<words[1].c_str()
1645 <<"\" is not a known command, package, black box type or black box name");
1653 if (words[2]=="all")
1655 if ( words[1]=="packages" )
1657 GetExecuter()->GetFactory()->PrintPackages(true,true);
1662 GetExecuter()->GetFactory()->HelpPackage(words[1],true);
1664 catch (bbtk::Exception f)
1670 HelpCommand(words[0]);
1671 bbtkError(words[0]<<" : syntax error");
1676 bbtkError("Should not reach here !!!");
1679 //=======================================================================
1681 //===================================================================
1682 /// Displays the Configuration
1683 void Interpreter::Config() const
1685 ConfigurationFile::GetInstance().GetHelp(1);
1687 //===================================================================
1689 //=======================================================================
1690 /// Displays help on all the commands
1691 void Interpreter::HelpCommands()
1693 std::cout << "Available commands :" << std::endl;
1694 CommandDictType::iterator i;
1695 for ( i = mCommandDict.begin();
1696 i != mCommandDict.end();
1698 std::cout << " " << i->first << std::endl;
1699 // std::cout << " usage : " << i->second.syntax << std::endl;
1700 // std::cout << " " << i->second.help << std::endl;
1704 //=======================================================================
1707 //=======================================================================
1708 /// Displays help on a particular commands
1709 void Interpreter::HelpCommand(const std::string& s)
1711 CommandDictType::iterator c;
1712 c = mCommandDict.find(s);
1713 if ( c == mCommandDict.end() ) {
1714 bbtkError(s<<" : Unknown command");
1716 // std::cout << " " << s << " : "<< std::endl;
1717 // CommandParamDictType::iterator i;
1718 // for ( i = c->second.begin();
1719 // i != c->second.end();
1721 std::cout << " usage : " << c->second.syntax << std::endl;
1722 std::cout << " " << c->second.help << std::endl;
1725 //=======================================================================
1728 //=======================================================================
1729 /// Fills the vector commands with the commands which
1730 /// have the first n chars of buf for prefix
1731 /// TODO : skip initial spaces in buf and also return the position of first
1732 /// non blank char in buf
1733 void Interpreter::FindCommandsWithPrefix( char* buf,
1735 std::vector<std::string>& commands )
1737 CommandDictType::const_iterator i;
1738 for (i=mCommandDict.begin(); i!=mCommandDict.end(); ++i)
1740 if ((i->first).find(buf,0,n) == 0)
1741 commands.push_back(i->first);
1744 //=======================================================================
1748 //=======================================================================
1749 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1751 inline void PrintChar(char c) { write(STDOUT_FILENO,&c,1); }
1752 inline void BackSpace() { write(STDOUT_FILENO,"\b \b",3); }
1754 // LG : KEYBOARD CODES AS SCANNED ON MY TTY : UNIVERSAL ?
1755 // IF NOT THE USER SHOULD BE ABLE TO CONFIGURE IT
1756 // E.G. STORE THIS IN bbtk_config.xml
1757 #define BBTK_UP_ARROW_KBCODE 0x00415B1B
1758 #define BBTK_DOWN_ARROW_KBCODE 0x00425B1B
1759 #define BBTK_RIGHT_ARROW_KBCODE 0x00435B1B
1760 #define BBTK_LEFT_ARROW_KBCODE 0x00445B1B
1761 #define BBTK_BACKSPACE_KBCODE 0x00000008
1762 #define BBTK_DEL_KBCODE 0x0000007F
1763 #define BBTK_SPACE_KBCODE 0x00000020
1765 //=======================================================================
1766 void Interpreter::GetLineFromPrompt(std::string& s)
1771 unsigned int MAX_LINE_SIZE = 160;
1772 unsigned int MAX_HISTORY_SIZE = 100;
1774 char* newline = new char[MAX_LINE_SIZE];
1775 memset(newline,0,MAX_LINE_SIZE);
1776 char* histline = new char[MAX_LINE_SIZE];
1777 memset(histline,0,MAX_LINE_SIZE);
1779 char* line = newline;
1780 unsigned int hist = mHistory.size();
1786 read ( STDIN_FILENO, &c, 4) ;
1788 bbtkDebugMessage("debug",9,"[0x"<<std::hex<<c<<"]\n");
1790 // Printable character
1791 if ( (ind<MAX_LINE_SIZE-1) &&
1792 ( c >= BBTK_SPACE_KBCODE ) &&
1793 ( c < BBTK_DEL_KBCODE ))
1801 // delete the unused line
1807 // empty lines are not stored in from history
1810 // if history too long : delete oldest command
1811 if (mHistory.size()>MAX_HISTORY_SIZE)
1813 delete mHistory.front();
1814 mHistory.pop_front();
1816 mHistory.push_back(line);
1821 else if ( (ind>0) &&
1822 ((c == BBTK_BACKSPACE_KBCODE) ||
1823 (c == BBTK_DEL_KBCODE)) )
1831 // TODO : Command completion
1832 std::vector<std::string> commands;
1833 FindCommandsWithPrefix( line,ind,commands);
1834 if (commands.size()==1)
1836 std::string com = *commands.begin();
1837 for (; ind<com.size(); ++ind)
1839 PrintChar(com[ind]);
1845 else if (commands.size()>1)
1847 std::vector<std::string>::iterator i;
1849 for (i=commands.begin();i!=commands.end();++i)
1851 write(STDOUT_FILENO,(*i).c_str(),strlen((*i).c_str()));
1854 write(STDOUT_FILENO,"\n> ",3);
1855 //for (int j=0;j<ind;++j)
1857 write(STDOUT_FILENO,line,ind);
1861 // Arrow up : back in history
1862 else if (c==BBTK_UP_ARROW_KBCODE)
1866 // erase current line
1867 while (ind--) BackSpace();
1871 strcpy(histline,mHistory[hist]);
1875 write(STDOUT_FILENO,line,ind);
1878 // Arrow down : down in history
1879 else if (c==BBTK_DOWN_ARROW_KBCODE)
1881 if (hist<mHistory.size()-1)
1883 // erase current line
1884 while (ind--) BackSpace();
1888 strcpy(histline,mHistory[hist]);
1892 write(STDOUT_FILENO,line,ind);
1894 // end of history : switch back to newline
1895 else if (hist==mHistory.size()-1)
1897 // erase current line
1898 while (ind--) BackSpace();
1905 write(STDOUT_FILENO,line,ind);
1909 else if (line[ind]!=0 && c==BBTK_RIGHT_ARROW_KBCODE)
1911 PrintChar(line[ind]);
1916 else if (ind>0 && c==BBTK_LEFT_ARROW_KBCODE)
1924 write(STDOUT_FILENO,"\n\r",2);
1932 //=======================================================================
1933 void Interpreter::GetLineFromPrompt(std::string& s)
1959 //=======================================================================
1965 //=======================================================================
1966 void Interpreter::CommandLineInterpreter()
1968 bbtkDebugMessageInc("interpreter",9,
1969 "Interpreter::CommandLineInterpreter()"<<std::endl);
1971 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1972 // Initialise the tty in non canonical mode with no echo
1973 // oter remembers the previous settings to restore them after
1974 struct termios ter,oter;
1977 ter.c_lflag &= ~ECHO;
1978 ter.c_lflag &= ~ICANON;
1981 tcsetattr(0,TCSANOW,&ter);
1984 mCommandLine = true;
1986 // bool insideComment = false; // for multiline comment
1987 mInsideComment = false;
1993 GetLineFromPrompt(line);
1994 DoInterpretLine(line); //, insideComment);
1997 catch (QuitException e)
1999 bbtkMessage("interpreter",1,"Interpreter : Quit"<<std::endl);
2003 catch (bbtk::Exception e)
2007 catch (std::exception& e)
2009 std::cerr << "* ERROR :: "<<e.what()<<" (not in bbtk)"<<std::endl;
2013 std::cerr << "* UNDEFINED ERROR (not a bbtk nor a std exception)"<<std::endl;
2018 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
2019 tcsetattr(0,TCSANOW,&oter);
2022 std::cout << "Good bye !" << std::endl;
2024 bbtkDebugDecTab("interpreter",9);
2027 //=======================================================================
2028 void Interpreter::Graph(const std::vector<std::string>& words)
2031 bool system_display = true;
2033 if ( ( mUser != 0 ) && ( mUser->InterpreterUserHasOwnHtmlPageViewer() ) )
2034 system_display = false;
2036 if (words.size()==1)
2038 page = mVirtualExecuter->ShowGraph(".","0","0","","","",system_display);
2040 else if (words.size()==2)
2042 page = mVirtualExecuter->ShowGraph(words[1],"0","0","","","",system_display);
2044 else if (words.size()==3)
2046 page = mVirtualExecuter->ShowGraph(words[1],words[2],"0","","","",system_display);
2048 else if (words.size()==4)
2050 page = mVirtualExecuter->ShowGraph(words[1],words[2],words[3],"","","",system_display);
2052 else if (words.size()==5)
2054 page = mVirtualExecuter->ShowGraph(words[1],words[2],words[3],words[4],"","",system_display);
2056 else if (words.size()==6)
2058 page = mVirtualExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],"",system_display);
2060 else if (words.size()==7)
2062 page = mVirtualExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],words[6],system_display);
2065 if ( ( mUser != 0 ) && ( mUser->InterpreterUserHasOwnHtmlPageViewer() ) )
2066 mUser->InterpreterUserViewHtmlPage(page);
2069 //=======================================================================
2072 //=======================================================================
2073 void Interpreter::Index(const std::string& filename,
2074 const std::string& type)
2076 Factory::IndexEntryType t;
2077 if (type=="Initials") t = Factory::Initials;
2078 else if (type=="Categories") t = Factory::Categories;
2079 else if (type=="Packages") t = Factory::Packages;
2080 else if (type=="Adaptors") t = Factory::Adaptors;
2082 GetExecuter()->GetFactory()->CreateHtmlIndex(t,filename);
2084 //=======================================================================
2087 //=======================================================================
2088 void Interpreter::NewGUI(const std::string& boxname,
2089 const std::string& instanceName)
2091 if (mRealExecuter.expired())
2093 bbtkError("command 'newgui' cannot be compiled yet");
2096 std::string typeName = instanceName+"Type";
2097 std::stringstream* s = new std::stringstream;
2098 // create the complex box
2099 (*s) << "define "<<typeName<<std::endl;
2100 // (*s) << " description 'Automatically generated user interface for the box "
2101 // << boxname << "'" <<std::endl;
2102 // create the Layout box
2103 (*s) << " load wx"<<std::endl;
2104 (*s) << " new LayoutLine layout"<<std::endl;
2105 // create the output 'Widget'
2106 (*s) << " output Widget layout.Widget Widget"<<std::endl;
2107 // the box change output
2108 (*s) << " new MultipleInputs change"<<std::endl;
2109 (*s) << " output BoxChange change.Out BoxChange"<<std::endl;
2111 // Browse the inputs of the box in order to find which ones are not
2112 // connected and can be adapted from a widget adaptor
2113 // vector which stores the list of inputs of the box which must be connected
2114 std::vector<std::string> in;
2116 Factory::Pointer F = mVirtualExecuter->GetFactory();
2118 Package::Pointer user = F->GetPackage("user");
2120 ComplexBlackBoxDescriptor::Pointer workspace =
2121 mRealExecuter.lock()->GetCurrentDescriptor();
2126 bbtkError("interpreter::CreateGUI : could not access the executer currently defined complex box");
2131 (ComplexBlackBoxDescriptor::Pointer)(user->GetBlackBoxMap().find("workspace")->second.get());
2134 BlackBox::Pointer box = workspace->GetPrototype()->bbGetBlackBox(boxname);
2135 // BlackBox::InputConnectorMapType incm = box->bbGetInputConnectorMap();
2137 BlackBox::InputConnectorMapType::iterator i;
2138 for (i=box->bbGetInputConnectorMap().begin();
2139 i!=box->bbGetInputConnectorMap().end();
2142 // If the input is connected : continue
2143 if (i->second->IsConnected()) continue;
2144 // Get the input descriptor
2145 const BlackBoxInputDescriptor* d = box->bbGetDescriptor()->GetInputDescriptor(i->first);
2146 // If it is a "system" input : skip it
2147 #ifdef USE_WXWIDGETS
2148 if ( ( d->GetCreatorTypeInfo() == typeid(AtomicBlackBoxDescriptor)) ||
2149 ( d->GetCreatorTypeInfo() == typeid(WxBlackBoxDescriptor)) )
2152 if ( ( d->GetCreatorTypeInfo() == typeid(AtomicBlackBoxDescriptor)) )
2156 std::string widget,adaptor;
2157 // try to find a widget adaptor
2158 if (F->FindWidgetAdaptor(DataInfo(d->GetTypeInfo(),""),
2162 // command to create the adaptor
2163 (*s) << " new "<<adaptor<<" "<<i->first<<std::endl;
2164 // Sets the label of the widget adaptor to the name of the input
2165 (*s) << " set "<<i->first<<".Label "<<i->first<<std::endl;
2166 // Sets the initial value of the widget to the value of the input
2167 (*s) << " set "<<i->first<<".In \" "
2168 <<box->bbGetInputAsString(i->first)<<"\""
2170 // store the input name
2171 in.push_back(i->first);
2172 (*s) << " connect "<<i->first<<".Widget layout.Widget"<<in.size()<<std::endl;
2173 //<i->first<<"'"<<std::endl;
2174 (*s) << " connect "<<i->first<<".BoxChange change.In"<<in.size()<<std::endl;
2176 // try to find a two pieces adaptor
2177 else if (F->FindWidgetAdaptor2(DataInfo(d->GetTypeInfo(),""),
2181 // command to create the widget
2182 (*s) << " new "<<widget<<" "<<i->first<<"Widget"<<std::endl;
2183 // command to create the adaptor
2184 (*s) << " new "<<adaptor<<" "<<i->first<<std::endl;
2186 (*s) << " connect "<<i->first<<"Widget.Out "
2187 <<i->first<<".In"<<std::endl;
2188 // Sets the label of the widget adaptor to the name of the input
2189 (*s) << " set "<<i->first<<"Widget.Label "<<i->first<<std::endl;
2190 // Sets the initial value of the widget to the value of the input
2191 (*s) << " set "<<i->first<<"Widget.In \" "
2192 <<box->bbGetInputAsString(i->first)<<"\""<< std::endl;
2193 // store the input name
2194 in.push_back(i->first);
2195 (*s) << " connect "<<i->first<<"Widget.Widget layout.Widget"<<in.size()<<std::endl;
2196 //<i->first<<"'"<<std::endl;
2197 (*s) << " connect "<<i->first<<"Widget.BoxChange change.In"<<in.size()<<std::endl;
2200 // try to find an adaptor from string
2201 // If found then can create a text input which
2202 // will be automatically adapted
2203 else if (F->FindAdaptor(DataInfo(typeid(std::string),""),
2207 // command to create the adaptor
2208 (*s) << " new InputText "<<i->first<<std::endl;
2209 // Sets the label of the widget adaptor to the name of the input
2210 (*s) << " set "<<i->first<<".Title "<<i->first<<std::endl;
2211 // Sets the initial value of the widget to the value of the input
2212 (*s) << " set "<<i->first<<".In \" "
2213 <<box->bbGetInputAsString(i->first)<<"\""<< std::endl;
2214 // store the input name
2215 in.push_back(i->first);
2216 (*s) << " connect "<<i->first<<".Widget layout.Widget"<<in.size()<<std::endl;
2217 //<i->first<<"'"<<std::endl;
2218 (*s) << " connect "<<i->first<<".BoxChange change.In"<<in.size()<<std::endl;
2227 // command to create the output
2228 (*s) << " output "<<i->first<<" "
2229 <<i->first<<".Out "<<i->first<<std::endl;
2230 // <<" Output of the widget which allows to set "
2234 // Inputs for window properties
2235 (*s) << " input WinTitle layout.WinTitle Title"<<std::endl;
2236 (*s) << " input WinWidth layout.WinWidth Width"<<std::endl;
2237 (*s) << " input WinHeight layout.WinHeight Height"<<std::endl;
2238 (*s) << " input WinDialog layout.WinDialog Dialog"<<std::endl;
2239 (*s) << " input WinHide layout.WinHide Hide"<<std::endl;
2243 // Execute the box executes the layout
2244 (*s) << " exec layout" << std::endl;
2245 (*s) << "endefine" << std::endl;
2246 // (*s) << "help "<< typeName<< std::endl;
2247 // instanciate the box and connect it
2248 (*s) << "new "<<typeName<<" "<<instanceName<<std::endl;
2250 std::vector<std::string>::iterator j;
2251 for (j=in.begin();j!=in.end();++j)
2254 (*s) << "connect "<<instanceName<<"."<<*j<<" "
2255 << boxname<<"."<<*j<<std::endl;
2257 // That's all folks ! now execute the commands :
2260 //=======================================================================
2264 //==========================================================================
2265 void Interpreter::Debug(const std::string& name)
2267 if ((name.length()==2)&&(name[0]=='-'))
2271 bbtk::StaticInitTime::PrintObjectListInfo = true;
2275 // int o = MessageManager::GetMessageLevel("debug");
2276 // if (o<2) MessageManager::SetMessageLevel("debug",2);
2277 mVirtualExecuter->GetFactory()->CheckPackages();
2278 // MessageManager::SetMessageLevel("debug",o);
2283 Object:: PrintObjectListInfo(name);
2286 //==========================================================================
2289 //==========================================================================
2290 // Adds a callback when 'break' command issued
2291 void Interpreter::AddBreakObserver( BreakCallbackType c )
2293 mBreakSignal.connect(c);
2295 //==========================================================================
2298 //==========================================================================
2299 std::string Interpreter::GetObjectName() const
2301 return std::string("Interpreter");
2303 //==========================================================================
2305 //==========================================================================
2306 std::string Interpreter::GetObjectInfo() const
2308 std::stringstream i;
2311 //==========================================================================
2313 //==========================================================================
2314 size_t Interpreter::GetObjectSize() const
2316 size_t s = Superclass::GetObjectSize();
2317 s += Interpreter::GetObjectInternalSize();
2320 //==========================================================================
2321 //==========================================================================
2322 size_t Interpreter::GetObjectInternalSize() const
2324 size_t s = sizeof(Interpreter);
2327 //==========================================================================
2328 //==========================================================================
2329 size_t Interpreter::GetObjectRecursiveSize() const
2331 size_t s = Superclass::GetObjectRecursiveSize();
2332 s += Interpreter::GetObjectInternalSize();
2333 s += mVirtualExecuter->GetObjectRecursiveSize();
2336 //==========================================================================