1 /*=========================================================================
3 Module: $RCSfile: bbtkInterpreter.cxx,v $
5 Date: $Date: 2009/10/05 22:44:48 $
6 Version: $Revision: 1.87 $
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);
690 //size 0 JCP 21-09-2009
691 int size=str.length();
693 if ( str[ size-1 ]==13 )
699 DoInterpretLine(str);
707 bbtkDebugMessage("interpreter",4,
708 "<== Interpreter::InterpretCurrentStreams()"<<std::endl);
712 //=======================================================================
714 //=======================================================================
715 /// Runs the interpretation of a command
716 Interpreter::ExitStatus Interpreter::InterpretLine( const std::string& line )
718 bbtkDebugMessage("interpreter",5,"==> Interpreter::InterpretLine('"<<line<<"')"<<std::endl);
722 mStatus = Interpreter_OK;
723 mInsideComment = false;
724 //std::cout<<"JCP bbtkInterpreter.cxx Interpreter::InterpretLine("<<std::endl;
725 DoInterpretLine(line );
730 bbtkDebugMessage("interpreter",5,"<== Interpreter::InterpretLine('"<<line<<"')"<<std::endl);
734 //=======================================================================
737 //=======================================================================
738 void Interpreter::DoInterpretLine( const std::string& line )
740 bbtkDebugMessage("interpreter",6,"==> Interpreter::DoInterpretLine(\""
741 <<line<<"\")"<<std::endl);
742 std::vector<std::string> words;
743 SplitLine(line,words);
748 bbtkDebugDecTab("interpreter",9);
752 // Single line comment : # or //
753 if ( words[0][0]=='#' || (words[0][0]=='/' && words[0][1]=='/') )
755 bbtkDebugDecTab("interpreter",9);
756 bbtkMessage("interpreter",9,"Comment"<<std::endl);
760 // Multi line comment ( /* ... */ ) -delimiters on different lines !-
762 if (words[0][0]=='/' && words[0][1]=='*')
764 bbtkDebugDecTab("interpreter",9);
765 bbtkMessage("interpreter",9,"In multiline comment"<<std::endl);
766 mInsideComment = true;
770 if (words[0][0]=='*' && words[0][1]=='/')
772 bbtkDebugDecTab("interpreter",9);
773 bbtkMessage("interpreter",9,"Out multiline comment"<<std::endl);
774 if ( !mInsideComment ) {
775 bbtkDebugDecTab("interpreter",9);
776 bbtkMessage("interpreter",9,"Comment mismatch : '*/' with no matching '/*'"<<std::endl);
778 mInsideComment = false;
784 bbtkDebugDecTab("interpreter",9);
785 bbtkMessage("interpreter",9,"Multiline Comment"<<std::endl);
790 CommandInfoType command;
791 InterpretCommand(words,command);
792 //std::cout<<"JCP bbtkInterpreter command.keyword ="<<command.keyword<<std::endl;
793 bbtkDebugMessage("interpreter",9,
794 "Command='"<<command.keyword
795 <<"' code="<<command.code<<std::endl);
797 std::string left,right,left2,right2;
798 std::string filename;
801 if (command.code==cMessage)
805 mVirtualExecuter->HelpMessages();
809 sscanf(words[2].c_str(),"%d",&level);
810 mVirtualExecuter->SetMessageLevel(words[1],level);
816 bbtkMessage("echo",2,line<<std::endl);
819 // break and quit commands
820 if ((command.code==cBreak) || (command.code==cQuit))
822 bool in_script = false;
823 std::string file("");
826 if (mFileName.size())
828 std::ifstream* fs = dynamic_cast<std::ifstream*>(mFile.back());
829 if (fs!=0) in_script = true;
830 file = mFileName.back();
833 if (command.code==cBreak)
836 std::cout << "BreakException("
839 <<line<<")"<<std::endl;
841 bbtkError("break");//,in_script,file,line);
842 // throw BreakException(in_script,file,line);
846 bbtkError("quit");//,in_script,file,line);
847 //throw QuitException(in_script,file,line);
851 //std::cout<<" mVirtualExecuter->Create(words[1],words[2]); "<<line<<std::endl;
853 switch (command.code)
856 mVirtualExecuter->Create(words[1],words[2]);
860 mVirtualExecuter->Destroy(words[1]);
864 Utilities::SplitAroundFirstDot(words[1],left,right);
865 Utilities::SplitAroundFirstDot(words[2],left2,right2);
866 mVirtualExecuter->Connect(left,right,left2,right2);
870 mVirtualExecuter->BeginPackage(words[1]);
874 mVirtualExecuter->EndPackage();
878 if (mFileName.size()>0)
880 filename = mFileName.back(); //mIncludeFileName.back(); //Utilities::get_file_name(mFileName.back());
884 mVirtualExecuter->Define(words[1],"",filename);
888 mVirtualExecuter->Define(words[1],words[2],filename);
893 mVirtualExecuter->EndDefine();
897 mVirtualExecuter->Kind(words[1]);
901 mVirtualExecuter->Print(words[1]);
905 if (words[1]=="freeze")
907 mVirtualExecuter->SetNoExecMode(true);
910 else if (words[1]=="freeze_no_error")
912 mVirtualExecuter->SetNoExecMode(true);
913 mVirtualExecuter->SetNoErrorMode(true);
916 else if (words[1]=="unfreeze")
918 mVirtualExecuter->SetNoExecMode(false);
919 mVirtualExecuter->SetNoErrorMode(false);
923 mVirtualExecuter->Execute(words[1]);
928 Utilities::SplitAroundFirstDot(words[2],left,right);
929 mVirtualExecuter->DefineInput(words[1],left,right,words[3]);
933 Utilities::SplitAroundFirstDot(words[2],left,right);
934 mVirtualExecuter->DefineOutput(words[1],left,right,words[3]);
938 Utilities::SplitAroundFirstDot(words[1],left,right);
939 mVirtualExecuter->Set(left,right,words[2]);
943 mVirtualExecuter->Author(words[1]);
947 NewGUI(words[1],words[2]);
951 mVirtualExecuter->Category(words[1]);
956 Index("tmp_index.html");
957 else if (words.size()==2)
959 else if (words.size()==3)
960 Index(words[1],words[2]);
964 mVirtualExecuter->Description(words[1]);
985 mVirtualExecuter->Clear();
989 // if 'source' was given (words.size()==3) then tell to set the
990 // source file name of the current complex box with the full file name included
993 InterpretFile(words[1],(words.size()==3));
997 SwitchToFile(words[1],(words.size()==3) );
1002 GetExecuter()->LoadPackage(words[1]);
1006 GetExecuter()->UnLoadPackage(words[1]);
1010 if (words.size()==2) Debug(words[1]);
1015 if (words.size() == 2)
1017 if (words[1]=="freeze") mVirtualExecuter->SetNoExecMode(true);
1018 else if (words[1]=="unfreeze") mVirtualExecuter->SetNoExecMode(false);
1022 mVirtualExecuter->SetWorkspaceName(words[2]);
1027 bbtkInternalError("should not reach here !!!");
1030 bbtkDebugMessage("interpreter",6,"<== Interpreter::DoInterpretLine(\""
1031 <<line<<"\")"<<std::endl);
1034 //=======================================================================
1040 //=======================================================================
1041 void Interpreter::SplitLine ( const std::string& str, std::vector<std::string>& tokens)
1043 bbtkDebugMessage("interpreter",9,"==> Interpreter::SplitLine(\""<<str<<"\")"<<std::endl);
1045 std::string delimiters = "\"";
1046 std::vector<std::string> quote;
1047 Utilities::SplitString(str,delimiters,quote);
1050 std::vector<std::string>::iterator i;
1051 for (i=quote.begin(); i!=quote.end(); )
1053 Utilities::SplitString(*i,delimiters,tokens);
1057 // bbtkDebugMessage("interpreter",0,"\""<<*i<<"\""<<std::endl);
1058 tokens.push_back(*i);
1063 for (i=tokens.begin(); i!=tokens.end(); ++i)
1065 bbtkDebugMessage("interpreter",9,"--["<<*i<<"]"<<std::endl);
1067 bbtkDebugMessage("interpreter",9,"<== Interpreter::SplitLine(\""<<str<<"\")"<<std::endl);
1070 //=======================================================================
1073 //=======================================================================
1074 void Interpreter::Reset()
1076 // Cannot close all files if the reset command is read from a file !
1078 mFileNameHistory.clear();
1079 this->mVirtualExecuter->Reset();
1081 //=======================================================================
1083 //=======================================================================
1088 void Interpreter::Print( const std::string& str)
1090 if (mVirtualExecuter->GetNoExecMode()) return;
1092 bbtkDebugMessageInc("interpreter",9,"Interpreter::Print(\""<<str<<"\")"<<std::endl);
1095 // InterpretLine ("load std")
1096 // InterpretLine("new ConcatStrings _C_ ") -> trouver un nom unique : # commande
1097 // InterpretLine("new Print _P_")
1098 // InterpretLine("connect _C_.Out _P_.In")
1102 std::vector<std::string> chains;
1103 std::string delimiters("$");
1105 // Skip delimiters at beginning.
1106 std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
1107 bool is_text = true;
1108 if (lastPos>0) is_text = false;
1110 // Find first delimiter.
1111 std::string::size_type pos = str.find_first_of(delimiters, lastPos);
1113 while (std::string::npos != pos || std::string::npos != lastPos)
1117 // Found a text token, add it to the vector.
1118 chains.push_back(str.substr(lastPos, pos - lastPos));
1119 // std::string token = str.substr(lastPos, pos - lastPos)
1120 // InterpretLine("set _C_.In%num% %token%")
1126 // is an output (between $$) : decode
1127 std::string tok,box,output;
1128 tok = str.substr(lastPos, pos - lastPos);
1129 Utilities::SplitAroundFirstDot(tok,box,output);
1130 chains.push_back( mVirtualExecuter->Get(box,output) );
1132 // InterpretLine("connect %tok% _C_.In%num%")
1135 // Skip delimiters. Note the "not_of"
1136 lastPos = str.find_first_not_of(delimiters, pos);
1137 // Find next delimiter
1138 pos = str.find_first_of(delimiters, lastPos);
1143 // InterpretLine("exec _P_")
1144 // if (IS_IN_WORKSPACE) InterpretLine("delete _C_; delete _P_");
1146 std::vector<std::string>::iterator i;
1147 for (i= chains.begin(); i!=chains.end(); ++i)
1150 Utilities::SubsBackslashN(*i);
1153 std::cout << std::endl;
1154 bbtkDebugDecTab("interpreter",9);
1158 //=======================================================================
1163 // =========================================================================
1164 void Interpreter::SwitchToFile( const std::string& name , bool source )
1166 // Note : in the following :
1167 // name : the user supplied name
1168 // - abreviated name e.g. scr scr.bbs
1169 // - relative full name e.g. ./scr.bbs ../../scr.bbs
1170 // - absolute full name e.g. /home/usrname/proj/dir/scr.bbs
1171 // same for Windows, with c:, d: ...
1173 // use ./directory/subdir/scrname.bbs
1176 bbtkDebugMessage("interpreter",4,"==> Interpreter::SwitchToFile( \""
1177 <<name<<"\")"<<std::endl);
1179 std::vector<std::string> script_paths;
1180 std::string fullPathScriptName; // full path script name
1181 std::string pkgname; // e.g. <scriptname>.bbs
1182 std::vector<std::string> Filenames;
1184 // The following is *NOT* a debug time message :
1185 // It's a user intended message.
1186 // Please don't remove it.
1187 bbtkMessage("interpreter",1,
1188 "look for : [" << name
1189 << "]" << std::endl);
1193 pkgname = Utilities::ExtractScriptName(name,upath);
1195 bbtkMessage("interpreter",3,
1196 "package name:[" << pkgname
1197 << "] path:[" << upath << "]" << std::endl);
1198 bool fullnameGiven = false;
1199 bool foundFile = false;
1201 // ==== "*" provided : load all scripts in given path
1202 // relative (e.g. std/boxes/*) or absolute
1206 std::stringstream* stream = new std::stringstream;
1207 //if (upath.size()!=0) // avoid troubles for "*"
1209 // ==== no path provided : look in root bbs path
1210 if (upath.size()==0)
1212 // bbtkMessage("interpreter",1,
1213 // LG : add all bbs path
1214 // script_paths.push_back( ConfigurationFile::GetInstance().Get_root_bbs_path() );
1215 std::vector<std::string>::const_iterator i;
1216 for (i=ConfigurationFile::GetInstance().Get_bbs_paths().begin();
1217 i!=ConfigurationFile::GetInstance().Get_bbs_paths().end();
1220 script_paths.push_back(*i);
1223 // ==== absolute path provided
1224 else if (upath[0]=='/' || upath[1] == ':' )
1226 if ( Utilities::IsDirectory( upath ) )
1228 script_paths.push_back(upath);
1232 bbtkError("'"<<upath<<"' : directory does not exist");
1235 // ==== relative path provided : search all bbs path appended with
1236 // the relative path provided
1239 std::vector<std::string>::const_iterator i;
1240 for (i=ConfigurationFile::GetInstance().Get_bbs_paths().begin();
1241 i!=ConfigurationFile::GetInstance().Get_bbs_paths().end();
1244 std::string full_path(*i);
1245 // we *really* want '.' to be the current working directory
1246 if (full_path == ".")
1248 char buf[2048]; // for getcwd
1249 char * currentDir = getcwd(buf, 2048);
1250 std::string cwd(currentDir);
1251 full_path = currentDir;
1254 full_path += ConfigurationFile::GetInstance().Get_file_separator();
1257 if ( Utilities::IsDirectory( full_path ) )
1259 script_paths.push_back(full_path);
1262 if (script_paths.empty())
1264 bbtkError("no '"<<upath<<"' subdir found in search paths"
1270 // === search paths list complete : now explore it
1272 // ==== relative name, iterate + load all .bbs/.bbp files
1273 std::vector<std::string>::iterator i;
1274 for (i=script_paths.begin();i!=script_paths.end();i++)
1276 bbtkMessage("interpreter",1,
1277 "--> Looking in '" << *i << "'" << std::endl);
1281 Utilities::Explore(*i, false, Filenames);
1283 for (std::vector<std::string>::iterator j = Filenames.begin();
1284 j!= Filenames.end(); ++j)
1286 int lgr = (*j).size();
1287 if (lgr < 5) continue;
1288 // ignore non .bbp file
1289 if ( (*j).substr(lgr-4, 4) != ".bbp") continue;
1291 (*stream) << "include \"" << *j << "\"\n";
1292 bbtkMessage("interpreter",2," --> Found '" << *j << "'" << std::endl);
1295 } // for (std::vector...
1296 } // for (i=script_...
1301 bbtkMessage("interpreter",1,
1302 " --> No .bbp found"<< std::endl);
1306 bbtkMessage("interpreter",1,
1307 " --> "<<nbBssFiles<<" .bbp found"<< std::endl);
1308 SwitchToStream(stream);
1312 //=============== end pkgname=="*" ===========
1315 // if name starts with a / or a . or contains : user is assumed to have passed a relative/absolute name
1316 // (not only a plain script name)
1317 // we trust him, and try to expland the directory name
1318 // WARNING : starting from current local directory : ./whatYouWant (./ mandatory!)
1320 if (name[0]=='/' || name[1] == ':' || name[0]=='.') // absolute path (linux/windows) or relative path
1323 // ===========================================================check user supplied location
1324 fullnameGiven = true;
1326 fullPathScriptName = Utilities::ExpandLibName(name, false);
1328 // allow user to always forget ".bbs"
1329 int l = fullPathScriptName.size();
1333 if ((fullPathScriptName.substr(l-4, 4) != ".bbs")&&
1334 (fullPathScriptName.substr(l-4, 4) != ".bbp"))
1336 std::string tfullPathScriptName = fullPathScriptName + ".bbs";
1337 if ( Utilities::FileExists(tfullPathScriptName) )
1339 fullPathScriptName = tfullPathScriptName;
1344 tfullPathScriptName = fullPathScriptName + ".bbp";
1345 if ( Utilities::FileExists(tfullPathScriptName) )
1347 fullPathScriptName = tfullPathScriptName;
1354 if ( Utilities::FileExists(fullPathScriptName) )
1362 // =============================== iterate on the paths
1364 script_paths = ConfigurationFile::GetInstance().Get_bbs_paths();
1366 std::vector<std::string>::iterator i;
1367 for (i=script_paths.begin();i!=script_paths.end();++i)
1370 // we *really* want '.' to be the current working directory
1373 char buf[2048]; // for getcwd
1374 char * currentDir = getcwd(buf, 2048);
1375 std::string cwd(currentDir);
1379 std::string tfullPathScriptName = Utilities::MakePkgnameFromPath(path, name, false);
1380 //Addition JCP tfullPathScriptName.size()>=4
1381 if(tfullPathScriptName.size()>=4){
1382 if (tfullPathScriptName.substr(tfullPathScriptName.size()-4, 3)==".bb")
1384 fullPathScriptName = tfullPathScriptName;
1385 if ( ! Utilities::FileExists(fullPathScriptName) )
1387 // The following is *NOT* a debug time message :
1388 // It's a user intended message.
1389 // Please don't remove it.
1390 bbtkMessage("interpreter",2,
1391 " [" <<fullPathScriptName <<"] : does not exist"
1393 continue; // try next path
1395 bbtkMessage("interpreter",2,
1396 " [" <<fullPathScriptName
1397 <<"] : found" <<std::endl);
1399 break; // a script was found; we stop iterating
1403 fullPathScriptName = tfullPathScriptName + ".bbs";
1404 // Check if library exists
1405 if ( ! Utilities::FileExists(fullPathScriptName) )
1407 fullPathScriptName = tfullPathScriptName + ".bbp";
1408 if ( ! Utilities::FileExists(fullPathScriptName) )
1410 // The following is *NOT* a debug time message :
1411 // It's a user intended message.
1412 // Please don't remove it.
1413 bbtkMessage("interpreter",2,
1414 " [" <<tfullPathScriptName <<".bbs/.bbp] : do not exist"
1416 continue; // try next path
1419 bbtkMessage("interpreter",2,
1420 " [" <<fullPathScriptName
1421 <<"] : found" <<std::endl);
1423 break; // a script was found; we stop iterating
1426 } //------------------ // end for ( package_paths.begin();i!=package_paths.end() )
1432 if(fullPathScriptName == "")
1433 bbtkError("Path ["<<upath<<"] doesn't exist");
1435 bbtkError("Script ["<<fullPathScriptName<<"] not found");
1437 bbtkError("No ["<<pkgname<<".bbs/.bbp] script found");
1442 LoadScript(fullPathScriptName,name);
1443 if (source) GetExecuter()->SetCurrentFileName(fullPathScriptName);
1448 //=======================================================================
1451 //=======================================================================
1452 void Interpreter::SwitchToStream( std::stringstream* stream )
1454 bbtkDebugMessage("interpreter",4,"==> Interpreter::SwitchToStream()"
1456 mFile.push_back(stream);
1457 std::ostringstream buffer_name;
1459 buffer_name << "buffer_" ;
1461 if (mFileName.size()>0 )
1463 buffer_name << mFileName.back() << "_" << mLine.back();
1465 mFileName.push_back(buffer_name.str());
1466 mIncludeFileName.push_back(buffer_name.str());
1469 //=======================================================================
1471 //=======================================================================
1473 void Interpreter::LoadScript( std::string fullPathScriptName,
1474 std::string includeScriptName)
1476 bbtkDebugMessage("interpreter",4,"==> Interpreter::LoadScript("
1477 <<fullPathScriptName<<")"
1480 Utilities::replace( fullPathScriptName ,
1481 INVALID_FILE_SEPARATOR , VALID_FILE_SEPARATOR);
1483 if (find(mFileNameHistory.begin(),
1484 mFileNameHistory.end(),
1485 fullPathScriptName)!=mFileNameHistory.end())
1491 s = new std::ifstream;
1492 s->open(fullPathScriptName.c_str());
1495 bbtkError("Could not open file ["<<fullPathScriptName<<"]");
1499 bbtkMessage("interpreter",1," -->[" << fullPathScriptName
1500 << "] found" << std::endl);
1503 mFileName.push_back(fullPathScriptName);
1504 mFileNameHistory.push_back(fullPathScriptName);
1505 mIncludeFileName.push_back(includeScriptName);
1510 //=======================================================================
1512 //=======================================================================
1513 void Interpreter::CloseCurrentFile()
1515 bbtkDebugMessage("interpreter",9,"==> Interpreter::CloseCurrentFile()"
1518 if (mFile.size()==0)
1520 bbtkDebugMessage("interpreter",9," -> no file left open"<<std::endl);
1524 bbtkDebugMessage("interpreter",9," Closing file '"<<mFileName.back()<<"'"<<std::endl);
1526 std::ifstream* file = dynamic_cast<std::ifstream*>(mFile.back());
1527 if (file!=0) file->close();
1529 delete mFile.back();
1531 mFileName.pop_back();
1532 mIncludeFileName.pop_back();
1535 bbtkDebugMessage("interpreter",9," Remains "
1537 <<" open"<<std::endl);
1538 bbtkDebugMessage("interpreter",9,"<== Interpreter::CloseCurrentFile()"
1541 //=======================================================================
1543 //=======================================================================
1544 void Interpreter::CloseAllFiles()
1546 bbtkDebugMessage("interpreter",9,"==> Interpreter::CloseAllFiles()"
1549 while (mFile.size() != 0)
1553 bbtkDebugMessage("interpreter",9,"<== Interpreter::CloseAllFiles()"
1556 //=======================================================================
1560 //=======================================================================
1561 void Interpreter::InterpretCommand( const std::vector<std::string>& words,
1562 CommandInfoType& info )
1564 bbtkDebugMessage("interpreter",9,"==> Interpreter::InterpretCommand(...)"<<std::endl);
1566 // searches the command keyword
1567 CommandDictType::iterator c;
1568 c = mCommandDict.find(words[0]);
1569 if ( c == mCommandDict.end() ) {
1570 bbtkError(words[0]<<" : unknown command");
1573 // tests the number of args
1574 if ( ( ((int)words.size())-1 < c->second.argmin ) ||
1575 ( ((int)words.size())-1 > c->second.argmax ) )
1577 HelpCommand(words[0]);
1578 bbtkError(words[0]<<" : wrong number of arguments");
1580 //std::cout<<"Interpreter::InterpretCommand( const std::vector<std::string>& words,"<<std::endl;
1583 bbtkDebugMessage("interpreter",9,"<== Interpreter::InterpretCommand(...)"<<std::endl);
1586 //=======================================================================
1589 //=======================================================================
1590 /// Displays help on all the commands
1591 void Interpreter::Help(const std::vector<std::string>& words)
1593 unsigned int nbarg = words.size()-1;
1601 if (words[1]=="packages")
1603 GetExecuter()->GetFactory()->PrintHelpListPackages(true);
1608 HelpCommand(words[1]);
1610 catch (bbtk::Exception e)
1614 GetExecuter()->GetFactory()->PrintHelpPackage(words[1]);
1618 ConfigurationFile::GetInstance().Get_doc_path();
1619 url += "/bbdoc/" + words[1] + "/index.html";
1620 if (Utilities::FileExists(url))
1622 mUser->InterpreterUserViewHtmlPage(url);
1626 catch (bbtk::Exception f)
1630 std::string package;
1631 GetExecuter()->GetFactory()->PrintHelpDescriptor(words[1],
1636 ConfigurationFile::GetInstance().Get_doc_path();
1637 url += "/bbdoc/" + package + "/index.html";
1638 if (Utilities::FileExists(url))
1640 url += "#" + words[1];
1641 mUser->InterpreterUserViewHtmlPage(url);
1645 catch (bbtk::Exception g)
1649 GetExecuter()->PrintHelpBlackBox(words[1],"0","9999");
1651 catch (bbtk::Exception h){
1652 bbtkError("\""<<words[1].c_str()
1653 <<"\" is not a known command, package, black box type or black box name");
1661 if (words[2]=="all")
1663 if ( words[1]=="packages" )
1665 GetExecuter()->GetFactory()->PrintHelpListPackages(true,true);
1670 GetExecuter()->GetFactory()->PrintHelpPackage(words[1],true);
1672 catch (bbtk::Exception f)
1678 HelpCommand(words[0]);
1679 bbtkError(words[0]<<" : syntax error");
1684 bbtkError("Should not reach here !!!");
1687 //=======================================================================
1689 //===================================================================
1690 /// Displays the Configuration
1691 void Interpreter::Config() const
1693 ConfigurationFile::GetInstance().GetHelp(1);
1695 //===================================================================
1697 //=======================================================================
1698 /// Displays help on all the commands
1699 void Interpreter::HelpCommands()
1701 std::cout << "Available commands :" << std::endl;
1702 CommandDictType::iterator i;
1703 for ( i = mCommandDict.begin();
1704 i != mCommandDict.end();
1706 std::cout << " " << i->first << std::endl;
1707 // std::cout << " usage : " << i->second.syntax << std::endl;
1708 // std::cout << " " << i->second.help << std::endl;
1712 //=======================================================================
1715 //=======================================================================
1716 /// Displays help on a particular commands
1717 void Interpreter::HelpCommand(const std::string& s)
1719 CommandDictType::iterator c;
1720 c = mCommandDict.find(s);
1721 if ( c == mCommandDict.end() ) {
1722 bbtkError(s<<" : Unknown command");
1724 // std::cout << " " << s << " : "<< std::endl;
1725 // CommandParamDictType::iterator i;
1726 // for ( i = c->second.begin();
1727 // i != c->second.end();
1729 std::cout << " usage : " << c->second.syntax << std::endl;
1730 std::cout << " " << c->second.help << std::endl;
1733 //=======================================================================
1736 //=======================================================================
1737 /// Fills the vector commands with the commands which
1738 /// have the first n chars of buf for prefix
1739 /// TODO : skip initial spaces in buf and also return the position of first
1740 /// non blank char in buf
1741 void Interpreter::FindCommandsWithPrefix( char* buf,
1743 std::vector<std::string>& commands )
1745 CommandDictType::const_iterator i;
1746 for (i=mCommandDict.begin(); i!=mCommandDict.end(); ++i)
1748 if ((i->first).find(buf,0,n) == 0)
1749 commands.push_back(i->first);
1752 //=======================================================================
1756 //=======================================================================
1757 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1759 inline void PrintChar(char c) { write(STDOUT_FILENO,&c,1); }
1760 inline void BackSpace() { write(STDOUT_FILENO,"\b \b",3); }
1762 // LG : KEYBOARD CODES AS SCANNED ON MY TTY : UNIVERSAL ?
1763 // IF NOT THE USER SHOULD BE ABLE TO CONFIGURE IT
1764 // E.G. STORE THIS IN bbtk_config.xml
1765 #define BBTK_UP_ARROW_KBCODE 0x00415B1B
1766 #define BBTK_DOWN_ARROW_KBCODE 0x00425B1B
1767 #define BBTK_RIGHT_ARROW_KBCODE 0x00435B1B
1768 #define BBTK_LEFT_ARROW_KBCODE 0x00445B1B
1769 #define BBTK_BACKSPACE_KBCODE 0x00000008
1770 #define BBTK_DEL_KBCODE 0x0000007F
1771 #define BBTK_SPACE_KBCODE 0x00000020
1773 //=======================================================================
1774 void Interpreter::GetLineFromPrompt(std::string& s)
1779 unsigned int MAX_LINE_SIZE = 160;
1780 unsigned int MAX_HISTORY_SIZE = 100;
1782 char* newline = new char[MAX_LINE_SIZE];
1783 memset(newline,0,MAX_LINE_SIZE);
1784 char* histline = new char[MAX_LINE_SIZE];
1785 memset(histline,0,MAX_LINE_SIZE);
1787 char* line = newline;
1788 unsigned int hist = mHistory.size();
1794 read ( STDIN_FILENO, &c, 4) ;
1796 bbtkDebugMessage("debug",9,"[0x"<<std::hex<<c<<"]\n");
1798 // Printable character
1799 if ( (ind<MAX_LINE_SIZE-1) &&
1800 ( c >= BBTK_SPACE_KBCODE ) &&
1801 ( c < BBTK_DEL_KBCODE ))
1809 // delete the unused line
1815 // empty lines are not stored in from history
1818 // if history too long : delete oldest command
1819 if (mHistory.size()>MAX_HISTORY_SIZE)
1821 delete mHistory.front();
1822 mHistory.pop_front();
1824 mHistory.push_back(line);
1829 else if ( (ind>0) &&
1830 ((c == BBTK_BACKSPACE_KBCODE) ||
1831 (c == BBTK_DEL_KBCODE)) )
1839 // TODO : Command completion
1840 std::vector<std::string> commands;
1841 FindCommandsWithPrefix( line,ind,commands);
1842 if (commands.size()==1)
1844 std::string com = *commands.begin();
1845 for (; ind<com.size(); ++ind)
1847 PrintChar(com[ind]);
1853 else if (commands.size()>1)
1855 std::vector<std::string>::iterator i;
1857 for (i=commands.begin();i!=commands.end();++i)
1859 write(STDOUT_FILENO,(*i).c_str(),strlen((*i).c_str()));
1862 write(STDOUT_FILENO,"\n> ",3);
1863 //for (int j=0;j<ind;++j)
1865 write(STDOUT_FILENO,line,ind);
1869 // Arrow up : back in history
1870 else if (c==BBTK_UP_ARROW_KBCODE)
1874 // erase current line
1875 while (ind--) BackSpace();
1879 strcpy(histline,mHistory[hist]);
1883 write(STDOUT_FILENO,line,ind);
1886 // Arrow down : down in history
1887 else if (c==BBTK_DOWN_ARROW_KBCODE)
1889 if (hist<mHistory.size()-1)
1891 // erase current line
1892 while (ind--) BackSpace();
1896 strcpy(histline,mHistory[hist]);
1900 write(STDOUT_FILENO,line,ind);
1902 // end of history : switch back to newline
1903 else if (hist==mHistory.size()-1)
1905 // erase current line
1906 while (ind--) BackSpace();
1913 write(STDOUT_FILENO,line,ind);
1917 else if (line[ind]!=0 && c==BBTK_RIGHT_ARROW_KBCODE)
1919 PrintChar(line[ind]);
1924 else if (ind>0 && c==BBTK_LEFT_ARROW_KBCODE)
1932 write(STDOUT_FILENO,"\n\r",2);
1940 //=======================================================================
1941 void Interpreter::GetLineFromPrompt(std::string& s)
1967 //=======================================================================
1973 //=======================================================================
1974 void Interpreter::CommandLineInterpreter()
1976 bbtkDebugMessageInc("interpreter",9,
1977 "Interpreter::CommandLineInterpreter()"<<std::endl);
1979 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1980 // Initialise the tty in non canonical mode with no echo
1981 // oter remembers the previous settings to restore them after
1982 struct termios ter,oter;
1985 ter.c_lflag &= ~ECHO;
1986 ter.c_lflag &= ~ICANON;
1989 tcsetattr(0,TCSANOW,&ter);
1992 mCommandLine = true;
1994 // bool insideComment = false; // for multiline comment
1995 mInsideComment = false;
2001 GetLineFromPrompt(line);
2002 DoInterpretLine(line); //, insideComment);
2005 catch (QuitException e)
2007 bbtkMessage("interpreter",1,"Interpreter : Quit"<<std::endl);
2011 catch (bbtk::Exception e)
2015 catch (std::exception& e)
2017 std::cerr << "* ERROR :: "<<e.what()<<" (not in bbtk)"<<std::endl;
2021 std::cerr << "* UNDEFINED ERROR (not a bbtk nor a std exception)"<<std::endl;
2026 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
2027 tcsetattr(0,TCSANOW,&oter);
2030 std::cout << "Good bye !" << std::endl;
2032 bbtkDebugDecTab("interpreter",9);
2035 //=======================================================================
2036 void Interpreter::Graph(const std::vector<std::string>& words)
2039 bool system_display = true;
2041 if ( ( mUser != 0 ) && ( mUser->InterpreterUserHasOwnHtmlPageViewer() ) )
2042 system_display = false;
2044 if (words.size()==1)
2046 page = mVirtualExecuter->ShowGraph(".","0","0","","","",system_display);
2048 else if (words.size()==2)
2050 page = mVirtualExecuter->ShowGraph(words[1],"0","0","","","",system_display);
2052 else if (words.size()==3)
2054 page = mVirtualExecuter->ShowGraph(words[1],words[2],"0","","","",system_display);
2056 else if (words.size()==4)
2058 page = mVirtualExecuter->ShowGraph(words[1],words[2],words[3],"","","",system_display);
2060 else if (words.size()==5)
2062 page = mVirtualExecuter->ShowGraph(words[1],words[2],words[3],words[4],"","",system_display);
2064 else if (words.size()==6)
2066 page = mVirtualExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],"",system_display);
2068 else if (words.size()==7)
2070 page = mVirtualExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],words[6],system_display);
2073 if ( ( mUser != 0 ) && ( mUser->InterpreterUserHasOwnHtmlPageViewer() ) )
2074 mUser->InterpreterUserViewHtmlPage(page);
2077 //=======================================================================
2080 //=======================================================================
2081 void Interpreter::Index(const std::string& filename,
2082 const std::string& type)
2084 Factory::IndexEntryType t;
2085 if (type=="Initials") t = Factory::Initials;
2086 else if (type=="Categories") t = Factory::Categories;
2087 else if (type=="Packages") t = Factory::Packages;
2088 else if (type=="Adaptors") t = Factory::Adaptors;
2090 GetExecuter()->GetFactory()->CreateHtmlIndex(t,filename);
2092 //=======================================================================
2095 //=======================================================================
2096 void Interpreter::NewGUI(const std::string& boxname,
2097 const std::string& instanceName)
2099 if (mRealExecuter.expired())
2101 bbtkError("command 'newgui' cannot be compiled yet");
2104 std::string typeName = instanceName+"Type";
2105 std::stringstream* s = new std::stringstream;
2106 // create the complex box
2107 (*s) << "define "<<typeName<<std::endl;
2108 // (*s) << " description 'Automatically generated user interface for the box "
2109 // << boxname << "'" <<std::endl;
2110 // create the Layout box
2111 (*s) << " load wx"<<std::endl;
2112 (*s) << " new LayoutLine layout"<<std::endl;
2113 // create the output 'Widget'
2114 (*s) << " output Widget layout.Widget Widget"<<std::endl;
2115 // the box change output
2116 (*s) << " new MultipleInputs change"<<std::endl;
2117 (*s) << " output BoxChange change.Out BoxChange"<<std::endl;
2119 // Browse the inputs of the box in order to find which ones are not
2120 // connected and can be adapted from a widget adaptor
2121 // vector which stores the list of inputs of the box which must be connected
2122 std::vector<std::string> in;
2124 Factory::Pointer F = mVirtualExecuter->GetFactory();
2126 Package::Pointer user = F->GetPackage("user");
2128 ComplexBlackBoxDescriptor::Pointer workspace =
2129 mRealExecuter.lock()->GetCurrentDescriptor();
2134 bbtkError("interpreter::CreateGUI : could not access the executer currently defined complex box");
2139 (ComplexBlackBoxDescriptor::Pointer)(user->GetBlackBoxMap().find("workspace")->second.get());
2142 BlackBox::Pointer box = workspace->GetPrototype()->bbGetBlackBox(boxname);
2143 // BlackBox::InputConnectorMapType incm = box->bbGetInputConnectorMap();
2145 BlackBox::InputConnectorMapType::iterator i;
2146 for (i=box->bbGetInputConnectorMap().begin();
2147 i!=box->bbGetInputConnectorMap().end();
2150 // If the input is connected : continue
2151 if (i->second->IsConnected()) continue;
2152 // Get the input descriptor
2153 const BlackBoxInputDescriptor* d = box->bbGetDescriptor()->GetInputDescriptor(i->first);
2154 // If it is a "system" input : skip it
2155 #ifdef USE_WXWIDGETS
2156 if ( ( d->GetCreatorTypeInfo() == typeid(AtomicBlackBoxDescriptor)) ||
2157 ( d->GetCreatorTypeInfo() == typeid(WxBlackBoxDescriptor)) )
2160 if ( ( d->GetCreatorTypeInfo() == typeid(AtomicBlackBoxDescriptor)) )
2164 std::string widget,adaptor;
2165 // try to find a widget adaptor
2166 if (F->FindWidgetAdaptor(DataInfo(d->GetTypeInfo(),""),
2170 // command to create the adaptor
2171 (*s) << " new "<<adaptor<<" "<<i->first<<std::endl;
2172 // Sets the label of the widget adaptor to the name of the input
2173 (*s) << " set "<<i->first<<".Label "<<i->first<<std::endl;
2174 // Sets the initial value of the widget to the value of the input
2175 (*s) << " set "<<i->first<<".In \" "
2176 <<box->bbGetInputAsString(i->first)<<"\""
2178 // store the input name
2179 in.push_back(i->first);
2180 (*s) << " connect "<<i->first<<".Widget layout.Widget"<<in.size()<<std::endl;
2181 //<i->first<<"'"<<std::endl;
2182 (*s) << " connect "<<i->first<<".BoxChange change.In"<<in.size()<<std::endl;
2184 // try to find a two pieces adaptor
2185 else if (F->FindWidgetAdaptor2(DataInfo(d->GetTypeInfo(),""),
2189 // command to create the widget
2190 (*s) << " new "<<widget<<" "<<i->first<<"Widget"<<std::endl;
2191 // command to create the adaptor
2192 (*s) << " new "<<adaptor<<" "<<i->first<<std::endl;
2194 (*s) << " connect "<<i->first<<"Widget.Out "
2195 <<i->first<<".In"<<std::endl;
2196 // Sets the label of the widget adaptor to the name of the input
2197 (*s) << " set "<<i->first<<"Widget.Label "<<i->first<<std::endl;
2198 // Sets the initial value of the widget to the value of the input
2199 (*s) << " set "<<i->first<<"Widget.In \" "
2200 <<box->bbGetInputAsString(i->first)<<"\""<< std::endl;
2201 // store the input name
2202 in.push_back(i->first);
2203 (*s) << " connect "<<i->first<<"Widget.Widget layout.Widget"<<in.size()<<std::endl;
2204 //<i->first<<"'"<<std::endl;
2205 (*s) << " connect "<<i->first<<"Widget.BoxChange change.In"<<in.size()<<std::endl;
2208 // try to find an adaptor from string
2209 // If found then can create a text input which
2210 // will be automatically adapted
2211 else if (F->FindAdaptor(DataInfo(typeid(std::string),""),
2215 // command to create the adaptor
2216 (*s) << " new InputText "<<i->first<<std::endl;
2217 // Sets the label of the widget adaptor to the name of the input
2218 (*s) << " set "<<i->first<<".Title "<<i->first<<std::endl;
2219 // Sets the initial value of the widget to the value of the input
2220 (*s) << " set "<<i->first<<".In \" "
2221 <<box->bbGetInputAsString(i->first)<<"\""<< std::endl;
2222 // store the input name
2223 in.push_back(i->first);
2224 (*s) << " connect "<<i->first<<".Widget layout.Widget"<<in.size()<<std::endl;
2225 //<i->first<<"'"<<std::endl;
2226 (*s) << " connect "<<i->first<<".BoxChange change.In"<<in.size()<<std::endl;
2235 // command to create the output
2236 (*s) << " output "<<i->first<<" "
2237 <<i->first<<".Out "<<i->first<<std::endl;
2238 // <<" Output of the widget which allows to set "
2242 // Inputs for window properties
2243 (*s) << " input WinTitle layout.WinTitle Title"<<std::endl;
2244 (*s) << " input WinWidth layout.WinWidth Width"<<std::endl;
2245 (*s) << " input WinHeight layout.WinHeight Height"<<std::endl;
2246 (*s) << " input WinDialog layout.WinDialog Dialog"<<std::endl;
2247 (*s) << " input WinHide layout.WinHide Hide"<<std::endl;
2251 // Execute the box executes the layout
2252 (*s) << " exec layout" << std::endl;
2253 (*s) << "endefine" << std::endl;
2254 // (*s) << "help "<< typeName<< std::endl;
2255 // instanciate the box and connect it
2256 (*s) << "new "<<typeName<<" "<<instanceName<<std::endl;
2258 std::vector<std::string>::iterator j;
2259 for (j=in.begin();j!=in.end();++j)
2262 (*s) << "connect "<<instanceName<<"."<<*j<<" "
2263 << boxname<<"."<<*j<<std::endl;
2265 // That's all folks ! now execute the commands :
2268 //=======================================================================
2272 //==========================================================================
2273 void Interpreter::Debug(const std::string& name)
2275 if ((name.length()==2)&&(name[0]=='-'))
2279 bbtk::StaticInitTime::PrintObjectListInfo = true;
2283 // int o = MessageManager::GetMessageLevel("debug");
2284 // if (o<2) MessageManager::SetMessageLevel("debug",2);
2285 mVirtualExecuter->GetFactory()->Check();
2286 // MessageManager::SetMessageLevel("debug",o);
2291 Object:: PrintObjectListInfo(name);
2294 //==========================================================================
2297 //==========================================================================
2298 // Adds a callback when 'break' command issued
2299 void Interpreter::AddBreakObserver( BreakCallbackType c )
2301 mBreakSignal.connect(c);
2303 //==========================================================================
2306 //==========================================================================
2307 std::string Interpreter::GetObjectName() const
2309 return std::string("Interpreter");
2311 //==========================================================================
2313 //==========================================================================
2314 std::string Interpreter::GetObjectInfo() const
2316 std::stringstream i;
2319 //==========================================================================
2321 //==========================================================================
2322 size_t Interpreter::GetObjectSize() const
2324 size_t s = Superclass::GetObjectSize();
2325 s += Interpreter::GetObjectInternalSize();
2328 //==========================================================================
2329 //==========================================================================
2330 size_t Interpreter::GetObjectInternalSize() const
2332 size_t s = sizeof(Interpreter);
2335 //==========================================================================
2336 //==========================================================================
2337 size_t Interpreter::GetObjectRecursiveSize() const
2339 size_t s = Superclass::GetObjectRecursiveSize();
2340 s += Interpreter::GetObjectInternalSize();
2341 s += mVirtualExecuter->GetObjectRecursiveSize();
2344 //==========================================================================