1 /*=========================================================================
3 Module: $RCSfile: bbtkInterpreter.cxx,v $
5 Date: $Date: 2010/09/15 14:17:17 $
6 Version: $Revision: 1.89 $
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);
870 void Interpreter::commandBreak()
873 std::cout << "BreakException("
876 <<line<<")"<<std::endl;
878 bbtkError("break");//,in_script,file,line);
879 // throw BreakException(in_script,file,line);
882 void Interpreter::commandQuit()
884 bbtkError("quit");//,in_script,file,line);
885 //throw QuitException(in_script,file,line);
888 void Interpreter::commandMessage()
890 mVirtualExecuter->HelpMessages();
894 void Interpreter::commandMessage(std::string kind, std::string levelstr)
897 sscanf(levelstr.c_str(),"%d",&level);
898 mVirtualExecuter->SetMessageLevel(kind,level);
904 //=======================================================================
905 void Interpreter::DoInterpretLine( const std::string& line )
907 bbtkDebugMessage("interpreter",6,"==> Interpreter::DoInterpretLine(\""
908 <<line<<"\")"<<std::endl);
909 std::vector<std::string> words;
910 SplitLine(line,words);
915 bbtkDebugDecTab("interpreter",9);
919 // Single line comment : # or //
920 if ( words[0][0]=='#' || (words[0][0]=='/' && words[0][1]=='/') )
922 bbtkDebugDecTab("interpreter",9);
923 bbtkMessage("interpreter",9,"Comment"<<std::endl);
927 // Multi line comment ( /* ... */ ) -delimiters on different lines !-
929 if (words[0][0]=='/' && words[0][1]=='*')
931 bbtkDebugDecTab("interpreter",9);
932 bbtkMessage("interpreter",9,"In multiline comment"<<std::endl);
933 mInsideComment = true;
937 if (words[0][0]=='*' && words[0][1]=='/')
939 bbtkDebugDecTab("interpreter",9);
940 bbtkMessage("interpreter",9,"Out multiline comment"<<std::endl);
941 if ( !mInsideComment ) {
942 bbtkDebugDecTab("interpreter",9);
943 bbtkMessage("interpreter",9,"Comment mismatch : '*/' with no matching '/*'"<<std::endl);
945 mInsideComment = false;
951 bbtkDebugDecTab("interpreter",9);
952 bbtkMessage("interpreter",9,"Multiline Comment"<<std::endl);
957 CommandInfoType command;
958 InterpretCommand(words,command);
959 //std::cout<<"JCP bbtkInterpreter command.keyword ="<<command.keyword<<std::endl;
960 bbtkDebugMessage("interpreter",9,
961 "Command='"<<command.keyword
962 <<"' code="<<command.code<<std::endl);
964 std::string left,right,left2,right2;
965 std::string filename;
969 if (command.code==cMessage)
974 //EED Borrame mVirtualExecuter->HelpMessages();
978 commandMessage(words[1],words[2]);
979 //EED Borrame sscanf(words[2].c_str(),"%d",&level);
980 //EED Borrame mVirtualExecuter->SetMessageLevel(words[1],level);
986 bbtkMessage("echo",2,line<<std::endl);
989 // break and quit commands
990 if ((command.code==cBreak) || (command.code==cQuit))
992 bool in_script = false;
993 std::string file("");
996 if (mFileName.size())
998 std::ifstream* fs = dynamic_cast<std::ifstream*>(mFile.back());
999 if (fs!=0) in_script = true;
1000 file = mFileName.back();
1001 line = mLine.back();
1003 if (command.code==cBreak)
1006 std::cout << "BreakException("
1009 <<line<<")"<<std::endl;
1012 //EED Borrame bbtkError("break");//,in_script,file,line);
1013 // throw BreakException(in_script,file,line);
1018 //EED Borrame bbtkError("quit");//,in_script,file,line);
1019 //throw QuitException(in_script,file,line);
1023 //std::cout<<" mVirtualExecuter->Create(words[1],words[2]); "<<line<<std::endl;
1026 switch (command.code)
1029 commandNew(words[1],words[2]);
1030 //EED Borrame mVirtualExecuter->Create(words[1],words[2]);
1034 commandDelete(words[1]);
1035 //EED Borrame mVirtualExecuter->Destroy(words[1]);
1039 Utilities::SplitAroundFirstDot(words[1],left,right);
1040 Utilities::SplitAroundFirstDot(words[2],left2,right2);
1041 commandConnection(left,right,left2,right2);
1042 //EED Borrame mVirtualExecuter->Connect(left,right,left2,right2);
1046 commandPackage(words[1]);
1047 //EED Borrame mVirtualExecuter->BeginPackage(words[1]);
1051 commandEndPackage();
1052 //EED Borrame mVirtualExecuter->EndPackage();
1056 if (mFileName.size()>0)
1058 //??? commandDefine(????);
1059 filename = mFileName.back(); //mIncludeFileName.back(); //Utilities::get_file_name(mFileName.back());
1061 if (words.size()==2)
1063 commandDefine(words[1],"",filename);
1064 //EED Borrame mVirtualExecuter->Define(words[1],"",filename);
1068 commandDefine(words[1],words[2],filename);
1069 //EED Borrame mVirtualExecuter->Define(words[1],words[2],filename);
1075 //EED Borrame mVirtualExecuter->EndDefine();
1079 commandKind(words[1]);
1080 //EED Borrame mVirtualExecuter->Kind(words[1]);
1084 commandPrint(words[1]);
1085 //EED Borrame mVirtualExecuter->Print(words[1]);
1089 commandExec(words[1]);
1090 //EED Borrame if (words[1]=="freeze")
1092 //EED Borrame mVirtualExecuter->SetNoExecMode(true);
1093 //EED Borrame mThrow = false;
1095 //EED Borrame else if (words[1]=="freeze_no_error")
1097 //EED Borrame mVirtualExecuter->SetNoExecMode(true);
1098 //EED Borrame mVirtualExecuter->SetNoErrorMode(true);
1099 //EED Borrame mThrow = false;
1101 //EED Borrame else if (words[1]=="unfreeze")
1103 //EED Borrame mVirtualExecuter->SetNoExecMode(false);
1104 //EED Borrame mVirtualExecuter->SetNoErrorMode(false);
1108 //EED Borrame mVirtualExecuter->Execute(words[1]);
1114 Utilities::SplitAroundFirstDot(words[2],left,right);
1115 commandInput(words[1],left,right,words[3]);
1116 //EED Borrame mVirtualExecuter->DefineInput(words[1],left,right,words[3]);
1120 Utilities::SplitAroundFirstDot(words[2],left,right);
1121 commandOutput(words[1],left,right,words[3]);
1122 //EED Borrame mVirtualExecuter->DefineOutput(words[1],left,right,words[3]);
1126 Utilities::SplitAroundFirstDot(words[1],left,right);
1127 commandSet(left,right,words[2]);
1128 //EED Borrame mVirtualExecuter->Set(left,right,words[2]);
1132 commandAuthor(words[1]);
1133 //EED Borrame mVirtualExecuter->Author(words[1]);
1137 commandNewGUI(words[1],words[2]);
1141 commandCategory(words[1]);
1142 //EED Borrame mVirtualExecuter->Category(words[1]);
1146 if (words.size()==1)
1147 commandIndex("tmp_index.html");
1148 else if (words.size()==2)
1149 commandIndex(words[1]);
1150 else if (words.size()==3)
1151 commandIndex(words[1],words[2]);
1155 commandDescription(words[1]);
1156 //EED Borrame mVirtualExecuter->Description(words[1]);
1165 commandGraph(words);
1178 //EED Borrame mVirtualExecuter->Clear();
1182 commandInclude( words[1] , (words.size()==3) );
1183 //EED Borrame // if 'source' was given (words.size()==3) then tell to set the
1184 //EED Borrame // source file name of the current complex box with the full file name included
1185 //EED Borrame if (mCommandLine)
1187 //EED Borrame InterpretFile(words[1],(words.size()==3));
1188 //EED Borrame } else{
1189 //EED Borrame SwitchToFile(words[1],(words.size()==3) );
1194 commandLoad( words[1] );
1195 //EED Borrame GetExecuter()->LoadPackage(words[1]);
1199 commandUnload( words[1] );
1200 //EED Borrame GetExecuter()->UnLoadPackage(words[1]);
1204 if (words.size()==2) commandDebug(words[1]);
1205 else commandDebug("");
1210 if (words.size() == 2)
1212 if (words[1]=="freeze") mVirtualExecuter->SetNoExecMode(true);
1213 else if (words[1]=="unfreeze") mVirtualExecuter->SetNoExecMode(false);
1217 mVirtualExecuter->SetWorkspaceName(words[2]);
1222 bbtkInternalError("should not reach here !!!");
1225 bbtkDebugMessage("interpreter",6,"<== Interpreter::DoInterpretLine(\""
1226 <<line<<"\")"<<std::endl);
1229 //=======================================================================
1235 //=======================================================================
1236 void Interpreter::SplitLine ( const std::string& str, std::vector<std::string>& tokens)
1238 bbtkDebugMessage("interpreter",9,"==> Interpreter::SplitLine(\""<<str<<"\")"<<std::endl);
1240 std::string delimiters = "\"";
1241 std::vector<std::string> quote;
1242 Utilities::SplitString(str,delimiters,quote);
1245 std::vector<std::string>::iterator i;
1246 for (i=quote.begin(); i!=quote.end(); )
1248 Utilities::SplitString(*i,delimiters,tokens);
1252 // bbtkDebugMessage("interpreter",0,"\""<<*i<<"\""<<std::endl);
1253 tokens.push_back(*i);
1258 for (i=tokens.begin(); i!=tokens.end(); ++i)
1260 bbtkDebugMessage("interpreter",9,"--["<<*i<<"]"<<std::endl);
1262 bbtkDebugMessage("interpreter",9,"<== Interpreter::SplitLine(\""<<str<<"\")"<<std::endl);
1265 //=======================================================================
1268 //=======================================================================
1269 void Interpreter::commandReset()
1271 // Cannot close all files if the reset command is read from a file !
1273 mFileNameHistory.clear();
1274 this->mVirtualExecuter->Reset();
1276 //=======================================================================
1278 //=======================================================================
1283 void Interpreter::Print( const std::string& str)
1285 if (mVirtualExecuter->GetNoExecMode()) return;
1287 bbtkDebugMessageInc("interpreter",9,"Interpreter::Print(\""<<str<<"\")"<<std::endl);
1290 // InterpretLine ("load std")
1291 // InterpretLine("new ConcatStrings _C_ ") -> trouver un nom unique : # commande
1292 // InterpretLine("new Print _P_")
1293 // InterpretLine("connect _C_.Out _P_.In")
1297 std::vector<std::string> chains;
1298 std::string delimiters("$");
1300 // Skip delimiters at beginning.
1301 std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
1302 bool is_text = true;
1303 if (lastPos>0) is_text = false;
1305 // Find first delimiter.
1306 std::string::size_type pos = str.find_first_of(delimiters, lastPos);
1308 while (std::string::npos != pos || std::string::npos != lastPos)
1312 // Found a text token, add it to the vector.
1313 chains.push_back(str.substr(lastPos, pos - lastPos));
1314 // std::string token = str.substr(lastPos, pos - lastPos)
1315 // InterpretLine("set _C_.In%num% %token%")
1321 // is an output (between $$) : decode
1322 std::string tok,box,output;
1323 tok = str.substr(lastPos, pos - lastPos);
1324 Utilities::SplitAroundFirstDot(tok,box,output);
1325 chains.push_back( mVirtualExecuter->Get(box,output) );
1327 // InterpretLine("connect %tok% _C_.In%num%")
1330 // Skip delimiters. Note the "not_of"
1331 lastPos = str.find_first_not_of(delimiters, pos);
1332 // Find next delimiter
1333 pos = str.find_first_of(delimiters, lastPos);
1338 // InterpretLine("exec _P_")
1339 // if (IS_IN_WORKSPACE) InterpretLine("delete _C_; delete _P_");
1341 std::vector<std::string>::iterator i;
1342 for (i= chains.begin(); i!=chains.end(); ++i)
1345 Utilities::SubsBackslashN(*i);
1348 std::cout << std::endl;
1349 bbtkDebugDecTab("interpreter",9);
1353 //=======================================================================
1358 // =========================================================================
1359 void Interpreter::SwitchToFile( const std::string& name , bool source )
1361 // Note : in the following :
1362 // name : the user supplied name
1363 // - abreviated name e.g. scr scr.bbs
1364 // - relative full name e.g. ./scr.bbs ../../scr.bbs
1365 // - absolute full name e.g. /home/usrname/proj/dir/scr.bbs
1366 // same for Windows, with c:, d: ...
1368 // use ./directory/subdir/scrname.bbs
1371 bbtkDebugMessage("interpreter",4,"==> Interpreter::SwitchToFile( \""
1372 <<name<<"\")"<<std::endl);
1374 std::vector<std::string> script_paths;
1375 std::string fullPathScriptName; // full path script name
1376 std::string pkgname; // e.g. <scriptname>.bbs
1377 std::vector<std::string> Filenames;
1379 // The following is *NOT* a debug time message :
1380 // It's a user intended message.
1381 // Please don't remove it.
1382 bbtkMessage("interpreter",1,
1383 "look for : [" << name
1384 << "]" << std::endl);
1388 pkgname = Utilities::ExtractScriptName(name,upath);
1390 bbtkMessage("interpreter",3,
1391 "package name:[" << pkgname
1392 << "] path:[" << upath << "]" << std::endl);
1393 bool fullnameGiven = false;
1394 bool foundFile = false;
1396 // ==== "*" provided : load all scripts in given path
1397 // relative (e.g. std/boxes/*) or absolute
1401 std::stringstream* stream = new std::stringstream;
1402 //if (upath.size()!=0) // avoid troubles for "*"
1404 // ==== no path provided : look in root bbs path
1405 if (upath.size()==0)
1407 // bbtkMessage("interpreter",1,
1408 // LG : add all bbs path
1409 // script_paths.push_back( ConfigurationFile::GetInstance().Get_root_bbs_path() );
1410 std::vector<std::string>::const_iterator i;
1411 for (i=ConfigurationFile::GetInstance().Get_bbs_paths().begin();
1412 i!=ConfigurationFile::GetInstance().Get_bbs_paths().end();
1415 script_paths.push_back(*i);
1418 // ==== absolute path provided
1419 else if (upath[0]=='/' || upath[1] == ':' )
1421 if ( Utilities::IsDirectory( upath ) )
1423 script_paths.push_back(upath);
1427 bbtkError("'"<<upath<<"' : directory does not exist");
1430 // ==== relative path provided : search all bbs path appended with
1431 // the relative path provided
1434 std::vector<std::string>::const_iterator i;
1435 for (i=ConfigurationFile::GetInstance().Get_bbs_paths().begin();
1436 i!=ConfigurationFile::GetInstance().Get_bbs_paths().end();
1439 std::string full_path(*i);
1440 // we *really* want '.' to be the current working directory
1441 if (full_path == ".")
1443 char buf[2048]; // for getcwd
1444 char * currentDir = getcwd(buf, 2048);
1445 std::string cwd(currentDir);
1446 full_path = currentDir;
1449 full_path += ConfigurationFile::GetInstance().Get_file_separator();
1452 if ( Utilities::IsDirectory( full_path ) )
1454 script_paths.push_back(full_path);
1457 if (script_paths.empty())
1459 bbtkError("no '"<<upath<<"' subdir found in search paths"
1465 // === search paths list complete : now explore it
1467 // ==== relative name, iterate + load all .bbs/.bbp files
1468 std::vector<std::string>::iterator i;
1469 for (i=script_paths.begin();i!=script_paths.end();i++)
1471 bbtkMessage("interpreter",1,
1472 "--> Looking in '" << *i << "'" << std::endl);
1476 Utilities::Explore(*i, false, Filenames);
1478 for (std::vector<std::string>::iterator j = Filenames.begin();
1479 j!= Filenames.end(); ++j)
1481 int lgr = (*j).size();
1482 if (lgr < 5) continue;
1483 // ignore non .bbp file
1484 if ( (*j).substr(lgr-4, 4) != ".bbp") continue;
1486 (*stream) << "include \"" << *j << "\"\n";
1487 bbtkMessage("interpreter",2," --> Found '" << *j << "'" << std::endl);
1490 } // for (std::vector...
1491 } // for (i=script_...
1496 bbtkMessage("interpreter",1,
1497 " --> No .bbp found"<< std::endl);
1501 bbtkMessage("interpreter",1,
1502 " --> "<<nbBssFiles<<" .bbp found"<< std::endl);
1503 SwitchToStream(stream);
1507 //=============== end pkgname=="*" ===========
1510 // if name starts with a / or a . or contains : user is assumed to have passed a relative/absolute name
1511 // (not only a plain script name)
1512 // we trust him, and try to expland the directory name
1513 // WARNING : starting from current local directory : ./whatYouWant (./ mandatory!)
1515 if (name[0]=='/' || name[1] == ':' || name[0]=='.') // absolute path (linux/windows) or relative path
1518 // ===========================================================check user supplied location
1519 fullnameGiven = true;
1521 fullPathScriptName = Utilities::ExpandLibName(name, false);
1523 // allow user to always forget ".bbs"
1524 int l = fullPathScriptName.size();
1528 if ((fullPathScriptName.substr(l-4, 4) != ".bbs")&&
1529 (fullPathScriptName.substr(l-4, 4) != ".bbp"))
1531 std::string tfullPathScriptName = fullPathScriptName + ".bbs";
1532 if ( Utilities::FileExists(tfullPathScriptName) )
1534 fullPathScriptName = tfullPathScriptName;
1539 tfullPathScriptName = fullPathScriptName + ".bbp";
1540 if ( Utilities::FileExists(tfullPathScriptName) )
1542 fullPathScriptName = tfullPathScriptName;
1549 if ( Utilities::FileExists(fullPathScriptName) )
1557 // =============================== iterate on the paths
1559 script_paths = ConfigurationFile::GetInstance().Get_bbs_paths();
1561 std::vector<std::string>::iterator i;
1562 for (i=script_paths.begin();i!=script_paths.end();++i)
1565 // we *really* want '.' to be the current working directory
1568 char buf[2048]; // for getcwd
1569 char * currentDir = getcwd(buf, 2048);
1570 std::string cwd(currentDir);
1574 std::string tfullPathScriptName = Utilities::MakePkgnameFromPath(path, name, false);
1575 //Addition JCP tfullPathScriptName.size()>=4
1576 if(tfullPathScriptName.size()>=4){
1577 if (tfullPathScriptName.substr(tfullPathScriptName.size()-4, 3)==".bb")
1579 fullPathScriptName = tfullPathScriptName;
1580 if ( ! Utilities::FileExists(fullPathScriptName) )
1582 // The following is *NOT* a debug time message :
1583 // It's a user intended message.
1584 // Please don't remove it.
1585 bbtkMessage("interpreter",2,
1586 " [" <<fullPathScriptName <<"] : does not exist"
1588 continue; // try next path
1590 bbtkMessage("interpreter",2,
1591 " [" <<fullPathScriptName
1592 <<"] : found" <<std::endl);
1594 break; // a script was found; we stop iterating
1598 fullPathScriptName = tfullPathScriptName + ".bbs";
1599 // Check if library exists
1600 if ( ! Utilities::FileExists(fullPathScriptName) )
1602 fullPathScriptName = tfullPathScriptName + ".bbp";
1603 if ( ! Utilities::FileExists(fullPathScriptName) )
1605 // The following is *NOT* a debug time message :
1606 // It's a user intended message.
1607 // Please don't remove it.
1608 bbtkMessage("interpreter",2,
1609 " [" <<tfullPathScriptName <<".bbs/.bbp] : do not exist"
1611 continue; // try next path
1614 bbtkMessage("interpreter",2,
1615 " [" <<fullPathScriptName
1616 <<"] : found" <<std::endl);
1618 break; // a script was found; we stop iterating
1621 } //------------------ // end for ( package_paths.begin();i!=package_paths.end() )
1627 if(fullPathScriptName == "")
1628 bbtkError("Path ["<<upath<<"] doesn't exist");
1630 bbtkError("Script ["<<fullPathScriptName<<"] not found");
1632 bbtkError("No ["<<pkgname<<".bbs/.bbp] script found");
1637 LoadScript(fullPathScriptName,name);
1638 if (source) GetExecuter()->SetCurrentFileName(fullPathScriptName);
1643 //=======================================================================
1646 //=======================================================================
1647 void Interpreter::SwitchToStream( std::stringstream* stream )
1649 bbtkDebugMessage("interpreter",4,"==> Interpreter::SwitchToStream()"
1651 mFile.push_back(stream);
1652 std::ostringstream buffer_name;
1654 buffer_name << "buffer_" ;
1656 if (mFileName.size()>0 )
1658 buffer_name << mFileName.back() << "_" << mLine.back();
1660 mFileName.push_back(buffer_name.str());
1661 mIncludeFileName.push_back(buffer_name.str());
1664 //=======================================================================
1666 //=======================================================================
1668 void Interpreter::LoadScript( std::string fullPathScriptName,
1669 std::string includeScriptName)
1671 bbtkDebugMessage("interpreter",4,"==> Interpreter::LoadScript("
1672 <<fullPathScriptName<<")"
1675 Utilities::replace( fullPathScriptName ,
1676 INVALID_FILE_SEPARATOR , VALID_FILE_SEPARATOR);
1678 if (find(mFileNameHistory.begin(),
1679 mFileNameHistory.end(),
1680 fullPathScriptName)!=mFileNameHistory.end())
1686 s = new std::ifstream;
1687 s->open(fullPathScriptName.c_str());
1690 bbtkError("Could not open file ["<<fullPathScriptName<<"]");
1694 bbtkMessage("interpreter",1," -->[" << fullPathScriptName
1695 << "] found" << std::endl);
1698 mFileName.push_back(fullPathScriptName);
1699 mFileNameHistory.push_back(fullPathScriptName);
1700 mIncludeFileName.push_back(includeScriptName);
1705 //=======================================================================
1707 //=======================================================================
1708 void Interpreter::CloseCurrentFile()
1710 bbtkDebugMessage("interpreter",9,"==> Interpreter::CloseCurrentFile()"
1713 if (mFile.size()==0)
1715 bbtkDebugMessage("interpreter",9," -> no file left open"<<std::endl);
1719 bbtkDebugMessage("interpreter",9," Closing file '"<<mFileName.back()<<"'"<<std::endl);
1721 std::ifstream* file = dynamic_cast<std::ifstream*>(mFile.back());
1722 if (file!=0) file->close();
1724 delete mFile.back();
1726 mFileName.pop_back();
1727 mIncludeFileName.pop_back();
1730 bbtkDebugMessage("interpreter",9," Remains "
1732 <<" open"<<std::endl);
1733 bbtkDebugMessage("interpreter",9,"<== Interpreter::CloseCurrentFile()"
1736 //=======================================================================
1738 //=======================================================================
1739 void Interpreter::CloseAllFiles()
1741 bbtkDebugMessage("interpreter",9,"==> Interpreter::CloseAllFiles()"
1744 while (mFile.size() != 0)
1748 bbtkDebugMessage("interpreter",9,"<== Interpreter::CloseAllFiles()"
1751 //=======================================================================
1755 //=======================================================================
1756 void Interpreter::InterpretCommand( const std::vector<std::string>& words,
1757 CommandInfoType& info )
1759 bbtkDebugMessage("interpreter",9,"==> Interpreter::InterpretCommand(...)"<<std::endl);
1761 // searches the command keyword
1762 CommandDictType::iterator c;
1763 c = mCommandDict.find(words[0]);
1764 if ( c == mCommandDict.end() ) {
1765 bbtkError(words[0]<<" : unknown command");
1768 // tests the number of args
1769 if ( ( ((int)words.size())-1 < c->second.argmin ) ||
1770 ( ((int)words.size())-1 > c->second.argmax ) )
1772 HelpCommand(words[0]);
1773 bbtkError(words[0]<<" : wrong number of arguments");
1775 //std::cout<<"Interpreter::InterpretCommand( const std::vector<std::string>& words,"<<std::endl;
1778 bbtkDebugMessage("interpreter",9,"<== Interpreter::InterpretCommand(...)"<<std::endl);
1781 //=======================================================================
1784 //=======================================================================
1785 /// Displays help on all the commands
1786 void Interpreter::commandHelp(const std::vector<std::string>& words)
1788 unsigned int nbarg = words.size()-1;
1796 if (words[1]=="packages")
1798 GetExecuter()->GetFactory()->PrintHelpListPackages(true);
1803 HelpCommand(words[1]);
1805 catch (bbtk::Exception e)
1809 GetExecuter()->GetFactory()->PrintHelpPackage(words[1]);
1813 ConfigurationFile::GetInstance().Get_doc_path();
1814 url += "/bbdoc/" + words[1] + "/index.html";
1815 if (Utilities::FileExists(url))
1817 mUser->InterpreterUserViewHtmlPage(url);
1821 catch (bbtk::Exception f)
1825 std::string package;
1826 GetExecuter()->GetFactory()->PrintHelpDescriptor(words[1],
1831 ConfigurationFile::GetInstance().Get_doc_path();
1832 url += "/bbdoc/" + package + "/index.html";
1833 if (Utilities::FileExists(url))
1835 url += "#" + words[1];
1836 mUser->InterpreterUserViewHtmlPage(url);
1840 catch (bbtk::Exception g)
1844 GetExecuter()->PrintHelpBlackBox(words[1],"0","9999");
1846 catch (bbtk::Exception h){
1847 bbtkError("\""<<words[1].c_str()
1848 <<"\" is not a known command, package, black box type or black box name");
1856 if (words[2]=="all")
1858 if ( words[1]=="packages" )
1860 GetExecuter()->GetFactory()->PrintHelpListPackages(true,true);
1865 GetExecuter()->GetFactory()->PrintHelpPackage(words[1],true);
1867 catch (bbtk::Exception f)
1873 HelpCommand(words[0]);
1874 bbtkError(words[0]<<" : syntax error");
1879 bbtkError("Should not reach here !!!");
1882 //=======================================================================
1884 //===================================================================
1885 /// Displays the Configuration
1886 void Interpreter::commandConfig() const
1888 ConfigurationFile::GetInstance().GetHelp(1);
1890 //===================================================================
1892 //=======================================================================
1893 /// Displays help on all the commands
1894 void Interpreter::HelpCommands()
1896 std::cout << "Available commands :" << std::endl;
1897 CommandDictType::iterator i;
1898 for ( i = mCommandDict.begin();
1899 i != mCommandDict.end();
1901 std::cout << " " << i->first << std::endl;
1902 // std::cout << " usage : " << i->second.syntax << std::endl;
1903 // std::cout << " " << i->second.help << std::endl;
1907 //=======================================================================
1910 //=======================================================================
1911 /// Displays help on a particular commands
1912 void Interpreter::HelpCommand(const std::string& s)
1914 CommandDictType::iterator c;
1915 c = mCommandDict.find(s);
1916 if ( c == mCommandDict.end() ) {
1917 bbtkError(s<<" : Unknown command");
1919 // std::cout << " " << s << " : "<< std::endl;
1920 // CommandParamDictType::iterator i;
1921 // for ( i = c->second.begin();
1922 // i != c->second.end();
1924 std::cout << " usage : " << c->second.syntax << std::endl;
1925 std::cout << " " << c->second.help << std::endl;
1928 //=======================================================================
1931 //=======================================================================
1932 /// Fills the vector commands with the commands which
1933 /// have the first n chars of buf for prefix
1934 /// TODO : skip initial spaces in buf and also return the position of first
1935 /// non blank char in buf
1936 void Interpreter::FindCommandsWithPrefix( char* buf,
1938 std::vector<std::string>& commands )
1940 CommandDictType::const_iterator i;
1941 for (i=mCommandDict.begin(); i!=mCommandDict.end(); ++i)
1943 if ((i->first).find(buf,0,n) == 0)
1944 commands.push_back(i->first);
1947 //=======================================================================
1951 //=======================================================================
1952 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1954 inline void PrintChar(char c) { write(STDOUT_FILENO,&c,1); }
1955 inline void BackSpace() { write(STDOUT_FILENO,"\b \b",3); }
1957 // LG : KEYBOARD CODES AS SCANNED ON MY TTY : UNIVERSAL ?
1958 // IF NOT THE USER SHOULD BE ABLE TO CONFIGURE IT
1959 // E.G. STORE THIS IN bbtk_config.xml
1960 #define BBTK_UP_ARROW_KBCODE 0x00415B1B
1961 #define BBTK_DOWN_ARROW_KBCODE 0x00425B1B
1962 #define BBTK_RIGHT_ARROW_KBCODE 0x00435B1B
1963 #define BBTK_LEFT_ARROW_KBCODE 0x00445B1B
1964 #define BBTK_BACKSPACE_KBCODE 0x00000008
1965 #define BBTK_DEL_KBCODE 0x0000007F
1966 #define BBTK_SPACE_KBCODE 0x00000020
1968 //=======================================================================
1969 void Interpreter::GetLineFromPrompt(std::string& s)
1974 unsigned int MAX_LINE_SIZE = 160;
1975 unsigned int MAX_HISTORY_SIZE = 100;
1977 char* newline = new char[MAX_LINE_SIZE];
1978 memset(newline,0,MAX_LINE_SIZE);
1979 char* histline = new char[MAX_LINE_SIZE];
1980 memset(histline,0,MAX_LINE_SIZE);
1982 char* line = newline;
1983 unsigned int hist = mHistory.size();
1989 read ( STDIN_FILENO, &c, 4) ;
1991 bbtkDebugMessage("debug",9,"[0x"<<std::hex<<c<<"]\n");
1993 // Printable character
1994 if ( (ind<MAX_LINE_SIZE-1) &&
1995 ( c >= BBTK_SPACE_KBCODE ) &&
1996 ( c < BBTK_DEL_KBCODE ))
2004 // delete the unused line
2010 // empty lines are not stored in from history
2013 // if history too long : delete oldest command
2014 if (mHistory.size()>MAX_HISTORY_SIZE)
2016 delete mHistory.front();
2017 mHistory.pop_front();
2019 mHistory.push_back(line);
2024 else if ( (ind>0) &&
2025 ((c == BBTK_BACKSPACE_KBCODE) ||
2026 (c == BBTK_DEL_KBCODE)) )
2034 // TODO : Command completion
2035 std::vector<std::string> commands;
2036 FindCommandsWithPrefix( line,ind,commands);
2037 if (commands.size()==1)
2039 std::string com = *commands.begin();
2040 for (; ind<com.size(); ++ind)
2042 PrintChar(com[ind]);
2048 else if (commands.size()>1)
2050 std::vector<std::string>::iterator i;
2052 for (i=commands.begin();i!=commands.end();++i)
2054 write(STDOUT_FILENO,(*i).c_str(),strlen((*i).c_str()));
2057 write(STDOUT_FILENO,"\n> ",3);
2058 //for (int j=0;j<ind;++j)
2060 write(STDOUT_FILENO,line,ind);
2064 // Arrow up : back in history
2065 else if (c==BBTK_UP_ARROW_KBCODE)
2069 // erase current line
2070 while (ind--) BackSpace();
2074 strcpy(histline,mHistory[hist]);
2078 write(STDOUT_FILENO,line,ind);
2081 // Arrow down : down in history
2082 else if (c==BBTK_DOWN_ARROW_KBCODE)
2084 if (hist<mHistory.size()-1)
2086 // erase current line
2087 while (ind--) BackSpace();
2091 strcpy(histline,mHistory[hist]);
2095 write(STDOUT_FILENO,line,ind);
2097 // end of history : switch back to newline
2098 else if (hist==mHistory.size()-1)
2100 // erase current line
2101 while (ind--) BackSpace();
2108 write(STDOUT_FILENO,line,ind);
2112 else if (line[ind]!=0 && c==BBTK_RIGHT_ARROW_KBCODE)
2114 PrintChar(line[ind]);
2119 else if (ind>0 && c==BBTK_LEFT_ARROW_KBCODE)
2127 write(STDOUT_FILENO,"\n\r",2);
2135 //=======================================================================
2136 void Interpreter::GetLineFromPrompt(std::string& s)
2162 //=======================================================================
2168 //=======================================================================
2169 void Interpreter::CommandLineInterpreter()
2171 bbtkDebugMessageInc("interpreter",9,
2172 "Interpreter::CommandLineInterpreter()"<<std::endl);
2174 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
2175 // Initialise the tty in non canonical mode with no echo
2176 // oter remembers the previous settings to restore them after
2177 struct termios ter,oter;
2180 ter.c_lflag &= ~ECHO;
2181 ter.c_lflag &= ~ICANON;
2184 tcsetattr(0,TCSANOW,&ter);
2187 mCommandLine = true;
2189 // bool insideComment = false; // for multiline comment
2190 mInsideComment = false;
2196 GetLineFromPrompt(line);
2197 DoInterpretLine(line); //, insideComment);
2200 catch (QuitException e)
2202 bbtkMessage("interpreter",1,"Interpreter : Quit"<<std::endl);
2206 catch (bbtk::Exception e)
2210 catch (std::exception& e)
2212 std::cerr << "* ERROR :: "<<e.what()<<" (not in bbtk)"<<std::endl;
2216 std::cerr << "* UNDEFINED ERROR (not a bbtk nor a std exception)"<<std::endl;
2221 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
2222 tcsetattr(0,TCSANOW,&oter);
2225 std::cout << "Good bye !" << std::endl;
2227 bbtkDebugDecTab("interpreter",9);
2230 //=======================================================================
2231 void Interpreter::commandGraph(const std::vector<std::string>& words)
2234 bool system_display = true;
2236 if ( ( mUser != 0 ) && ( mUser->InterpreterUserHasOwnHtmlPageViewer() ) )
2237 system_display = false;
2239 if (words.size()==1)
2241 page = mVirtualExecuter->ShowGraph(".","0","0","","","",system_display);
2243 else if (words.size()==2)
2245 page = mVirtualExecuter->ShowGraph(words[1],"0","0","","","",system_display);
2247 else if (words.size()==3)
2249 page = mVirtualExecuter->ShowGraph(words[1],words[2],"0","","","",system_display);
2251 else if (words.size()==4)
2253 page = mVirtualExecuter->ShowGraph(words[1],words[2],words[3],"","","",system_display);
2255 else if (words.size()==5)
2257 page = mVirtualExecuter->ShowGraph(words[1],words[2],words[3],words[4],"","",system_display);
2259 else if (words.size()==6)
2261 page = mVirtualExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],"",system_display);
2263 else if (words.size()==7)
2265 page = mVirtualExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],words[6],system_display);
2268 if ( ( mUser != 0 ) && ( mUser->InterpreterUserHasOwnHtmlPageViewer() ) )
2269 mUser->InterpreterUserViewHtmlPage(page);
2272 //=======================================================================
2275 //=======================================================================
2276 void Interpreter::commandIndex(const std::string& filename,
2277 const std::string& type)
2279 Factory::IndexEntryType t;
2280 if (type=="Initials") t = Factory::Initials;
2281 else if (type=="Categories") t = Factory::Categories;
2282 else if (type=="Packages") t = Factory::Packages;
2283 else if (type=="Adaptors") t = Factory::Adaptors;
2285 GetExecuter()->GetFactory()->CreateHtmlIndex(t,filename);
2287 //=======================================================================
2290 //=======================================================================
2291 void Interpreter::commandNewGUI(const std::string& boxname,
2292 const std::string& instanceName)
2294 if (mRealExecuter.expired())
2296 bbtkError("command 'newgui' cannot be compiled yet");
2299 std::string typeName = instanceName+"Type";
2300 std::stringstream* s = new std::stringstream;
2301 // create the complex box
2302 (*s) << "define "<<typeName<<std::endl;
2303 // (*s) << " description 'Automatically generated user interface for the box "
2304 // << boxname << "'" <<std::endl;
2305 // create the Layout box
2306 (*s) << " load wx"<<std::endl;
2307 (*s) << " new LayoutLine layout"<<std::endl;
2308 // create the output 'Widget'
2309 (*s) << " output Widget layout.Widget Widget"<<std::endl;
2310 // the box change output
2311 (*s) << " new MultipleInputs change"<<std::endl;
2312 (*s) << " output BoxChange change.Out BoxChange"<<std::endl;
2314 // Browse the inputs of the box in order to find which ones are not
2315 // connected and can be adapted from a widget adaptor
2316 // vector which stores the list of inputs of the box which must be connected
2317 std::vector<std::string> in;
2319 Factory::Pointer F = mVirtualExecuter->GetFactory();
2321 Package::Pointer user = F->GetPackage("user");
2323 ComplexBlackBoxDescriptor::Pointer workspace =
2324 mRealExecuter.lock()->GetCurrentDescriptor();
2329 bbtkError("interpreter::CreateGUI : could not access the executer currently defined complex box");
2334 (ComplexBlackBoxDescriptor::Pointer)(user->GetBlackBoxMap().find("workspace")->second.get());
2337 BlackBox::Pointer box = workspace->GetPrototype()->bbGetBlackBox(boxname);
2338 // BlackBox::InputConnectorMapType incm = box->bbGetInputConnectorMap();
2340 BlackBox::InputConnectorMapType::iterator i;
2341 for (i=box->bbGetInputConnectorMap().begin();
2342 i!=box->bbGetInputConnectorMap().end();
2345 // If the input is connected : continue
2346 if (i->second->IsConnected()) continue;
2347 // Get the input descriptor
2348 const BlackBoxInputDescriptor* d = box->bbGetDescriptor()->GetInputDescriptor(i->first);
2349 // If it is a "system" input : skip it
2350 #ifdef USE_WXWIDGETS
2351 if ( ( d->GetCreatorTypeInfo() == typeid(AtomicBlackBoxDescriptor)) ||
2352 ( d->GetCreatorTypeInfo() == typeid(WxBlackBoxDescriptor)) )
2355 if ( ( d->GetCreatorTypeInfo() == typeid(AtomicBlackBoxDescriptor)) )
2359 std::string widget,adaptor;
2360 // try to find a widget adaptor
2361 if (F->FindWidgetAdaptor(DataInfo(d->GetTypeInfo(),""),
2365 // command to create the adaptor
2366 (*s) << " new "<<adaptor<<" "<<i->first<<std::endl;
2367 // Sets the label of the widget adaptor to the name of the input
2368 (*s) << " set "<<i->first<<".Label "<<i->first<<std::endl;
2369 // Sets the initial value of the widget to the value of the input
2370 (*s) << " set "<<i->first<<".In \" "
2371 <<box->bbGetInputAsString(i->first)<<"\""
2373 // store the input name
2374 in.push_back(i->first);
2375 (*s) << " connect "<<i->first<<".Widget layout.Widget"<<in.size()<<std::endl;
2376 //<i->first<<"'"<<std::endl;
2377 (*s) << " connect "<<i->first<<".BoxChange change.In"<<in.size()<<std::endl;
2379 // try to find a two pieces adaptor
2380 else if (F->FindWidgetAdaptor2(DataInfo(d->GetTypeInfo(),""),
2384 // command to create the widget
2385 (*s) << " new "<<widget<<" "<<i->first<<"Widget"<<std::endl;
2386 // command to create the adaptor
2387 (*s) << " new "<<adaptor<<" "<<i->first<<std::endl;
2389 (*s) << " connect "<<i->first<<"Widget.Out "
2390 <<i->first<<".In"<<std::endl;
2391 // Sets the label of the widget adaptor to the name of the input
2392 (*s) << " set "<<i->first<<"Widget.Label "<<i->first<<std::endl;
2393 // Sets the initial value of the widget to the value of the input
2394 (*s) << " set "<<i->first<<"Widget.In \" "
2395 <<box->bbGetInputAsString(i->first)<<"\""<< std::endl;
2396 // store the input name
2397 in.push_back(i->first);
2398 (*s) << " connect "<<i->first<<"Widget.Widget layout.Widget"<<in.size()<<std::endl;
2399 //<i->first<<"'"<<std::endl;
2400 (*s) << " connect "<<i->first<<"Widget.BoxChange change.In"<<in.size()<<std::endl;
2403 // try to find an adaptor from string
2404 // If found then can create a text input which
2405 // will be automatically adapted
2406 else if (F->FindAdaptor(DataInfo(typeid(std::string),""),
2410 // command to create the adaptor
2411 (*s) << " new InputText "<<i->first<<std::endl;
2412 // Sets the label of the widget adaptor to the name of the input
2413 (*s) << " set "<<i->first<<".Title "<<i->first<<std::endl;
2414 // Sets the initial value of the widget to the value of the input
2415 (*s) << " set "<<i->first<<".In \" "
2416 <<box->bbGetInputAsString(i->first)<<"\""<< std::endl;
2417 // store the input name
2418 in.push_back(i->first);
2419 (*s) << " connect "<<i->first<<".Widget layout.Widget"<<in.size()<<std::endl;
2420 //<i->first<<"'"<<std::endl;
2421 (*s) << " connect "<<i->first<<".BoxChange change.In"<<in.size()<<std::endl;
2430 // command to create the output
2431 (*s) << " output "<<i->first<<" "
2432 <<i->first<<".Out "<<i->first<<std::endl;
2433 // <<" Output of the widget which allows to set "
2437 // Inputs for window properties
2438 (*s) << " input WinTitle layout.WinTitle Title"<<std::endl;
2439 (*s) << " input WinWidth layout.WinWidth Width"<<std::endl;
2440 (*s) << " input WinHeight layout.WinHeight Height"<<std::endl;
2441 (*s) << " input WinDialog layout.WinDialog Dialog"<<std::endl;
2442 (*s) << " input WinHide layout.WinHide Hide"<<std::endl;
2446 // Execute the box executes the layout
2447 (*s) << " exec layout" << std::endl;
2448 (*s) << "endefine" << std::endl;
2449 // (*s) << "help "<< typeName<< std::endl;
2450 // instanciate the box and connect it
2451 (*s) << "new "<<typeName<<" "<<instanceName<<std::endl;
2453 std::vector<std::string>::iterator j;
2454 for (j=in.begin();j!=in.end();++j)
2457 (*s) << "connect "<<instanceName<<"."<<*j<<" "
2458 << boxname<<"."<<*j<<std::endl;
2460 // That's all folks ! now execute the commands :
2463 //=======================================================================
2467 //==========================================================================
2468 void Interpreter::commandDebug(const std::string& name)
2470 if ((name.length()==2)&&(name[0]=='-'))
2474 bbtk::StaticInitTime::PrintObjectListInfo = true;
2478 // int o = MessageManager::GetMessageLevel("debug");
2479 // if (o<2) MessageManager::SetMessageLevel("debug",2);
2480 mVirtualExecuter->GetFactory()->Check();
2481 // MessageManager::SetMessageLevel("debug",o);
2486 Object:: PrintObjectListInfo(name);
2489 //==========================================================================
2492 //==========================================================================
2493 // Adds a callback when 'break' command issued
2494 void Interpreter::AddBreakObserver( BreakCallbackType c )
2496 mBreakSignal.connect(c);
2498 //==========================================================================
2501 //==========================================================================
2502 std::string Interpreter::GetObjectName() const
2504 return std::string("Interpreter");
2506 //==========================================================================
2508 //==========================================================================
2509 std::string Interpreter::GetObjectInfo() const
2511 std::stringstream i;
2514 //==========================================================================
2516 //==========================================================================
2517 size_t Interpreter::GetObjectSize() const
2519 size_t s = Superclass::GetObjectSize();
2520 s += Interpreter::GetObjectInternalSize();
2523 //==========================================================================
2524 //==========================================================================
2525 size_t Interpreter::GetObjectInternalSize() const
2527 size_t s = sizeof(Interpreter);
2530 //==========================================================================
2531 //==========================================================================
2532 size_t Interpreter::GetObjectRecursiveSize() const
2534 size_t s = Superclass::GetObjectRecursiveSize();
2535 s += Interpreter::GetObjectInternalSize();
2536 s += mVirtualExecuter->GetObjectRecursiveSize();
2539 //==========================================================================