1 /*=========================================================================
3 Module: $RCSfile: bbtkInterpreter.cxx,v $
5 Date: $Date: 2010/09/14 07:18:46 $
6 Version: $Revision: 1.88 $
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 //=======================================================================
736 void Interpreter::commandNew(std::string boxType, std::string boxName)
738 mVirtualExecuter->Create(boxType,boxName);
741 void Interpreter::commandDelete(std::string boxName)
743 mVirtualExecuter->Destroy(boxName);
746 void Interpreter::commandConnection(std::string nodeFrom, std::string outputLabel, std::string nodeTo, std::string inputLabel)
748 mVirtualExecuter->Connect(nodeFrom,outputLabel,nodeTo,inputLabel);
751 void Interpreter::commandPackage(std::string packageName)
753 mVirtualExecuter->BeginPackage(packageName);
756 void Interpreter::commandEndPackage()
758 mVirtualExecuter->EndPackage();
761 void Interpreter::commandDefine(std::string name, std::string pack, std::string scriptfilename)
763 mVirtualExecuter->Define(name,pack,scriptfilename);
766 void Interpreter::commandEndDefine()
768 mVirtualExecuter->EndDefine();
771 void Interpreter::commandKind(std::string kind)
773 mVirtualExecuter->Kind(kind);
776 void Interpreter::commandPrint(std::string value)
778 mVirtualExecuter->Print(value);
782 void Interpreter::commandExec(std::string word)
786 mVirtualExecuter->SetNoExecMode(true);
789 else if (word=="freeze_no_error")
791 mVirtualExecuter->SetNoExecMode(true);
792 mVirtualExecuter->SetNoErrorMode(true);
795 else if (word=="unfreeze")
797 mVirtualExecuter->SetNoExecMode(false);
798 mVirtualExecuter->SetNoErrorMode(false);
802 mVirtualExecuter->Execute(word);
807 void Interpreter::commandInput(std::string name, std::string box, std::string input,std::string help)
809 mVirtualExecuter->DefineInput(name,box,input,help);
812 void Interpreter::commandOutput(std::string name, std::string box, std::string output,std::string help)
814 mVirtualExecuter->DefineOutput(name,box,output,help);
817 void Interpreter::commandSet(std::string box, std::string input, std::string value)
819 mVirtualExecuter->Set(box,input,value);
822 void Interpreter::commandAuthor(std::string author)
824 mVirtualExecuter->Author(author);
827 void Interpreter::commandCategory(std::string categorytype)
829 mVirtualExecuter->Category(categorytype);
834 void Interpreter::commandDescription(std::string description)
836 mVirtualExecuter->Description(description);
840 void Interpreter::commandClear()
842 mVirtualExecuter->Clear();
845 void Interpreter::commandInclude(std::string word, bool ok)
847 // if 'source' was given (words.size()==3) then tell to set the
848 // source file name of the current complex box with the full file name included
851 InterpretFile(word, ok );
855 SwitchToFile(word , ok );
860 void Interpreter::commandLoad(std::string packageName)
862 GetExecuter()->LoadPackage(packageName);
865 void Interpreter::commandUnload(std::string packageName)
867 GetExecuter()->UnLoadPackage(packageName);
873 //=======================================================================
874 void Interpreter::DoInterpretLine( const std::string& line )
876 bbtkDebugMessage("interpreter",6,"==> Interpreter::DoInterpretLine(\""
877 <<line<<"\")"<<std::endl);
878 std::vector<std::string> words;
879 SplitLine(line,words);
884 bbtkDebugDecTab("interpreter",9);
888 // Single line comment : # or //
889 if ( words[0][0]=='#' || (words[0][0]=='/' && words[0][1]=='/') )
891 bbtkDebugDecTab("interpreter",9);
892 bbtkMessage("interpreter",9,"Comment"<<std::endl);
896 // Multi line comment ( /* ... */ ) -delimiters on different lines !-
898 if (words[0][0]=='/' && words[0][1]=='*')
900 bbtkDebugDecTab("interpreter",9);
901 bbtkMessage("interpreter",9,"In multiline comment"<<std::endl);
902 mInsideComment = true;
906 if (words[0][0]=='*' && words[0][1]=='/')
908 bbtkDebugDecTab("interpreter",9);
909 bbtkMessage("interpreter",9,"Out multiline comment"<<std::endl);
910 if ( !mInsideComment ) {
911 bbtkDebugDecTab("interpreter",9);
912 bbtkMessage("interpreter",9,"Comment mismatch : '*/' with no matching '/*'"<<std::endl);
914 mInsideComment = false;
920 bbtkDebugDecTab("interpreter",9);
921 bbtkMessage("interpreter",9,"Multiline Comment"<<std::endl);
926 CommandInfoType command;
927 InterpretCommand(words,command);
928 //std::cout<<"JCP bbtkInterpreter command.keyword ="<<command.keyword<<std::endl;
929 bbtkDebugMessage("interpreter",9,
930 "Command='"<<command.keyword
931 <<"' code="<<command.code<<std::endl);
933 std::string left,right,left2,right2;
934 std::string filename;
937 if (command.code==cMessage)
941 mVirtualExecuter->HelpMessages();
945 sscanf(words[2].c_str(),"%d",&level);
946 mVirtualExecuter->SetMessageLevel(words[1],level);
952 bbtkMessage("echo",2,line<<std::endl);
955 // break and quit commands
956 if ((command.code==cBreak) || (command.code==cQuit))
958 bool in_script = false;
959 std::string file("");
962 if (mFileName.size())
964 std::ifstream* fs = dynamic_cast<std::ifstream*>(mFile.back());
965 if (fs!=0) in_script = true;
966 file = mFileName.back();
969 if (command.code==cBreak)
972 std::cout << "BreakException("
975 <<line<<")"<<std::endl;
977 bbtkError("break");//,in_script,file,line);
978 // throw BreakException(in_script,file,line);
982 bbtkError("quit");//,in_script,file,line);
983 //throw QuitException(in_script,file,line);
987 //std::cout<<" mVirtualExecuter->Create(words[1],words[2]); "<<line<<std::endl;
990 switch (command.code)
993 commandNew(words[1],words[2]);
994 //EED Borrame mVirtualExecuter->Create(words[1],words[2]);
998 commandDelete(words[1]);
999 //EED Borrame mVirtualExecuter->Destroy(words[1]);
1003 Utilities::SplitAroundFirstDot(words[1],left,right);
1004 Utilities::SplitAroundFirstDot(words[2],left2,right2);
1005 commandConnection(left,right,left2,right2);
1006 //EED Borrame mVirtualExecuter->Connect(left,right,left2,right2);
1010 commandPackage(words[1]);
1011 //EED Borrame mVirtualExecuter->BeginPackage(words[1]);
1015 commandEndPackage();
1016 //EED Borrame mVirtualExecuter->EndPackage();
1020 if (mFileName.size()>0)
1022 //??? commandDefine(????);
1023 filename = mFileName.back(); //mIncludeFileName.back(); //Utilities::get_file_name(mFileName.back());
1025 if (words.size()==2)
1027 commandDefine(words[1],"",filename);
1028 //EED Borrame mVirtualExecuter->Define(words[1],"",filename);
1032 commandDefine(words[1],words[2],filename);
1033 //EED Borrame mVirtualExecuter->Define(words[1],words[2],filename);
1039 //EED Borrame mVirtualExecuter->EndDefine();
1043 commandKind(words[1]);
1044 //EED Borrame mVirtualExecuter->Kind(words[1]);
1048 commandPrint(words[1]);
1049 //EED Borrame mVirtualExecuter->Print(words[1]);
1053 commandExec(words[1]);
1054 //EED Borrame if (words[1]=="freeze")
1056 //EED Borrame mVirtualExecuter->SetNoExecMode(true);
1057 //EED Borrame mThrow = false;
1059 //EED Borrame else if (words[1]=="freeze_no_error")
1061 //EED Borrame mVirtualExecuter->SetNoExecMode(true);
1062 //EED Borrame mVirtualExecuter->SetNoErrorMode(true);
1063 //EED Borrame mThrow = false;
1065 //EED Borrame else if (words[1]=="unfreeze")
1067 //EED Borrame mVirtualExecuter->SetNoExecMode(false);
1068 //EED Borrame mVirtualExecuter->SetNoErrorMode(false);
1072 //EED Borrame mVirtualExecuter->Execute(words[1]);
1078 Utilities::SplitAroundFirstDot(words[2],left,right);
1079 commandInput(words[1],left,right,words[3]);
1080 //EED Borrame mVirtualExecuter->DefineInput(words[1],left,right,words[3]);
1084 Utilities::SplitAroundFirstDot(words[2],left,right);
1085 commandOutput(words[1],left,right,words[3]);
1086 //EED Borrame mVirtualExecuter->DefineOutput(words[1],left,right,words[3]);
1090 Utilities::SplitAroundFirstDot(words[1],left,right);
1091 commandSet(left,right,words[1]);
1092 //EED Borrame mVirtualExecuter->Set(left,right,words[2]);
1096 commandAuthor(words[1]);
1097 //EED Borrame mVirtualExecuter->Author(words[1]);
1101 NewGUI(words[1],words[2]);
1105 commandCategory(words[1]);
1106 //EED Borrame mVirtualExecuter->Category(words[1]);
1110 if (words.size()==1)
1111 Index("tmp_index.html");
1112 else if (words.size()==2)
1114 else if (words.size()==3)
1115 Index(words[1],words[2]);
1119 commandDescription(words[1]);
1120 //EED Borrame mVirtualExecuter->Description(words[1]);
1142 //EED Borrame mVirtualExecuter->Clear();
1146 commandInclude( words[1] , (words.size()==3) );
1147 //EED Borrame // if 'source' was given (words.size()==3) then tell to set the
1148 //EED Borrame // source file name of the current complex box with the full file name included
1149 //EED Borrame if (mCommandLine)
1151 //EED Borrame InterpretFile(words[1],(words.size()==3));
1152 //EED Borrame } else{
1153 //EED Borrame SwitchToFile(words[1],(words.size()==3) );
1158 commandLoad( words[1] );
1159 //EED Borrame GetExecuter()->LoadPackage(words[1]);
1163 commandUnload( words[1] );
1164 //EED Borrame GetExecuter()->UnLoadPackage(words[1]);
1169 if (words.size()==2) Debug(words[1]);
1175 if (words.size() == 2)
1177 if (words[1]=="freeze") mVirtualExecuter->SetNoExecMode(true);
1178 else if (words[1]=="unfreeze") mVirtualExecuter->SetNoExecMode(false);
1182 mVirtualExecuter->SetWorkspaceName(words[2]);
1187 bbtkInternalError("should not reach here !!!");
1190 bbtkDebugMessage("interpreter",6,"<== Interpreter::DoInterpretLine(\""
1191 <<line<<"\")"<<std::endl);
1194 //=======================================================================
1200 //=======================================================================
1201 void Interpreter::SplitLine ( const std::string& str, std::vector<std::string>& tokens)
1203 bbtkDebugMessage("interpreter",9,"==> Interpreter::SplitLine(\""<<str<<"\")"<<std::endl);
1205 std::string delimiters = "\"";
1206 std::vector<std::string> quote;
1207 Utilities::SplitString(str,delimiters,quote);
1210 std::vector<std::string>::iterator i;
1211 for (i=quote.begin(); i!=quote.end(); )
1213 Utilities::SplitString(*i,delimiters,tokens);
1217 // bbtkDebugMessage("interpreter",0,"\""<<*i<<"\""<<std::endl);
1218 tokens.push_back(*i);
1223 for (i=tokens.begin(); i!=tokens.end(); ++i)
1225 bbtkDebugMessage("interpreter",9,"--["<<*i<<"]"<<std::endl);
1227 bbtkDebugMessage("interpreter",9,"<== Interpreter::SplitLine(\""<<str<<"\")"<<std::endl);
1230 //=======================================================================
1233 //=======================================================================
1234 void Interpreter::Reset()
1236 // Cannot close all files if the reset command is read from a file !
1238 mFileNameHistory.clear();
1239 this->mVirtualExecuter->Reset();
1241 //=======================================================================
1243 //=======================================================================
1248 void Interpreter::Print( const std::string& str)
1250 if (mVirtualExecuter->GetNoExecMode()) return;
1252 bbtkDebugMessageInc("interpreter",9,"Interpreter::Print(\""<<str<<"\")"<<std::endl);
1255 // InterpretLine ("load std")
1256 // InterpretLine("new ConcatStrings _C_ ") -> trouver un nom unique : # commande
1257 // InterpretLine("new Print _P_")
1258 // InterpretLine("connect _C_.Out _P_.In")
1262 std::vector<std::string> chains;
1263 std::string delimiters("$");
1265 // Skip delimiters at beginning.
1266 std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
1267 bool is_text = true;
1268 if (lastPos>0) is_text = false;
1270 // Find first delimiter.
1271 std::string::size_type pos = str.find_first_of(delimiters, lastPos);
1273 while (std::string::npos != pos || std::string::npos != lastPos)
1277 // Found a text token, add it to the vector.
1278 chains.push_back(str.substr(lastPos, pos - lastPos));
1279 // std::string token = str.substr(lastPos, pos - lastPos)
1280 // InterpretLine("set _C_.In%num% %token%")
1286 // is an output (between $$) : decode
1287 std::string tok,box,output;
1288 tok = str.substr(lastPos, pos - lastPos);
1289 Utilities::SplitAroundFirstDot(tok,box,output);
1290 chains.push_back( mVirtualExecuter->Get(box,output) );
1292 // InterpretLine("connect %tok% _C_.In%num%")
1295 // Skip delimiters. Note the "not_of"
1296 lastPos = str.find_first_not_of(delimiters, pos);
1297 // Find next delimiter
1298 pos = str.find_first_of(delimiters, lastPos);
1303 // InterpretLine("exec _P_")
1304 // if (IS_IN_WORKSPACE) InterpretLine("delete _C_; delete _P_");
1306 std::vector<std::string>::iterator i;
1307 for (i= chains.begin(); i!=chains.end(); ++i)
1310 Utilities::SubsBackslashN(*i);
1313 std::cout << std::endl;
1314 bbtkDebugDecTab("interpreter",9);
1318 //=======================================================================
1323 // =========================================================================
1324 void Interpreter::SwitchToFile( const std::string& name , bool source )
1326 // Note : in the following :
1327 // name : the user supplied name
1328 // - abreviated name e.g. scr scr.bbs
1329 // - relative full name e.g. ./scr.bbs ../../scr.bbs
1330 // - absolute full name e.g. /home/usrname/proj/dir/scr.bbs
1331 // same for Windows, with c:, d: ...
1333 // use ./directory/subdir/scrname.bbs
1336 bbtkDebugMessage("interpreter",4,"==> Interpreter::SwitchToFile( \""
1337 <<name<<"\")"<<std::endl);
1339 std::vector<std::string> script_paths;
1340 std::string fullPathScriptName; // full path script name
1341 std::string pkgname; // e.g. <scriptname>.bbs
1342 std::vector<std::string> Filenames;
1344 // The following is *NOT* a debug time message :
1345 // It's a user intended message.
1346 // Please don't remove it.
1347 bbtkMessage("interpreter",1,
1348 "look for : [" << name
1349 << "]" << std::endl);
1353 pkgname = Utilities::ExtractScriptName(name,upath);
1355 bbtkMessage("interpreter",3,
1356 "package name:[" << pkgname
1357 << "] path:[" << upath << "]" << std::endl);
1358 bool fullnameGiven = false;
1359 bool foundFile = false;
1361 // ==== "*" provided : load all scripts in given path
1362 // relative (e.g. std/boxes/*) or absolute
1366 std::stringstream* stream = new std::stringstream;
1367 //if (upath.size()!=0) // avoid troubles for "*"
1369 // ==== no path provided : look in root bbs path
1370 if (upath.size()==0)
1372 // bbtkMessage("interpreter",1,
1373 // LG : add all bbs path
1374 // script_paths.push_back( ConfigurationFile::GetInstance().Get_root_bbs_path() );
1375 std::vector<std::string>::const_iterator i;
1376 for (i=ConfigurationFile::GetInstance().Get_bbs_paths().begin();
1377 i!=ConfigurationFile::GetInstance().Get_bbs_paths().end();
1380 script_paths.push_back(*i);
1383 // ==== absolute path provided
1384 else if (upath[0]=='/' || upath[1] == ':' )
1386 if ( Utilities::IsDirectory( upath ) )
1388 script_paths.push_back(upath);
1392 bbtkError("'"<<upath<<"' : directory does not exist");
1395 // ==== relative path provided : search all bbs path appended with
1396 // the relative path provided
1399 std::vector<std::string>::const_iterator i;
1400 for (i=ConfigurationFile::GetInstance().Get_bbs_paths().begin();
1401 i!=ConfigurationFile::GetInstance().Get_bbs_paths().end();
1404 std::string full_path(*i);
1405 // we *really* want '.' to be the current working directory
1406 if (full_path == ".")
1408 char buf[2048]; // for getcwd
1409 char * currentDir = getcwd(buf, 2048);
1410 std::string cwd(currentDir);
1411 full_path = currentDir;
1414 full_path += ConfigurationFile::GetInstance().Get_file_separator();
1417 if ( Utilities::IsDirectory( full_path ) )
1419 script_paths.push_back(full_path);
1422 if (script_paths.empty())
1424 bbtkError("no '"<<upath<<"' subdir found in search paths"
1430 // === search paths list complete : now explore it
1432 // ==== relative name, iterate + load all .bbs/.bbp files
1433 std::vector<std::string>::iterator i;
1434 for (i=script_paths.begin();i!=script_paths.end();i++)
1436 bbtkMessage("interpreter",1,
1437 "--> Looking in '" << *i << "'" << std::endl);
1441 Utilities::Explore(*i, false, Filenames);
1443 for (std::vector<std::string>::iterator j = Filenames.begin();
1444 j!= Filenames.end(); ++j)
1446 int lgr = (*j).size();
1447 if (lgr < 5) continue;
1448 // ignore non .bbp file
1449 if ( (*j).substr(lgr-4, 4) != ".bbp") continue;
1451 (*stream) << "include \"" << *j << "\"\n";
1452 bbtkMessage("interpreter",2," --> Found '" << *j << "'" << std::endl);
1455 } // for (std::vector...
1456 } // for (i=script_...
1461 bbtkMessage("interpreter",1,
1462 " --> No .bbp found"<< std::endl);
1466 bbtkMessage("interpreter",1,
1467 " --> "<<nbBssFiles<<" .bbp found"<< std::endl);
1468 SwitchToStream(stream);
1472 //=============== end pkgname=="*" ===========
1475 // if name starts with a / or a . or contains : user is assumed to have passed a relative/absolute name
1476 // (not only a plain script name)
1477 // we trust him, and try to expland the directory name
1478 // WARNING : starting from current local directory : ./whatYouWant (./ mandatory!)
1480 if (name[0]=='/' || name[1] == ':' || name[0]=='.') // absolute path (linux/windows) or relative path
1483 // ===========================================================check user supplied location
1484 fullnameGiven = true;
1486 fullPathScriptName = Utilities::ExpandLibName(name, false);
1488 // allow user to always forget ".bbs"
1489 int l = fullPathScriptName.size();
1493 if ((fullPathScriptName.substr(l-4, 4) != ".bbs")&&
1494 (fullPathScriptName.substr(l-4, 4) != ".bbp"))
1496 std::string tfullPathScriptName = fullPathScriptName + ".bbs";
1497 if ( Utilities::FileExists(tfullPathScriptName) )
1499 fullPathScriptName = tfullPathScriptName;
1504 tfullPathScriptName = fullPathScriptName + ".bbp";
1505 if ( Utilities::FileExists(tfullPathScriptName) )
1507 fullPathScriptName = tfullPathScriptName;
1514 if ( Utilities::FileExists(fullPathScriptName) )
1522 // =============================== iterate on the paths
1524 script_paths = ConfigurationFile::GetInstance().Get_bbs_paths();
1526 std::vector<std::string>::iterator i;
1527 for (i=script_paths.begin();i!=script_paths.end();++i)
1530 // we *really* want '.' to be the current working directory
1533 char buf[2048]; // for getcwd
1534 char * currentDir = getcwd(buf, 2048);
1535 std::string cwd(currentDir);
1539 std::string tfullPathScriptName = Utilities::MakePkgnameFromPath(path, name, false);
1540 //Addition JCP tfullPathScriptName.size()>=4
1541 if(tfullPathScriptName.size()>=4){
1542 if (tfullPathScriptName.substr(tfullPathScriptName.size()-4, 3)==".bb")
1544 fullPathScriptName = tfullPathScriptName;
1545 if ( ! Utilities::FileExists(fullPathScriptName) )
1547 // The following is *NOT* a debug time message :
1548 // It's a user intended message.
1549 // Please don't remove it.
1550 bbtkMessage("interpreter",2,
1551 " [" <<fullPathScriptName <<"] : does not exist"
1553 continue; // try next path
1555 bbtkMessage("interpreter",2,
1556 " [" <<fullPathScriptName
1557 <<"] : found" <<std::endl);
1559 break; // a script was found; we stop iterating
1563 fullPathScriptName = tfullPathScriptName + ".bbs";
1564 // Check if library exists
1565 if ( ! Utilities::FileExists(fullPathScriptName) )
1567 fullPathScriptName = tfullPathScriptName + ".bbp";
1568 if ( ! Utilities::FileExists(fullPathScriptName) )
1570 // The following is *NOT* a debug time message :
1571 // It's a user intended message.
1572 // Please don't remove it.
1573 bbtkMessage("interpreter",2,
1574 " [" <<tfullPathScriptName <<".bbs/.bbp] : do not exist"
1576 continue; // try next path
1579 bbtkMessage("interpreter",2,
1580 " [" <<fullPathScriptName
1581 <<"] : found" <<std::endl);
1583 break; // a script was found; we stop iterating
1586 } //------------------ // end for ( package_paths.begin();i!=package_paths.end() )
1592 if(fullPathScriptName == "")
1593 bbtkError("Path ["<<upath<<"] doesn't exist");
1595 bbtkError("Script ["<<fullPathScriptName<<"] not found");
1597 bbtkError("No ["<<pkgname<<".bbs/.bbp] script found");
1602 LoadScript(fullPathScriptName,name);
1603 if (source) GetExecuter()->SetCurrentFileName(fullPathScriptName);
1608 //=======================================================================
1611 //=======================================================================
1612 void Interpreter::SwitchToStream( std::stringstream* stream )
1614 bbtkDebugMessage("interpreter",4,"==> Interpreter::SwitchToStream()"
1616 mFile.push_back(stream);
1617 std::ostringstream buffer_name;
1619 buffer_name << "buffer_" ;
1621 if (mFileName.size()>0 )
1623 buffer_name << mFileName.back() << "_" << mLine.back();
1625 mFileName.push_back(buffer_name.str());
1626 mIncludeFileName.push_back(buffer_name.str());
1629 //=======================================================================
1631 //=======================================================================
1633 void Interpreter::LoadScript( std::string fullPathScriptName,
1634 std::string includeScriptName)
1636 bbtkDebugMessage("interpreter",4,"==> Interpreter::LoadScript("
1637 <<fullPathScriptName<<")"
1640 Utilities::replace( fullPathScriptName ,
1641 INVALID_FILE_SEPARATOR , VALID_FILE_SEPARATOR);
1643 if (find(mFileNameHistory.begin(),
1644 mFileNameHistory.end(),
1645 fullPathScriptName)!=mFileNameHistory.end())
1651 s = new std::ifstream;
1652 s->open(fullPathScriptName.c_str());
1655 bbtkError("Could not open file ["<<fullPathScriptName<<"]");
1659 bbtkMessage("interpreter",1," -->[" << fullPathScriptName
1660 << "] found" << std::endl);
1663 mFileName.push_back(fullPathScriptName);
1664 mFileNameHistory.push_back(fullPathScriptName);
1665 mIncludeFileName.push_back(includeScriptName);
1670 //=======================================================================
1672 //=======================================================================
1673 void Interpreter::CloseCurrentFile()
1675 bbtkDebugMessage("interpreter",9,"==> Interpreter::CloseCurrentFile()"
1678 if (mFile.size()==0)
1680 bbtkDebugMessage("interpreter",9," -> no file left open"<<std::endl);
1684 bbtkDebugMessage("interpreter",9," Closing file '"<<mFileName.back()<<"'"<<std::endl);
1686 std::ifstream* file = dynamic_cast<std::ifstream*>(mFile.back());
1687 if (file!=0) file->close();
1689 delete mFile.back();
1691 mFileName.pop_back();
1692 mIncludeFileName.pop_back();
1695 bbtkDebugMessage("interpreter",9," Remains "
1697 <<" open"<<std::endl);
1698 bbtkDebugMessage("interpreter",9,"<== Interpreter::CloseCurrentFile()"
1701 //=======================================================================
1703 //=======================================================================
1704 void Interpreter::CloseAllFiles()
1706 bbtkDebugMessage("interpreter",9,"==> Interpreter::CloseAllFiles()"
1709 while (mFile.size() != 0)
1713 bbtkDebugMessage("interpreter",9,"<== Interpreter::CloseAllFiles()"
1716 //=======================================================================
1720 //=======================================================================
1721 void Interpreter::InterpretCommand( const std::vector<std::string>& words,
1722 CommandInfoType& info )
1724 bbtkDebugMessage("interpreter",9,"==> Interpreter::InterpretCommand(...)"<<std::endl);
1726 // searches the command keyword
1727 CommandDictType::iterator c;
1728 c = mCommandDict.find(words[0]);
1729 if ( c == mCommandDict.end() ) {
1730 bbtkError(words[0]<<" : unknown command");
1733 // tests the number of args
1734 if ( ( ((int)words.size())-1 < c->second.argmin ) ||
1735 ( ((int)words.size())-1 > c->second.argmax ) )
1737 HelpCommand(words[0]);
1738 bbtkError(words[0]<<" : wrong number of arguments");
1740 //std::cout<<"Interpreter::InterpretCommand( const std::vector<std::string>& words,"<<std::endl;
1743 bbtkDebugMessage("interpreter",9,"<== Interpreter::InterpretCommand(...)"<<std::endl);
1746 //=======================================================================
1749 //=======================================================================
1750 /// Displays help on all the commands
1751 void Interpreter::Help(const std::vector<std::string>& words)
1753 unsigned int nbarg = words.size()-1;
1761 if (words[1]=="packages")
1763 GetExecuter()->GetFactory()->PrintHelpListPackages(true);
1768 HelpCommand(words[1]);
1770 catch (bbtk::Exception e)
1774 GetExecuter()->GetFactory()->PrintHelpPackage(words[1]);
1778 ConfigurationFile::GetInstance().Get_doc_path();
1779 url += "/bbdoc/" + words[1] + "/index.html";
1780 if (Utilities::FileExists(url))
1782 mUser->InterpreterUserViewHtmlPage(url);
1786 catch (bbtk::Exception f)
1790 std::string package;
1791 GetExecuter()->GetFactory()->PrintHelpDescriptor(words[1],
1796 ConfigurationFile::GetInstance().Get_doc_path();
1797 url += "/bbdoc/" + package + "/index.html";
1798 if (Utilities::FileExists(url))
1800 url += "#" + words[1];
1801 mUser->InterpreterUserViewHtmlPage(url);
1805 catch (bbtk::Exception g)
1809 GetExecuter()->PrintHelpBlackBox(words[1],"0","9999");
1811 catch (bbtk::Exception h){
1812 bbtkError("\""<<words[1].c_str()
1813 <<"\" is not a known command, package, black box type or black box name");
1821 if (words[2]=="all")
1823 if ( words[1]=="packages" )
1825 GetExecuter()->GetFactory()->PrintHelpListPackages(true,true);
1830 GetExecuter()->GetFactory()->PrintHelpPackage(words[1],true);
1832 catch (bbtk::Exception f)
1838 HelpCommand(words[0]);
1839 bbtkError(words[0]<<" : syntax error");
1844 bbtkError("Should not reach here !!!");
1847 //=======================================================================
1849 //===================================================================
1850 /// Displays the Configuration
1851 void Interpreter::Config() const
1853 ConfigurationFile::GetInstance().GetHelp(1);
1855 //===================================================================
1857 //=======================================================================
1858 /// Displays help on all the commands
1859 void Interpreter::HelpCommands()
1861 std::cout << "Available commands :" << std::endl;
1862 CommandDictType::iterator i;
1863 for ( i = mCommandDict.begin();
1864 i != mCommandDict.end();
1866 std::cout << " " << i->first << std::endl;
1867 // std::cout << " usage : " << i->second.syntax << std::endl;
1868 // std::cout << " " << i->second.help << std::endl;
1872 //=======================================================================
1875 //=======================================================================
1876 /// Displays help on a particular commands
1877 void Interpreter::HelpCommand(const std::string& s)
1879 CommandDictType::iterator c;
1880 c = mCommandDict.find(s);
1881 if ( c == mCommandDict.end() ) {
1882 bbtkError(s<<" : Unknown command");
1884 // std::cout << " " << s << " : "<< std::endl;
1885 // CommandParamDictType::iterator i;
1886 // for ( i = c->second.begin();
1887 // i != c->second.end();
1889 std::cout << " usage : " << c->second.syntax << std::endl;
1890 std::cout << " " << c->second.help << std::endl;
1893 //=======================================================================
1896 //=======================================================================
1897 /// Fills the vector commands with the commands which
1898 /// have the first n chars of buf for prefix
1899 /// TODO : skip initial spaces in buf and also return the position of first
1900 /// non blank char in buf
1901 void Interpreter::FindCommandsWithPrefix( char* buf,
1903 std::vector<std::string>& commands )
1905 CommandDictType::const_iterator i;
1906 for (i=mCommandDict.begin(); i!=mCommandDict.end(); ++i)
1908 if ((i->first).find(buf,0,n) == 0)
1909 commands.push_back(i->first);
1912 //=======================================================================
1916 //=======================================================================
1917 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1919 inline void PrintChar(char c) { write(STDOUT_FILENO,&c,1); }
1920 inline void BackSpace() { write(STDOUT_FILENO,"\b \b",3); }
1922 // LG : KEYBOARD CODES AS SCANNED ON MY TTY : UNIVERSAL ?
1923 // IF NOT THE USER SHOULD BE ABLE TO CONFIGURE IT
1924 // E.G. STORE THIS IN bbtk_config.xml
1925 #define BBTK_UP_ARROW_KBCODE 0x00415B1B
1926 #define BBTK_DOWN_ARROW_KBCODE 0x00425B1B
1927 #define BBTK_RIGHT_ARROW_KBCODE 0x00435B1B
1928 #define BBTK_LEFT_ARROW_KBCODE 0x00445B1B
1929 #define BBTK_BACKSPACE_KBCODE 0x00000008
1930 #define BBTK_DEL_KBCODE 0x0000007F
1931 #define BBTK_SPACE_KBCODE 0x00000020
1933 //=======================================================================
1934 void Interpreter::GetLineFromPrompt(std::string& s)
1939 unsigned int MAX_LINE_SIZE = 160;
1940 unsigned int MAX_HISTORY_SIZE = 100;
1942 char* newline = new char[MAX_LINE_SIZE];
1943 memset(newline,0,MAX_LINE_SIZE);
1944 char* histline = new char[MAX_LINE_SIZE];
1945 memset(histline,0,MAX_LINE_SIZE);
1947 char* line = newline;
1948 unsigned int hist = mHistory.size();
1954 read ( STDIN_FILENO, &c, 4) ;
1956 bbtkDebugMessage("debug",9,"[0x"<<std::hex<<c<<"]\n");
1958 // Printable character
1959 if ( (ind<MAX_LINE_SIZE-1) &&
1960 ( c >= BBTK_SPACE_KBCODE ) &&
1961 ( c < BBTK_DEL_KBCODE ))
1969 // delete the unused line
1975 // empty lines are not stored in from history
1978 // if history too long : delete oldest command
1979 if (mHistory.size()>MAX_HISTORY_SIZE)
1981 delete mHistory.front();
1982 mHistory.pop_front();
1984 mHistory.push_back(line);
1989 else if ( (ind>0) &&
1990 ((c == BBTK_BACKSPACE_KBCODE) ||
1991 (c == BBTK_DEL_KBCODE)) )
1999 // TODO : Command completion
2000 std::vector<std::string> commands;
2001 FindCommandsWithPrefix( line,ind,commands);
2002 if (commands.size()==1)
2004 std::string com = *commands.begin();
2005 for (; ind<com.size(); ++ind)
2007 PrintChar(com[ind]);
2013 else if (commands.size()>1)
2015 std::vector<std::string>::iterator i;
2017 for (i=commands.begin();i!=commands.end();++i)
2019 write(STDOUT_FILENO,(*i).c_str(),strlen((*i).c_str()));
2022 write(STDOUT_FILENO,"\n> ",3);
2023 //for (int j=0;j<ind;++j)
2025 write(STDOUT_FILENO,line,ind);
2029 // Arrow up : back in history
2030 else if (c==BBTK_UP_ARROW_KBCODE)
2034 // erase current line
2035 while (ind--) BackSpace();
2039 strcpy(histline,mHistory[hist]);
2043 write(STDOUT_FILENO,line,ind);
2046 // Arrow down : down in history
2047 else if (c==BBTK_DOWN_ARROW_KBCODE)
2049 if (hist<mHistory.size()-1)
2051 // erase current line
2052 while (ind--) BackSpace();
2056 strcpy(histline,mHistory[hist]);
2060 write(STDOUT_FILENO,line,ind);
2062 // end of history : switch back to newline
2063 else if (hist==mHistory.size()-1)
2065 // erase current line
2066 while (ind--) BackSpace();
2073 write(STDOUT_FILENO,line,ind);
2077 else if (line[ind]!=0 && c==BBTK_RIGHT_ARROW_KBCODE)
2079 PrintChar(line[ind]);
2084 else if (ind>0 && c==BBTK_LEFT_ARROW_KBCODE)
2092 write(STDOUT_FILENO,"\n\r",2);
2100 //=======================================================================
2101 void Interpreter::GetLineFromPrompt(std::string& s)
2127 //=======================================================================
2133 //=======================================================================
2134 void Interpreter::CommandLineInterpreter()
2136 bbtkDebugMessageInc("interpreter",9,
2137 "Interpreter::CommandLineInterpreter()"<<std::endl);
2139 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
2140 // Initialise the tty in non canonical mode with no echo
2141 // oter remembers the previous settings to restore them after
2142 struct termios ter,oter;
2145 ter.c_lflag &= ~ECHO;
2146 ter.c_lflag &= ~ICANON;
2149 tcsetattr(0,TCSANOW,&ter);
2152 mCommandLine = true;
2154 // bool insideComment = false; // for multiline comment
2155 mInsideComment = false;
2161 GetLineFromPrompt(line);
2162 DoInterpretLine(line); //, insideComment);
2165 catch (QuitException e)
2167 bbtkMessage("interpreter",1,"Interpreter : Quit"<<std::endl);
2171 catch (bbtk::Exception e)
2175 catch (std::exception& e)
2177 std::cerr << "* ERROR :: "<<e.what()<<" (not in bbtk)"<<std::endl;
2181 std::cerr << "* UNDEFINED ERROR (not a bbtk nor a std exception)"<<std::endl;
2186 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
2187 tcsetattr(0,TCSANOW,&oter);
2190 std::cout << "Good bye !" << std::endl;
2192 bbtkDebugDecTab("interpreter",9);
2195 //=======================================================================
2196 void Interpreter::Graph(const std::vector<std::string>& words)
2199 bool system_display = true;
2201 if ( ( mUser != 0 ) && ( mUser->InterpreterUserHasOwnHtmlPageViewer() ) )
2202 system_display = false;
2204 if (words.size()==1)
2206 page = mVirtualExecuter->ShowGraph(".","0","0","","","",system_display);
2208 else if (words.size()==2)
2210 page = mVirtualExecuter->ShowGraph(words[1],"0","0","","","",system_display);
2212 else if (words.size()==3)
2214 page = mVirtualExecuter->ShowGraph(words[1],words[2],"0","","","",system_display);
2216 else if (words.size()==4)
2218 page = mVirtualExecuter->ShowGraph(words[1],words[2],words[3],"","","",system_display);
2220 else if (words.size()==5)
2222 page = mVirtualExecuter->ShowGraph(words[1],words[2],words[3],words[4],"","",system_display);
2224 else if (words.size()==6)
2226 page = mVirtualExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],"",system_display);
2228 else if (words.size()==7)
2230 page = mVirtualExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],words[6],system_display);
2233 if ( ( mUser != 0 ) && ( mUser->InterpreterUserHasOwnHtmlPageViewer() ) )
2234 mUser->InterpreterUserViewHtmlPage(page);
2237 //=======================================================================
2240 //=======================================================================
2241 void Interpreter::Index(const std::string& filename,
2242 const std::string& type)
2244 Factory::IndexEntryType t;
2245 if (type=="Initials") t = Factory::Initials;
2246 else if (type=="Categories") t = Factory::Categories;
2247 else if (type=="Packages") t = Factory::Packages;
2248 else if (type=="Adaptors") t = Factory::Adaptors;
2250 GetExecuter()->GetFactory()->CreateHtmlIndex(t,filename);
2252 //=======================================================================
2255 //=======================================================================
2256 void Interpreter::NewGUI(const std::string& boxname,
2257 const std::string& instanceName)
2259 if (mRealExecuter.expired())
2261 bbtkError("command 'newgui' cannot be compiled yet");
2264 std::string typeName = instanceName+"Type";
2265 std::stringstream* s = new std::stringstream;
2266 // create the complex box
2267 (*s) << "define "<<typeName<<std::endl;
2268 // (*s) << " description 'Automatically generated user interface for the box "
2269 // << boxname << "'" <<std::endl;
2270 // create the Layout box
2271 (*s) << " load wx"<<std::endl;
2272 (*s) << " new LayoutLine layout"<<std::endl;
2273 // create the output 'Widget'
2274 (*s) << " output Widget layout.Widget Widget"<<std::endl;
2275 // the box change output
2276 (*s) << " new MultipleInputs change"<<std::endl;
2277 (*s) << " output BoxChange change.Out BoxChange"<<std::endl;
2279 // Browse the inputs of the box in order to find which ones are not
2280 // connected and can be adapted from a widget adaptor
2281 // vector which stores the list of inputs of the box which must be connected
2282 std::vector<std::string> in;
2284 Factory::Pointer F = mVirtualExecuter->GetFactory();
2286 Package::Pointer user = F->GetPackage("user");
2288 ComplexBlackBoxDescriptor::Pointer workspace =
2289 mRealExecuter.lock()->GetCurrentDescriptor();
2294 bbtkError("interpreter::CreateGUI : could not access the executer currently defined complex box");
2299 (ComplexBlackBoxDescriptor::Pointer)(user->GetBlackBoxMap().find("workspace")->second.get());
2302 BlackBox::Pointer box = workspace->GetPrototype()->bbGetBlackBox(boxname);
2303 // BlackBox::InputConnectorMapType incm = box->bbGetInputConnectorMap();
2305 BlackBox::InputConnectorMapType::iterator i;
2306 for (i=box->bbGetInputConnectorMap().begin();
2307 i!=box->bbGetInputConnectorMap().end();
2310 // If the input is connected : continue
2311 if (i->second->IsConnected()) continue;
2312 // Get the input descriptor
2313 const BlackBoxInputDescriptor* d = box->bbGetDescriptor()->GetInputDescriptor(i->first);
2314 // If it is a "system" input : skip it
2315 #ifdef USE_WXWIDGETS
2316 if ( ( d->GetCreatorTypeInfo() == typeid(AtomicBlackBoxDescriptor)) ||
2317 ( d->GetCreatorTypeInfo() == typeid(WxBlackBoxDescriptor)) )
2320 if ( ( d->GetCreatorTypeInfo() == typeid(AtomicBlackBoxDescriptor)) )
2324 std::string widget,adaptor;
2325 // try to find a widget adaptor
2326 if (F->FindWidgetAdaptor(DataInfo(d->GetTypeInfo(),""),
2330 // command to create the adaptor
2331 (*s) << " new "<<adaptor<<" "<<i->first<<std::endl;
2332 // Sets the label of the widget adaptor to the name of the input
2333 (*s) << " set "<<i->first<<".Label "<<i->first<<std::endl;
2334 // Sets the initial value of the widget to the value of the input
2335 (*s) << " set "<<i->first<<".In \" "
2336 <<box->bbGetInputAsString(i->first)<<"\""
2338 // store the input name
2339 in.push_back(i->first);
2340 (*s) << " connect "<<i->first<<".Widget layout.Widget"<<in.size()<<std::endl;
2341 //<i->first<<"'"<<std::endl;
2342 (*s) << " connect "<<i->first<<".BoxChange change.In"<<in.size()<<std::endl;
2344 // try to find a two pieces adaptor
2345 else if (F->FindWidgetAdaptor2(DataInfo(d->GetTypeInfo(),""),
2349 // command to create the widget
2350 (*s) << " new "<<widget<<" "<<i->first<<"Widget"<<std::endl;
2351 // command to create the adaptor
2352 (*s) << " new "<<adaptor<<" "<<i->first<<std::endl;
2354 (*s) << " connect "<<i->first<<"Widget.Out "
2355 <<i->first<<".In"<<std::endl;
2356 // Sets the label of the widget adaptor to the name of the input
2357 (*s) << " set "<<i->first<<"Widget.Label "<<i->first<<std::endl;
2358 // Sets the initial value of the widget to the value of the input
2359 (*s) << " set "<<i->first<<"Widget.In \" "
2360 <<box->bbGetInputAsString(i->first)<<"\""<< std::endl;
2361 // store the input name
2362 in.push_back(i->first);
2363 (*s) << " connect "<<i->first<<"Widget.Widget layout.Widget"<<in.size()<<std::endl;
2364 //<i->first<<"'"<<std::endl;
2365 (*s) << " connect "<<i->first<<"Widget.BoxChange change.In"<<in.size()<<std::endl;
2368 // try to find an adaptor from string
2369 // If found then can create a text input which
2370 // will be automatically adapted
2371 else if (F->FindAdaptor(DataInfo(typeid(std::string),""),
2375 // command to create the adaptor
2376 (*s) << " new InputText "<<i->first<<std::endl;
2377 // Sets the label of the widget adaptor to the name of the input
2378 (*s) << " set "<<i->first<<".Title "<<i->first<<std::endl;
2379 // Sets the initial value of the widget to the value of the input
2380 (*s) << " set "<<i->first<<".In \" "
2381 <<box->bbGetInputAsString(i->first)<<"\""<< std::endl;
2382 // store the input name
2383 in.push_back(i->first);
2384 (*s) << " connect "<<i->first<<".Widget layout.Widget"<<in.size()<<std::endl;
2385 //<i->first<<"'"<<std::endl;
2386 (*s) << " connect "<<i->first<<".BoxChange change.In"<<in.size()<<std::endl;
2395 // command to create the output
2396 (*s) << " output "<<i->first<<" "
2397 <<i->first<<".Out "<<i->first<<std::endl;
2398 // <<" Output of the widget which allows to set "
2402 // Inputs for window properties
2403 (*s) << " input WinTitle layout.WinTitle Title"<<std::endl;
2404 (*s) << " input WinWidth layout.WinWidth Width"<<std::endl;
2405 (*s) << " input WinHeight layout.WinHeight Height"<<std::endl;
2406 (*s) << " input WinDialog layout.WinDialog Dialog"<<std::endl;
2407 (*s) << " input WinHide layout.WinHide Hide"<<std::endl;
2411 // Execute the box executes the layout
2412 (*s) << " exec layout" << std::endl;
2413 (*s) << "endefine" << std::endl;
2414 // (*s) << "help "<< typeName<< std::endl;
2415 // instanciate the box and connect it
2416 (*s) << "new "<<typeName<<" "<<instanceName<<std::endl;
2418 std::vector<std::string>::iterator j;
2419 for (j=in.begin();j!=in.end();++j)
2422 (*s) << "connect "<<instanceName<<"."<<*j<<" "
2423 << boxname<<"."<<*j<<std::endl;
2425 // That's all folks ! now execute the commands :
2428 //=======================================================================
2432 //==========================================================================
2433 void Interpreter::Debug(const std::string& name)
2435 if ((name.length()==2)&&(name[0]=='-'))
2439 bbtk::StaticInitTime::PrintObjectListInfo = true;
2443 // int o = MessageManager::GetMessageLevel("debug");
2444 // if (o<2) MessageManager::SetMessageLevel("debug",2);
2445 mVirtualExecuter->GetFactory()->Check();
2446 // MessageManager::SetMessageLevel("debug",o);
2451 Object:: PrintObjectListInfo(name);
2454 //==========================================================================
2457 //==========================================================================
2458 // Adds a callback when 'break' command issued
2459 void Interpreter::AddBreakObserver( BreakCallbackType c )
2461 mBreakSignal.connect(c);
2463 //==========================================================================
2466 //==========================================================================
2467 std::string Interpreter::GetObjectName() const
2469 return std::string("Interpreter");
2471 //==========================================================================
2473 //==========================================================================
2474 std::string Interpreter::GetObjectInfo() const
2476 std::stringstream i;
2479 //==========================================================================
2481 //==========================================================================
2482 size_t Interpreter::GetObjectSize() const
2484 size_t s = Superclass::GetObjectSize();
2485 s += Interpreter::GetObjectInternalSize();
2488 //==========================================================================
2489 //==========================================================================
2490 size_t Interpreter::GetObjectInternalSize() const
2492 size_t s = sizeof(Interpreter);
2495 //==========================================================================
2496 //==========================================================================
2497 size_t Interpreter::GetObjectRecursiveSize() const
2499 size_t s = Superclass::GetObjectRecursiveSize();
2500 s += Interpreter::GetObjectInternalSize();
2501 s += mVirtualExecuter->GetObjectRecursiveSize();
2504 //==========================================================================