]> Creatis software - bbtk.git/blob - kernel/src/bbtkInterpreter.cxx
*** empty log message ***
[bbtk.git] / kernel / src / bbtkInterpreter.cxx
1 /*=========================================================================
2                                                                                 
3   Program:   bbtk
4   Module:    $RCSfile: bbtkInterpreter.cxx,v $ $
5   Language:  C++
6   Date:      $Date: 2008/10/08 14:59:25 $
7   Version:   $Revision: 1.76 $
8                                                                                 
9   Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
10   l'Image). All rights reserved. See Doc/License.txt or
11   http://www.creatis.insa-lyon.fr/Public/bbtk/License.html for details.
12
13      This software is distributed WITHOUT ANY WARRANTY; without even
14      the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15      PURPOSE.  See the above copyright notices for more information.
16                                                                                 
17 =========================================================================*/
18 /**
19  *  \file 
20  *  \brief class Interpreter :
21  */
22
23 #include "bbtkInterpreter.h"
24 #include "bbtkExecuter.h"
25 #include "bbtkTranscriptor.h"
26 #include "bbtkMessageManager.h"
27 #include "bbtkConfigurationFile.h"
28 #include "bbtkUtilities.h"
29 #include "bbtkWxBlackBox.h"
30 #include <sys/stat.h>
31 #include <algorithm>
32 #ifdef CMAKE_HAVE_TERMIOS_H
33 #include <termios.h>
34 #define BBTK_USE_TERMIOS_BASED_PROMPT
35 #endif
36
37 #include <string>
38
39 namespace bbtk
40 {
41
42  //=======================================================================
43   Interpreter::Pointer Interpreter::New(const std::string& cpp_file) 
44   {
45     bbtkDebugMessage("Kernel",9,"Interpreter::New('"<<cpp_file<<"')"<<std::endl);
46     return MakePointer(new Interpreter(cpp_file));
47   }
48  //=======================================================================
49
50  //=======================================================================
51   Interpreter::Pointer Interpreter::New(VirtualExec::Pointer e) 
52   {
53     bbtkDebugMessage("Kernel",9,"Interpreter::New(VirtualExec)"<<std::endl);
54     return MakePointer(new Interpreter(e));
55   }
56  //=======================================================================
57
58  //=======================================================================
59   Interpreter::Interpreter(const std::string& cpp_file) 
60   {
61     Init(VirtualExec::Pointer(), cpp_file);
62   }
63   //=======================================================================
64
65  //=======================================================================
66   Interpreter::Interpreter(VirtualExec::Pointer e) 
67   {
68     Init(e,"");
69   }
70   //=======================================================================
71
72   //=======================================================================
73   void Interpreter::Init(VirtualExec::Pointer e, const std::string& cpp_file) 
74   {
75     mUser = 0;
76     mCommandLine = false;
77     mThrow = false;
78     bufferNb =0;  
79     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);
80     bbtk::MessageManager::RegisterMessageType("Interpreter","Messages of the interpreter",0);
81     bbtkDebugMessageInc("Interpreter",9,"Interpreter::Interpreter()" <<std::endl);
82     if (e)
83       {
84         mVirtualExecuter = e;
85       }
86     else if (cpp_file.size()!=0)
87       {
88         mVirtualExecuter = boost::static_pointer_cast<VirtualExec>(bbtk::Transcriptor::New(cpp_file));
89       }
90     else 
91       {
92         bbtk::Executer::Pointer exe = bbtk::Executer::New();
93         mRealExecuter = exe;
94         mVirtualExecuter = boost::static_pointer_cast<VirtualExec>(exe);
95       }
96
97     // Lock this pointer or will auto-destruct !!
98     if (!e) mVirtualExecuter->SetInterpreter(MakePointer(this,true));
99     
100     // For the time being, comment out previous line, and
101     // uncomment next line to check Transcriptor
102
103     //mVirtualExecuter = new bbtk::Transcriptor("GeneratedProgram.txt");
104
105     // Builds the commands dict
106     CommandInfoType info;
107    
108     info.keyword = "new";
109     info.argmin = 2;
110     info.argmax = 2;
111     info.code = cNew;
112     info.syntax = "new <type> <name>";
113     info.help = "Creates a new black box of type <type> with name <name>";
114     mCommandDict[info.keyword] = info;
115     
116     info.keyword = "delete";
117     info.argmin = 1;
118     info.argmax = 1;
119     info.code = cDelete;
120     info.syntax = "delete <box>";
121     info.help = "Deletes the black box of name <box>";
122     mCommandDict[info.keyword] = info;
123
124     info.keyword = "newgui";
125     info.argmin = 2;
126     info.argmax = 2;
127     info.code = cNewGUI;
128     info.syntax = "newgui <box> <name>";
129     info.help = "Automatically creates a graphical user interface with name <name> for the black box <box> and connects it to the box inputs";
130     mCommandDict[info.keyword] = info;
131
132     info.keyword = "connect";
133     info.argmin = 2;
134     info.argmax = 2;
135     info.code = cConnect;
136     info.syntax = "connect <box1.output> <box2.input>";
137     info.help = "Connects the ouput <output> of black box <box1> to the input <input> of black box <box2>";
138     mCommandDict[info.keyword] = info;
139
140     info.keyword = "print";
141     info.argmin = 1;
142     info.argmax = 1;
143     info.code = cPrint;
144     info.syntax = "print <string>";
145     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').";
146     mCommandDict[info.keyword] = info;
147
148     info.keyword = "exec";
149     info.argmin = 1;
150     info.argmax = 2;
151     info.code = cExec;
152     info.syntax = "exec <box | 'freeze' | 'unfreeze' | 'freeze_no_error' >";
153     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.";
154     mCommandDict[info.keyword] = info;
155
156     info.keyword = "package";
157     info.argmin = 1;
158     info.argmax = 1;
159     info.code = cPackage;
160     info.syntax = "package <name>";
161     info.help = "Begins the definition of a package.";
162     mCommandDict[info.keyword] = info;
163     
164     info.keyword = "endpackage";
165     info.argmin = 0;
166     info.argmax = 0;
167     info.code = cEndPackage;
168     info.syntax = "endpackage";
169     info.help = "Ends the definition of a package.";
170     mCommandDict[info.keyword] = info;
171
172     info.keyword = "define";
173     info.argmin = 1;
174     info.argmax = 2;
175     info.code = cDefine;
176     info.syntax = "define <type> [<package>]";
177     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.";
178     mCommandDict[info.keyword] = info;
179     
180     info.keyword = "endefine";
181     info.argmin = 0;
182     info.argmax = 0;
183     info.code = cEndDefine;
184     info.syntax = "endefine";
185     info.help = "Ends the definition of a new type of complex black box";
186     mCommandDict[info.keyword] = info;
187
188     info.keyword = "kind";
189     info.argmin = 1;
190     info.argmax = 1;
191     info.code = cKind;
192     info.syntax = "kind <ADAPTOR|DEFAULT_ADAPTOR|WIDGET_ADAPTOR|DEFAULT_WIDGET_ADAPTOR>";
193     info.help = "Sets the kind of the currently defined complex black box";
194     mCommandDict[info.keyword] = info;
195
196     info.keyword = "input";
197     info.argmin = 3;
198     info.argmax = 3;
199     info.code = cInput;
200     info.syntax = "input <name> <box.input> <help>";
201     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";
202     mCommandDict[info.keyword] = info;
203
204     info.keyword = "output";
205     info.argmin = 3;
206     info.argmax = 3;
207     info.code = cOutput;
208     info.syntax = "output <name> <box.output> <help>";
209     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";
210     mCommandDict[info.keyword] = info;
211
212     info.keyword = "set";
213     info.argmin = 2;
214     info.argmax = 2;
215     info.code = cSet;
216     info.syntax = "set <box.input> <value>";
217     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";
218     mCommandDict[info.keyword] = info;
219    
220     info.keyword = "config";  // JPR
221     info.argmin = 0;
222     info.argmax = 0;
223     info.code = cConfig;
224     info.syntax = "config";
225     info.help = "Prints the value of all configuration parameters";
226     mCommandDict[info.keyword] = info;
227
228     info.keyword = "index";  // LG
229     info.argmin = 0;
230     info.argmax = 2;
231     info.code = cIndex;
232
233     info.syntax = "index [<filename> ['Initials'(default)|'Packages'|'Categories'|'Adaptors']]";
234     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.";
235     mCommandDict[info.keyword] = info;
236
237     info.keyword = "reset";  
238     info.argmin = 0;
239     info.argmax = 0;
240     info.code = cReset;
241     info.syntax = "reset";
242     info.help = "Deletes all boxes and unloads all packages (reset to start state)";
243     mCommandDict[info.keyword] = info;
244
245     info.keyword = "author";
246     info.argmin = 1;
247     info.argmax = 1;
248     info.code = cAuthor;
249     info.syntax = "author <string>";
250     info.help = "Adds the string <string> to the author information of the black box being defined";
251     mCommandDict[info.keyword] = info;
252     
253     info.keyword = "category"; //JP
254     info.argmin = 1;
255     info.argmax = 1;
256     info.code = cCategory;
257     info.syntax = "category <list of items, separated by ;>";
258     info.help = "Adds the string <string> to the category information of the black box being defined";
259     mCommandDict[info.keyword] = info;
260
261     info.keyword = "description";
262     info.argmin = 1;
263     info.argmax = 1;
264     info.code = cDescription;
265     info.syntax = "description <string>";
266     info.help = "Adds the string <string> to the descriptive information of the black box being defined";
267     mCommandDict[info.keyword] = info;
268
269     info.keyword = "help";
270     info.argmin = 0;
271     info.argmax = 2;
272     info.code = cHelp;
273     info.syntax = "help";
274     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>";
275     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.";
276     mCommandDict[info.keyword] = info;
277
278     info.keyword = "message";
279     info.argmin = 0;
280     info.argmax = 2;
281     info.code = cMessage;
282     info.syntax = "message <kind> <level>";
283     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.";  
284     mCommandDict[info.keyword] = info;
285
286     info.keyword = "include";
287     info.argmin = 1;
288     info.argmax = 2;
289     info.code = cInclude;
290     info.syntax = "include <filename> [source]";
291     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).";
292     mCommandDict[info.keyword] = info;
293
294     info.keyword = "quit";
295     info.argmin = 0;
296     info.argmax = 0;
297     info.code = cQuit;
298     info.syntax = "quit";
299     info.help = "Quits the program (during script execution it stops the complete execution)";
300     mCommandDict[info.keyword] = info;
301
302     info.keyword = "load";
303     info.argmin = 1;
304     info.argmax = 1;
305     info.code = cLoad;
306     info.syntax = "load <packagename>";
307     info.help = "Loads the black box package <packagename>";
308     mCommandDict[info.keyword] = info;
309
310     info.keyword = "unload";
311     info.argmin = 1;
312     info.argmax = 1;
313     info.code = cUnload;
314     info.syntax = "unload <packagename>";
315     info.help = "Unloads the black box package <packagename>";
316     mCommandDict[info.keyword] = info;
317
318     info.keyword = "graph";
319     info.argmin = 0;
320     info.argmax = 6;
321     info.code = cGraph;
322     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 ]]]]]]";
323     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')";
324     mCommandDict[info.keyword] = info;
325
326     info.keyword = "debug";
327     info.argmin = 0;
328     info.argmax = 1;
329     info.code = cDebug;
330     info.syntax = "debug [expr|-C|-D]";
331     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";
332     mCommandDict[info.keyword] = info;
333
334     /*
335     info.keyword = "workspace";
336     info.argmin = 1;
337     info.argmax = 2;
338     info.code = cWorkspace;
339     info.syntax = "workspace < ( freeze | unfreeze ) | ( rename <newname> ) >";
340     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.";
341     mCommandDict[info.keyword] = info;
342     */
343
344     bbtkDebugDecTab("Interpreter",9);
345
346   } 
347   //=======================================================================
348   
349   
350   
351   //=======================================================================  
352   /**
353    *  
354    */
355   Interpreter::~Interpreter()
356   {
357     bbtkDebugMessageInc("Interpreter",9,"==> Interpreter::~Interpreter()" <<std::endl);
358     mVirtualExecuter = VirtualExec::Pointer();
359     bbtkDebugMessageInc("Interpreter",9,"<== Interpreter::~Interpreter()" <<std::endl);
360   }
361   //=======================================================================
362
363
364   InterpreterError::InterpreterError( const std::string& message,
365                                       bool in_script_file,
366                                       const std::string& script_file,
367                                       int script_line 
368                                       )
369     : Exception("Interpreter",0,message),
370       mInScriptFile(in_script_file),
371       mScriptFile(script_file),
372       mScriptLine(script_line)
373   {
374   }
375   InterpreterError::InterpreterError( const Exception& excep,
376                       bool in_script_file,
377                       const std::string& script_file,
378                       int script_line 
379                       )
380     : Exception(excep),
381       mInScriptFile(in_script_file),
382       mScriptFile(script_file),
383       mScriptLine(script_line)
384   {
385   }
386   //=======================================================================
387   void Interpreter::CatchBbtkException( const bbtk::Exception& e )
388   {
389     if (mThrow) 
390       {
391         bool in_script = false;
392         std::string file("");
393         int line = 0;
394         if (mFileName.size()) {
395           std::ifstream* fs = dynamic_cast<std::ifstream*>(mFile.back());
396           if (fs!=0) in_script = true;    
397           file = mFileName.back();
398           line = mLine.back();
399         }   
400         CloseAllFiles();
401         throw InterpreterError(e,in_script,file,line);
402       }
403     else
404       {
405         std::stringstream mess;
406         mess << "* ERROR : "<<e.GetErrorMessage()<<std::endl;
407         if (mFileName.size()) {
408           mess << "* FILE  : \""<<mFileName.back()<<"\""<<std::endl;
409           mess << "* LINE  : "<<mLine.back()<<std::endl;
410         }    
411         std::cerr << mess.str();
412       }
413   }
414   //=======================================================================
415   
416   //=======================================================================
417   void Interpreter::CatchStdException( const std::exception& e )
418   {  
419     if (mThrow) 
420       {
421         bool in_script = false;
422         std::string file("");
423         int line = 0;
424         if (mFileName.size()) {
425           std::ifstream* fs = dynamic_cast<std::ifstream*>(mFile.back());
426           if (fs!=0) in_script = true;    
427           file = mFileName.back();
428           line = mLine.back();
429         }    
430         CloseAllFiles();
431         throw InterpreterError(e.what(),in_script,file,line);
432       }
433     else
434       {
435         std::stringstream mess;
436         mess << "* ERROR : "<<e.what()<<std::endl;
437         if (mFileName.size()) {
438           mess << "* FILE  : \""<<mFileName.back()<<"\""<<std::endl;
439           mess << "* LINE  : "<<mLine.back()<<std::endl;
440         }    
441         std::cerr << mess.str();
442       }
443   }
444   //=======================================================================
445
446   //=======================================================================
447   void Interpreter::CatchUnknownException()
448   {
449     if (mThrow) 
450       {
451         bool in_script = false;
452         std::string file("");
453         int line = 0;
454         if (mFileName.size()) {
455           std::ifstream* fs = dynamic_cast<std::ifstream*>(mFile.back());
456           if (fs!=0) in_script = true;    
457           file = mFileName.back();
458           line = mLine.back();
459         }    
460         CloseAllFiles();
461         throw InterpreterError("Unknown exception caught",
462                                    in_script,file,line);
463       }
464     else
465       {
466         std::stringstream mess;
467         mess << "* UNDEFINED ERROR (not a bbtk nor a std exception)" 
468              << std::endl;
469         if (mFileName.size()) {
470           mess << "* FILE  : \""<<mFileName.back()<<"\""<<std::endl;
471           mess << "* LINE  : "<<mLine.back()<<std::endl;
472         }    
473         std::cerr << mess.str();
474       }
475   }
476   //=======================================================================
477
478   //=======================================================================
479
480 #define CATCH_MACRO                             \
481   catch (QuitException e)                       \
482     {                                           \
483       status = Interpreter_QUIT;                \
484       if (mThrow) throw QuitException();        \
485     }                                           \
486   catch (bbtk::Exception e)                     \
487     {                                           \
488       status = Interpreter_ERROR;               \
489       CatchBbtkException(e);                    \
490     }                                           \
491   catch (std::exception& e)                     \
492     {                                           \
493       status = Interpreter_ERROR;               \
494       CatchStdException(e);                     \
495     }                                           \
496   catch (...)                                   \
497     {                                           \
498       status = Interpreter_ERROR;               \
499       CatchUnknownException();                  \
500     }                                           
501   //=======================================================================
502    
503
504   //=======================================================================
505   /**
506    *  
507    */
508   Interpreter::ExitStatus Interpreter::InterpretFile( const std::string& filename, bool source )
509   {
510     bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretFile(\""<<filename<<"\")"<<std::endl);
511
512     bool exm = mCommandLine;
513     mCommandLine = false;
514
515     ExitStatus status = Interpreter_OK;
516
517     try 
518     {
519       SwitchToFile(filename,source);
520
521       bool insideComment = false; // for multiline comment
522       while (mFile.size()>0) 
523       {
524         while (!mFile.back()->eof()) {
525           mLine.back()++;
526           char buf[500];
527           mFile.back()->getline(buf,500);
528           std::string str(buf);
529           int size=str.length();
530           if ( str[ size-1 ]==13  )
531             {
532               str.erase(size-1,1);
533             }
534           try
535             {
536               InterpretLine(str, insideComment);
537             }
538           CATCH_MACRO;
539           
540        }//while !eof
541        CloseCurrentFile();
542       }//while >0
543     } // try
544     CATCH_MACRO;
545     
546     CloseAllFiles();
547     bbtkDebugMessage("Interpreter",9,"EO Interpreter::InterpretFile(\""<<filename<<"\")"<<std::endl);
548     bbtkDecTab("Interpreter",9);
549
550     mCommandLine = exm;
551     
552     return status;
553   }
554   //=======================================================================
555
556
557   //=======================================================================
558   /**
559    *  
560    */
561   Interpreter::ExitStatus 
562   Interpreter::InterpretBuffer( std::stringstream* buffer )
563   {
564     bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretBuffer()"<<std::endl);
565
566     bool exm = mCommandLine;
567     mCommandLine = false;
568
569     ExitStatus status = Interpreter_OK;
570
571     try 
572     {
573       SwitchToStream(buffer);
574       bool insideComment = false; // for multiline comment
575       while (mFile.size()>0) 
576       {
577         while (!mFile.back()->eof()) {
578           mLine.back()++;
579           char buf[500];
580           mFile.back()->getline(buf,500);
581           std::string str(buf);
582           
583           int size=str.length();
584           if ( str[ size-1 ]==13  )
585             {
586               str.erase(size-1,1);
587             }
588           try
589             {
590               InterpretLine(str, insideComment);
591             }
592           CATCH_MACRO;
593         }//while
594         CloseCurrentFile();
595       }
596     }
597     CATCH_MACRO;
598     
599     CloseAllFiles();
600     bbtkDebugMessage("Interpreter",9,"EO Interpreter::InterpretBuffer()"<<std::endl);
601     bbtkDecTab("Interpreter",9);
602     
603     mCommandLine = exm;
604     return status;
605   }
606   //=======================================================================
607
608   //=======================================================================
609   /// Runs the interpretation of a command
610   Interpreter::ExitStatus Interpreter::InterpretLine( const std::string& line )
611   {
612     bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretLine('"<<line<<"')"<<std::endl);
613
614     ExitStatus status = Interpreter_OK;
615
616     try 
617     {
618       bool insideComment = false;
619       InterpretLine(line, insideComment);
620     }
621     CATCH_MACRO;
622   
623
624     bbtkDebugMessage("Interpreter",9,"EO Interpreter::InterpretLine()"
625                      <<std::endl);
626     bbtkDecTab("Interpreter",9);
627     
628     return status;
629   }
630   
631
632   //=======================================================================  
633   /**
634    *
635    */
636 void Interpreter::InterpretLine( const std::string& line, bool &insideComment )
637 {
638     bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretLine(\""<<line<<"\")"<<std::endl);
639     bbtkMessage("echo",2,line<<std::endl);
640
641     std::vector<std::string> words;
642     SplitLine(line,words);
643
644     // Empty line
645     if (words.size()<1) 
646     {
647        bbtkDebugDecTab("Interpreter",9);
648        return;
649     }
650
651     // Single line comment : # or //
652     if ( words[0][0]=='#' || (words[0][0]=='/' && words[0][1]=='/') ) 
653     {  
654        bbtkDebugDecTab("Interpreter",9);
655        bbtkMessage("Interpreter",9,"Comment"<<std::endl);
656        return;
657     }
658
659     // Multi line comment ( /* ... */ ) -delimiters on different lines !-
660     
661     if (words[0][0]=='/' && words[0][1]=='*') 
662     {  
663        bbtkDebugDecTab("Interpreter",9);
664        bbtkMessage("Interpreter",9,"In multiline comment"<<std::endl);
665        insideComment = true;
666        return;
667     }
668
669     if (words[0][0]=='*' && words[0][1]=='/') 
670     {  
671        bbtkDebugDecTab("Interpreter",9);
672        bbtkMessage("Interpreter",9,"Out multiline comment"<<std::endl);
673        if ( !insideComment ) {
674           bbtkDebugDecTab("Interpreter",9);
675           bbtkMessage("Interpreter",9,"Comment mismatch : '*/' with no matching '/*'"<<std::endl);       
676        }
677        insideComment = false;
678        return;
679     }
680
681     if (insideComment) 
682     {  
683        bbtkDebugDecTab("Interpreter",9);
684        bbtkMessage("Interpreter",9,"Multiline Comment"<<std::endl);
685        return;
686     }
687
688     // Command 
689     CommandInfoType command;
690     InterpretCommand(words,command);
691
692     bbtkDebugMessage("Interpreter",9,
693                      "Command='"<<command.keyword
694                       <<"' code="<<command.code<<std::endl); 
695     int level=0;
696     std::string left,right,left2,right2;
697     std::string filename;
698     switch (command.code) 
699     {
700       case cNew :
701         mVirtualExecuter->Create(words[1],words[2]);
702         break;
703
704       case cDelete :
705         mVirtualExecuter->Destroy(words[1]);
706         break;
707
708       case cConnect :
709         Utilities::SplitAroundFirstDot(words[1],left,right);
710         Utilities::SplitAroundFirstDot(words[2],left2,right2);      
711         mVirtualExecuter->Connect(left,right,left2,right2);
712         break;
713
714       case cPackage :
715         mVirtualExecuter->BeginPackage(words[1]);
716         break;
717
718       case cEndPackage :
719         mVirtualExecuter->EndPackage();
720         break;
721
722       case cDefine :
723         if (mFileName.size()>0) 
724         {
725                    filename = mFileName.back(); //mIncludeFileName.back(); //Utilities::get_file_name(mFileName.back());
726         }
727         if (words.size()==2) 
728         {
729            mVirtualExecuter->Define(words[1],"",filename);
730         }
731         else
732         {
733            mVirtualExecuter->Define(words[1],words[2],filename);
734         }
735         break;
736
737       case cEndDefine :
738         mVirtualExecuter->EndDefine();
739         break;
740
741       case cKind :
742         mVirtualExecuter->Kind(words[1]);
743         break;
744
745       case cPrint :
746         mVirtualExecuter->Print(words[1]);
747         break;
748         
749       case cExec :
750         if (words[1]=="freeze") 
751           {
752             mVirtualExecuter->SetNoExecMode(true);
753             mThrow = false;
754           }
755         else if (words[1]=="freeze_no_error ") 
756           {
757             mVirtualExecuter->SetNoExecMode(true);
758             mVirtualExecuter->SetNoErrorMode(true);
759             mThrow = false;
760           }
761         else if (words[1]=="unfreeze") 
762           {
763             mVirtualExecuter->SetNoExecMode(false);
764             mVirtualExecuter->SetNoErrorMode(false);
765           }
766         else
767           {
768             mVirtualExecuter->Execute(words[1]);
769           }
770         break;
771
772       case cInput :
773         Utilities::SplitAroundFirstDot(words[2],left,right);
774         mVirtualExecuter->DefineInput(words[1],left,right,words[3]);
775         break;
776
777       case cOutput :
778         Utilities::SplitAroundFirstDot(words[2],left,right);
779         mVirtualExecuter->DefineOutput(words[1],left,right,words[3]);
780         break;
781
782       case cSet :
783         Utilities::SplitAroundFirstDot(words[1],left,right);
784         mVirtualExecuter->Set(left,right,words[2]);
785         break;
786
787       case cAuthor :
788         mVirtualExecuter->Author(words[1]);
789         break;
790
791       case cNewGUI :
792         NewGUI(words[1],words[2]);
793         break;
794
795       case cCategory :
796         mVirtualExecuter->Category(words[1]);
797         break;
798
799       case cIndex :
800         if (words.size()==1)
801              Index("tmp_index.html");
802         else if (words.size()==2)
803              Index(words[1]);
804         else if (words.size()==3)
805              Index(words[1],words[2]);
806         break;
807
808       case cDescription :
809         mVirtualExecuter->Description(words[1]);
810         break;
811
812       case cHelp :
813         Help(words);
814         break;
815
816       case cMessage : 
817         if (words.size()<3)
818         {
819           mVirtualExecuter->HelpMessages();
820         }
821         else
822         {
823           sscanf(words[2].c_str(),"%d",&level);
824           mVirtualExecuter->SetMessageLevel(words[1],level);
825         }
826         break;
827
828       case cGraph :
829         Graph(words);
830         break;
831
832       case cConfig :
833         Config();
834         break;
835
836       case cReset :  
837         Reset();
838         break;
839
840       case cInclude :
841                 // if 'source' was given (words.size()==3) then tell to set the 
842                 // source file name of the current complex box with the full file name included
843                 if (mCommandLine)
844         {
845            InterpretFile(words[1],(words.size()==3)); 
846         }
847         else
848         {
849             SwitchToFile(words[1],(words.size()==3) );
850         }
851                 break;
852
853       case cLoad:
854         GetExecuter()->LoadPackage(words[1]);
855         break;
856
857       case cUnload:
858         GetExecuter()->UnLoadPackage(words[1]);
859         break;
860
861       case cQuit :
862         throw QuitException();
863         break;
864
865       case cDebug :
866         if (words.size()==2) Debug(words[1]);
867         else Debug("");
868         break;
869         /* obsolete
870       case cWorkspace :
871         if (words.size() == 2) 
872         {
873            if (words[1]=="freeze")        mVirtualExecuter->SetNoExecMode(true);
874            else if (words[1]=="unfreeze") mVirtualExecuter->SetNoExecMode(false);
875         }
876         else
877         {
878            mVirtualExecuter->SetWorkspaceName(words[2]);
879         }
880         break;
881         */
882       default:
883         bbtkInternalError("should not reach here !!!");
884    }
885
886    bbtkDecTab("Interpreter",9);
887 }
888   //=======================================================================  
889
890
891
892
893
894   //=======================================================================
895   /**
896    *
897    */
898 void Interpreter::SplitLine ( const std::string& str, std::vector<std::string>& tokens)
899 {
900     bbtkDebugMessageInc("Interpreter",9,"Interpreter::SplitLine(\""<<str<<"\")"<<std::endl);
901
902     std::string delimiters = "\"";
903     std::vector<std::string> quote;
904     Utilities::SplitString(str,delimiters,quote);
905
906     delimiters = " \t";
907     std::vector<std::string>::iterator i;
908     for (i=quote.begin(); i!=quote.end(); ) 
909     {
910        Utilities::SplitString(*i,delimiters,tokens);
911        ++i;
912        if (i!=quote.end()) 
913        {
914         //    bbtkDebugMessage("Interpreter",0,"\""<<*i<<"\""<<std::endl);
915           tokens.push_back(*i);
916           ++i;
917        }
918     }
919
920     for (i=tokens.begin(); i!=tokens.end(); ++i) 
921     {
922        bbtkDebugMessage("Interpreter",9,"["<<*i<<"] ");
923     }
924     bbtkDebugMessageCont("Interpreter",9,std::endl);
925
926     bbtkDebugDecTab("Interpreter",9);
927  }
928   //=======================================================================
929
930
931   //=======================================================================
932   void Interpreter::Reset()
933   {
934     // Cannot close all files if the reset command is read from a file !
935     //    CloseAllFiles();
936     mFileNameHistory.clear();
937     this->mVirtualExecuter->Reset();
938   }
939   //=======================================================================
940
941   //=======================================================================
942   /**
943    *
944    */
945   /*
946   void Interpreter::Print( const std::string& str)
947   {
948     if (mVirtualExecuter->GetNoExecMode()) return;
949
950     bbtkDebugMessageInc("Interpreter",9,"Interpreter::Print(\""<<str<<"\")"<<std::endl);
951
952  // TO DO :
953  // InterpretLine ("load std")
954  // InterpretLine("new ConcatStrings _C_ ") -> trouver un nom unique : # commande 
955  // InterpretLine("new Print _P_") 
956  // InterpretLine("connect _C_.Out _P_.In")
957  // int num = 1
958  
959
960     std::vector<std::string> chains;
961     std::string delimiters("$");
962
963     // Skip delimiters at beginning.
964     std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
965     bool is_text = true;
966     if (lastPos>0) is_text = false;
967
968     // Find first delimiter.
969     std::string::size_type pos     = str.find_first_of(delimiters, lastPos);
970
971     while (std::string::npos != pos || std::string::npos != lastPos)
972     {
973        if (is_text) 
974        {
975           // Found a text token, add it to the vector.
976           chains.push_back(str.substr(lastPos, pos - lastPos));
977  // std::string token = str.substr(lastPos, pos - lastPos)
978  // InterpretLine("set _C_.In%num% %token%")
979  
980        }
981        else 
982        {
983
984        // is an output (between $$) : decode 
985          std::string tok,box,output;
986          tok = str.substr(lastPos, pos - lastPos);
987          Utilities::SplitAroundFirstDot(tok,box,output);
988          chains.push_back( mVirtualExecuter->Get(box,output) );
989
990 // InterpretLine("connect %tok% _C_.In%num%") 
991
992        }
993         // Skip delimiters.  Note the "not_of"
994        lastPos = str.find_first_not_of(delimiters, pos);
995         // Find next delimiter
996        pos = str.find_first_of(delimiters, lastPos);
997     //
998        is_text = !is_text;
999 // num ++;
1000      }
1001 // InterpretLine("exec _P_")
1002 // if (IS_IN_WORKSPACE) InterpretLine("delete _C_; delete _P_");
1003
1004      std::vector<std::string>::iterator i;
1005      for (i= chains.begin(); i!=chains.end(); ++i) 
1006      {
1007
1008        Utilities::SubsBackslashN(*i);
1009        std::cout << *i;
1010      }
1011      std::cout << std::endl;
1012      bbtkDebugDecTab("Interpreter",9);
1013  }
1014 */
1015
1016   //=======================================================================
1017   /**
1018    *
1019    */
1020
1021   // =========================================================================
1022   void Interpreter::SwitchToFile( const std::string& name , bool source )
1023   {
1024   // Note : in the following :
1025   // name : the user supplied name 
1026   //      - abreviated name    e.g.       scr   scr.bbs
1027   //      - relative full name e.g.       ./scr.bbs   ../../scr.bbs 
1028   //      - absolute full name e.g.       /home/usrname/proj/dir/scr.bbs
1029   //          same for Windows, with      c:, d: ...
1030   //
1031   // use ./directory/subdir/scrname.bbs
1032   //
1033
1034     bbtkDebugMessageInc("Interpreter",9,"Interpreter::SwitchToFile( \""
1035                          <<name<<"\")"<<std::endl);
1036
1037     std::vector<std::string> script_paths;
1038     std::string fullPathScriptName;  // full path script name
1039     std::string pkgname;             // e.g. <scriptname>.bbs
1040     std::vector<std::string> Filenames;
1041
1042     // The following is *NOT* a debug time message :
1043     // It's a user intended message.
1044     // Please don't remove it.
1045     bbtkMessage("Interpreter",1,
1046         "look for : [" << name
1047         << "]" << std::endl);
1048
1049
1050     std::string upath;
1051     pkgname = Utilities::ExtractScriptName(name,upath);
1052
1053     bbtkMessage("Interpreter",3,
1054                 "package name:[" << pkgname
1055                  << "] path:[" << upath << "]" << std::endl);
1056     bool fullnameGiven = false; 
1057     bool foundFile     = false;
1058
1059     // ==== "*" provided : load all scripts in given path 
1060     // relative (e.g. std/boxes/*) or absolute 
1061     if (pkgname == "*") 
1062       {
1063
1064         std::stringstream* stream = new std::stringstream;
1065         //if (upath.size()!=0) // avoid troubles for "*"
1066         
1067         // ==== no path provided : look in root bbs path
1068         if (upath.size()==0)
1069           {
1070             //      bbtkMessage("Interpreter",1,
1071             // LG : add all bbs path
1072             //  script_paths.push_back(  ConfigurationFile::GetInstance().Get_root_bbs_path() );
1073             std::vector<std::string>::const_iterator i;
1074             for (i=ConfigurationFile::GetInstance().Get_bbs_paths().begin();
1075                  i!=ConfigurationFile::GetInstance().Get_bbs_paths().end();
1076                  i++)
1077               {
1078                 script_paths.push_back(*i);
1079               }
1080           }
1081         // ==== absolute path provided 
1082         else if (upath[0]=='/' || upath[1] == ':' ) 
1083           {
1084             if ( Utilities::IsDirectory( upath ) )
1085               {
1086                 script_paths.push_back(upath);
1087               }
1088             else 
1089               {
1090                 bbtkError("'"<<upath<<"' : directory does not exist"); 
1091               }
1092           }
1093         // ==== relative path provided : search all bbs path appended with 
1094         // the relative path provided
1095         else
1096           {    
1097             std::vector<std::string>::const_iterator i;
1098             for (i=ConfigurationFile::GetInstance().Get_bbs_paths().begin();
1099                  i!=ConfigurationFile::GetInstance().Get_bbs_paths().end();
1100                  i++)
1101               {
1102                 std::string full_path(*i);
1103                 // we *really* want '.' to be the current working directory
1104                 if (full_path == ".") 
1105                   {
1106                     char buf[2048]; // for getcwd
1107                     char * currentDir = getcwd(buf, 2048);
1108                     std::string cwd(currentDir);
1109                     full_path = currentDir;
1110                   } // if full_path
1111                 
1112                 full_path += ConfigurationFile::GetInstance().Get_file_separator();
1113                 full_path += upath;
1114                 
1115                 if ( Utilities::IsDirectory( full_path ) )
1116                   {
1117                     script_paths.push_back(full_path);
1118                   }
1119               } 
1120             if (script_paths.empty())
1121               {
1122                 bbtkError("no '"<<upath<<"' subdir found in search paths" 
1123                           << std::endl);
1124               }
1125           }
1126         
1127         
1128         // === search paths list complete : now explore it
1129         int nbBssFiles = 0;     
1130         // ==== relative name, iterate + load all .bbs/.bbp files
1131         std::vector<std::string>::iterator i;
1132         for (i=script_paths.begin();i!=script_paths.end();i++)
1133           {
1134             bbtkMessage("Interpreter",1,
1135                         "--> Looking in '" << *i << "'" << std::endl);
1136             
1137             Filenames.clear();
1138             //int nbFiles = 
1139             Utilities::Explore(*i, false, Filenames);
1140             
1141             for (std::vector<std::string>::iterator j = Filenames.begin(); 
1142                  j!= Filenames.end(); ++j)
1143               {
1144                 int lgr = (*j).size();
1145                 if (lgr < 5) continue;  
1146                 // ignore non .bbp file
1147                 if ( (*j).substr(lgr-4, 4) != ".bbp") continue; 
1148                 
1149                 (*stream) << "include \"" << *j << "\"\n";
1150                 bbtkMessage("Interpreter",2,"  --> Found '" << *j << "'" << std::endl);
1151                 
1152                 nbBssFiles++;
1153               } // for (std::vector...
1154           } // for (i=script_...
1155
1156         // === Result ...
1157         if (nbBssFiles==0)
1158           {
1159             bbtkMessage("Interpreter",1,
1160                         "  --> No .bbp found"<< std::endl);
1161           } 
1162         else 
1163           {
1164             bbtkMessage("Interpreter",1,
1165                         "  --> "<<nbBssFiles<<" .bbp found"<< std::endl);
1166             SwitchToStream(stream);
1167           }
1168         return;
1169       }  
1170     //=============== end pkgname=="*" ===========
1171     
1172     
1173     // if name starts with a / or a . or contains : user is assumed to have passed a relative/absolute name
1174     // (not only a plain script name)
1175     // we trust him, and try to expland the directory name
1176     // WARNING : starting from current local directory :  ./whatYouWant  (./ mandatory!)
1177
1178     if (name[0]=='/' || name[1] == ':' || name[0]=='.')  // absolute path (linux/windows) or relative path
1179     { 
1180
1181       // ===========================================================check user supplied location
1182       fullnameGiven = true;
1183
1184       fullPathScriptName =  Utilities::ExpandLibName(name, false);
1185
1186       // allow user to always forget ".bbs"
1187       int l = fullPathScriptName.size();
1188
1189       if (l!=0) 
1190           {
1191          if ((fullPathScriptName.substr(l-4, 4) != ".bbs")&&
1192                          (fullPathScriptName.substr(l-4, 4) != ".bbp"))
1193          {
1194                         std::string tfullPathScriptName = fullPathScriptName + ".bbs";
1195                         if ( Utilities::FileExists(tfullPathScriptName) )
1196                         {
1197                                 fullPathScriptName = tfullPathScriptName;
1198                                 foundFile = true;
1199                         }
1200                         else 
1201                         {
1202                                 tfullPathScriptName = fullPathScriptName + ".bbp";
1203                                 if ( Utilities::FileExists(tfullPathScriptName) )
1204                                 {
1205                                         fullPathScriptName = tfullPathScriptName;
1206                                         foundFile = true;
1207                                 }
1208                         }
1209                  }
1210                  else 
1211                  {
1212                         if ( Utilities::FileExists(fullPathScriptName) )
1213                         {
1214                                 foundFile = true;
1215                         }
1216                  }
1217           } // endif l != 0
1218   }
1219   else
1220   // =============================== iterate on the paths
1221   {
1222       script_paths = ConfigurationFile::GetInstance().Get_bbs_paths();
1223       std::string path;
1224       std::vector<std::string>::iterator i;
1225       for (i=script_paths.begin();i!=script_paths.end();++i)
1226           {
1227                 path = *i;
1228                 // we *really* want '.' to be the current working directory
1229                 if (path == ".") 
1230                 {
1231                         char buf[2048]; // for getcwd
1232                         char * currentDir = getcwd(buf, 2048);
1233                         std::string cwd(currentDir);
1234                         path = currentDir;
1235                 }
1236           
1237                 std::string tfullPathScriptName = Utilities::MakePkgnameFromPath(path, name, false);
1238                 if (tfullPathScriptName.substr(tfullPathScriptName.size()-4, 3)==".bb")
1239                 {
1240                   fullPathScriptName = tfullPathScriptName;
1241                         if ( ! Utilities::FileExists(fullPathScriptName) )
1242                         {
1243                                 // The following is *NOT* a debug time message :
1244                                 // It's a user intended message.
1245                                 // Please don't remove it.
1246                                 bbtkMessage("Interpreter",2,
1247                           "   [" <<fullPathScriptName <<"] : does not exist" 
1248                           <<std::endl);
1249                                 continue;  // try next path
1250                         }
1251                         bbtkMessage("Interpreter",2,
1252                               "   [" <<fullPathScriptName 
1253                                   <<"] : found" <<std::endl);
1254                         foundFile = true;
1255                         break; // a script was found; we stop iterating
1256                 }
1257                 else 
1258                 {
1259                         fullPathScriptName = tfullPathScriptName + ".bbs";
1260                         // Check if library exists
1261                         if ( ! Utilities::FileExists(fullPathScriptName) )
1262                         {
1263                                 fullPathScriptName = tfullPathScriptName + ".bbp";
1264                                 if ( ! Utilities::FileExists(fullPathScriptName) )
1265                                 {
1266                                         // The following is *NOT* a debug time message :
1267                                         // It's a user intended message.
1268                                         // Please don't remove it.
1269                                         bbtkMessage("Interpreter",2,
1270                                         "   [" <<tfullPathScriptName <<".bbs/.bbp] : do not exist" 
1271                                         <<std::endl);
1272                                         continue;  // try next path
1273                                 }
1274                         }
1275                         bbtkMessage("Interpreter",2,
1276                       "   [" <<fullPathScriptName 
1277                       <<"] : found" <<std::endl);
1278                         foundFile = true;
1279                         break; // a script was found; we stop iterating
1280                 }
1281         } //------------------ // end for ( package_paths.begin();i!=package_paths.end() )
1282   }
1283
1284     if (!foundFile)
1285       {
1286         if (fullnameGiven)
1287           if(fullPathScriptName == "")
1288             bbtkError("Path ["<<upath<<"] doesn't exist");
1289           else
1290             bbtkError("Script ["<<fullPathScriptName<<"] not found");
1291         else
1292           bbtkError("No ["<<pkgname<<".bbs/.bbp] script found");
1293         return;
1294       }
1295     else
1296         {
1297       LoadScript(fullPathScriptName,name);
1298           if (source) GetExecuter()->SetCurrentFileName(fullPathScriptName);
1299         }
1300     
1301     return;
1302   }
1303   //=======================================================================
1304
1305
1306   //=======================================================================
1307 void Interpreter::SwitchToStream( std::stringstream* stream )
1308 {
1309     mFile.push_back(stream);
1310     std::ostringstream buffer_name;
1311     bufferNb++;
1312     buffer_name << "buffer_" ;
1313
1314     if (mFileName.size()>0 )
1315     {
1316        buffer_name << mFileName.back() << "_" << mLine.back();
1317     }
1318     mFileName.push_back(buffer_name.str());
1319     mIncludeFileName.push_back(buffer_name.str());
1320     mLine.push_back(0);
1321 }
1322   //=======================================================================
1323
1324   //=======================================================================
1325
1326   void Interpreter::LoadScript( std::string fullPathScriptName,
1327                                 std::string includeScriptName)
1328   {
1329      Utilities::replace( fullPathScriptName , 
1330                          INVALID_FILE_SEPARATOR , VALID_FILE_SEPARATOR);
1331    
1332      if (find(mFileNameHistory.begin(),
1333               mFileNameHistory.end(),
1334               fullPathScriptName)!=mFileNameHistory.end())
1335      {
1336         return;
1337      }
1338
1339     std::ifstream* s;
1340     s = new std::ifstream;
1341     s->open(fullPathScriptName.c_str());
1342     if (!s->good())
1343     {
1344         bbtkError("Could not open file ["<<fullPathScriptName<<"]");
1345         return;
1346     }
1347
1348     bbtkMessage("Interpreter",1,"   -->[" << fullPathScriptName 
1349                 << "] found" << std::endl);
1350
1351     mFile.push_back(s);
1352     mFileName.push_back(fullPathScriptName);
1353     mFileNameHistory.push_back(fullPathScriptName);
1354     mIncludeFileName.push_back(includeScriptName);
1355     mLine.push_back(0);
1356
1357         return;
1358   }
1359
1360   //=======================================================================
1361   /**
1362    *  
1363    */
1364   void Interpreter::CloseCurrentFile()
1365   {
1366     bbtkDebugMessage("Interpreter",9,"Interpreter::CloseCurrentFile()"
1367                       <<std::endl);
1368
1369     if (mFile.size()==0)
1370     {
1371       bbtkDebugMessage("Interpreter",9," -> no file left open"<<std::endl);
1372       return;
1373     }
1374
1375     bbtkDebugMessage("Interpreter",9," Closing file '"<<mFileName.back()<<"'"<<std::endl);
1376
1377     std::ifstream* file = dynamic_cast<std::ifstream*>(mFile.back());
1378     if (file!=0) file->close();
1379
1380     delete mFile.back();
1381     mFile.pop_back();
1382     mFileName.pop_back();
1383     mIncludeFileName.pop_back();
1384     mLine.pop_back();
1385
1386     bbtkDebugMessage("Interpreter",9," Remains "
1387                      <<mFile.size()
1388                      <<" open"<<std::endl);
1389     bbtkDebugMessage("Interpreter",9,"EO Interpreter::CloseCurrentFile()"
1390                      <<std::endl);
1391   }
1392   //=======================================================================
1393
1394  //=======================================================================
1395   /**
1396    *  
1397    */
1398   void Interpreter::CloseAllFiles()
1399   {
1400     bbtkDebugMessage("Interpreter",9,"Interpreter::CloseAllFiles()"
1401                       <<std::endl);
1402
1403     while (mFile.size() != 0) 
1404     {
1405        CloseCurrentFile();
1406     }
1407     bbtkDebugMessage("Interpreter",9,"EO Interpreter::CloseAllFiles()"
1408                       <<std::endl);
1409   }
1410   //=======================================================================
1411
1412
1413
1414   //=======================================================================
1415   /**
1416    *  
1417    */
1418   void Interpreter::InterpretCommand( const std::vector<std::string>& words,
1419                                       CommandInfoType& info )
1420   {
1421     bbtkDebugMessageInc("Interpreter",9,"Interpreter::InterpretCommand(...)"<<std::endl);
1422
1423     // searches the command keyword
1424     CommandDictType::iterator c;
1425     c = mCommandDict.find(words[0]);
1426     if ( c == mCommandDict.end() ) {
1427       bbtkError(words[0]<<" : unknown command");
1428     }
1429
1430     // tests the number of args 
1431     if ( ( ((int)words.size())-1 < c->second.argmin ) ||
1432          ( ((int)words.size())-1 > c->second.argmax ) )
1433     {
1434        HelpCommand(words[0]);
1435        bbtkError(words[0]<<" : wrong number of arguments");
1436     }
1437
1438     info = c->second;
1439     bbtkDecTab("Interpreter",9);
1440   }
1441   //=======================================================================
1442
1443
1444   //=======================================================================
1445   /// Displays help on all the commands
1446 void Interpreter::Help(const std::vector<std::string>& words)
1447 {
1448     unsigned int nbarg = words.size()-1;
1449
1450     if (nbarg==0) 
1451     {
1452        HelpCommands();
1453     }
1454     else if (nbarg==1) 
1455     {
1456       if (words[1]=="packages") 
1457       {
1458          GetExecuter()->GetFactory()->PrintPackages(true);
1459          return;
1460       }
1461       try 
1462       {
1463           HelpCommand(words[1]);
1464       }
1465       catch (bbtk::Exception e) 
1466       {
1467          try 
1468          {
1469             GetExecuter()->GetFactory()->HelpPackage(words[1]);
1470             if ( mUser != 0 )
1471               {
1472                 std::string url = 
1473                   ConfigurationFile::GetInstance().Get_doc_path();
1474                 url += "/bbdoc/" + words[1] + "/index.html";
1475                 if (Utilities::FileExists(url)) 
1476                   {
1477                     mUser->InterpreterUserViewHtmlPage(url);
1478                   }
1479               }
1480          }
1481          catch (bbtk::Exception f) 
1482          {
1483            try 
1484              {
1485                std::string package;
1486                GetExecuter()->GetFactory()->HelpBlackBox(words[1],package);
1487                if ( mUser != 0 )
1488                  {
1489                    std::string url = 
1490                      ConfigurationFile::GetInstance().Get_doc_path();
1491                    url += "/bbdoc/" + package + "/index.html";
1492                    if (Utilities::FileExists(url)) 
1493                      {
1494                        url += "#" + words[1];
1495                        mUser->InterpreterUserViewHtmlPage(url);
1496                      }
1497                  }
1498              }
1499            catch (bbtk::Exception g) 
1500              {
1501                try
1502                  {
1503                    GetExecuter()->ShowRelations(words[1],"0","9999");
1504                  }
1505                catch (bbtk::Exception h){
1506                  bbtkError("\""<<words[1].c_str()
1507                            <<"\" is not a known command, package, black box type or black box name");
1508                }
1509              }
1510          }
1511       }
1512     }
1513     else if (nbarg==2) 
1514     {
1515       if (words[2]=="all")
1516       {
1517          if ( words[1]=="packages" )
1518          {
1519             GetExecuter()->GetFactory()->PrintPackages(true,true);
1520             return;
1521           }
1522          try 
1523          {
1524             GetExecuter()->GetFactory()->HelpPackage(words[1],true);
1525          }
1526          catch (bbtk::Exception f) 
1527          {
1528          }
1529      }
1530      else 
1531      {
1532         HelpCommand(words[0]);
1533         bbtkError(words[0]<<" : syntax error");
1534      }
1535   }
1536   else 
1537   {
1538      bbtkError("Should not reach here !!!");
1539   }
1540 }
1541   //=======================================================================
1542
1543    //===================================================================    
1544   /// Displays the Configuration
1545   void Interpreter::Config() const
1546   {
1547     ConfigurationFile::GetInstance().GetHelp(1);
1548   }  
1549    //===================================================================    
1550
1551   //=======================================================================
1552   /// Displays help on all the commands
1553   void Interpreter::HelpCommands()
1554   {
1555     std::cout << "Available commands :" << std::endl;
1556     CommandDictType::iterator i;
1557     for ( i =  mCommandDict.begin();
1558           i != mCommandDict.end();
1559         ++i) {
1560               std::cout << " " << i->first << std::endl;
1561       //      std::cout << "   usage : " << i->second.syntax << std::endl;
1562       //     std::cout << "    " << i->second.help << std::endl;
1563
1564     }
1565   }
1566   //=======================================================================
1567
1568
1569   //=======================================================================
1570   /// Displays help on a particular commands
1571   void Interpreter::HelpCommand(const std::string& s)
1572   {
1573     CommandDictType::iterator c;
1574     c = mCommandDict.find(s);
1575     if ( c == mCommandDict.end() ) {
1576       bbtkError(s<<" : Unknown command");
1577     }   
1578     //    std::cout << " " << s << " : "<<  std::endl;
1579     //    CommandParamDictType::iterator i;
1580     //    for ( i =  c->second.begin();
1581     //      i != c->second.end();
1582     //      ++i) {
1583     std::cout << " usage : " << c->second.syntax << std::endl;
1584     std::cout << "  " << c->second.help << std::endl;
1585
1586   }
1587   //=======================================================================
1588
1589
1590   //=======================================================================
1591   /// Fills the vector commands with the commands which 
1592   /// have the first n chars of buf for prefix
1593   /// TODO : skip initial spaces in buf and also return the position of first
1594   /// non blank char in buf
1595   void Interpreter::FindCommandsWithPrefix( char* buf,
1596                                             int n,
1597                                             std::vector<std::string>& commands )
1598   {
1599     CommandDictType::const_iterator i;
1600     for (i=mCommandDict.begin(); i!=mCommandDict.end(); ++i)
1601     {
1602       if ((i->first).find(buf,0,n) == 0) 
1603         commands.push_back(i->first);
1604     }
1605   }
1606   //=======================================================================
1607
1608
1609
1610   //=======================================================================
1611 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1612   
1613   inline void PrintChar(char c) { write(STDOUT_FILENO,&c,1); }
1614   inline void BackSpace() { write(STDOUT_FILENO,"\b \b",3); }
1615   
1616   // LG : KEYBOARD CODES AS SCANNED ON MY TTY : UNIVERSAL ?
1617   // IF NOT THE USER SHOULD BE ABLE TO CONFIGURE IT
1618   // E.G. STORE THIS IN bbtk_config.xml
1619 #define BBTK_UP_ARROW_KBCODE    0x00415B1B
1620 #define BBTK_DOWN_ARROW_KBCODE  0x00425B1B
1621 #define BBTK_RIGHT_ARROW_KBCODE 0x00435B1B
1622 #define BBTK_LEFT_ARROW_KBCODE  0x00445B1B
1623 #define BBTK_BACKSPACE_KBCODE   0x00000008
1624 #define BBTK_DEL_KBCODE         0x0000007F
1625 #define BBTK_SPACE_KBCODE       0x00000020 
1626
1627   //=======================================================================
1628   void Interpreter::GetLineFromPrompt(std::string& s)
1629   {
1630     int c;
1631     unsigned int ind=0;
1632
1633     unsigned int MAX_LINE_SIZE = 160;
1634     unsigned int MAX_HISTORY_SIZE = 100;
1635
1636     char* newline = new char[MAX_LINE_SIZE];
1637     memset(newline,0,MAX_LINE_SIZE);
1638     char* histline = new char[MAX_LINE_SIZE];
1639     memset(histline,0,MAX_LINE_SIZE);
1640
1641     char* line = newline;
1642     unsigned int hist = mHistory.size();
1643
1644     write(1,"> ",2);
1645     while(1)
1646     {
1647        c=0;
1648        read ( STDIN_FILENO, &c, 4) ;
1649
1650        bbtkDebugMessage("debug",9,"[0x"<<std::hex<<c<<"]\n");
1651
1652        // Printable character
1653        if ( (ind<MAX_LINE_SIZE-1) &&
1654             ( c >= BBTK_SPACE_KBCODE ) && 
1655             ( c <  BBTK_DEL_KBCODE )) 
1656        {
1657           PrintChar(c);
1658           line[ind++]=c;
1659        }
1660       // CR
1661        else if (c=='\n')
1662        {
1663        // delete the unused line
1664           if (line==newline)
1665               delete histline;
1666           else
1667               delete newline;
1668    
1669     // empty lines are not stored in from history
1670           if (strlen(line)) 
1671           {
1672              // if history too long : delete oldest command
1673              if (mHistory.size()>MAX_HISTORY_SIZE) 
1674              {
1675                 delete mHistory.front();
1676                 mHistory.pop_front();
1677              }
1678              mHistory.push_back(line);
1679           }
1680           break;
1681         }
1682        // Backspace
1683         else if ( (ind>0) && 
1684                   ((c == BBTK_BACKSPACE_KBCODE) ||
1685                    (c == BBTK_DEL_KBCODE)) )
1686           {
1687             line[ind--]=' ';
1688             BackSpace();
1689           }
1690         // Tab 
1691         else if (c=='\t')
1692           {
1693             // TODO : Command completion  
1694             std::vector<std::string> commands;
1695             FindCommandsWithPrefix( line,ind,commands);
1696             if (commands.size()==1) 
1697               {
1698                 std::string com = *commands.begin();
1699                 for (; ind<com.size(); ++ind) 
1700                   {
1701                     PrintChar(com[ind]); 
1702                     line[ind]=com[ind];
1703                   }
1704                 PrintChar(' '); 
1705                 line[ind++]=' ';
1706               }
1707             else if (commands.size()>1) 
1708               {
1709                 std::vector<std::string>::iterator i;
1710                 write(1,"\n",1);
1711                 for (i=commands.begin();i!=commands.end();++i) 
1712                   {
1713                     write(STDOUT_FILENO,(*i).c_str(),strlen((*i).c_str()));
1714                     PrintChar(' ');
1715                   }
1716                 write(STDOUT_FILENO,"\n> ",3);
1717                 //for (int j=0;j<ind;++j) 
1718                   //{
1719                     write(STDOUT_FILENO,line,ind); 
1720                     //  }
1721               }
1722           }
1723         // Arrow up : back in history
1724         else if (c==BBTK_UP_ARROW_KBCODE)
1725           {
1726             if (hist) 
1727               {
1728                 // erase current line
1729                 while (ind--) BackSpace();
1730                 // 
1731                 hist--;
1732                 // 
1733                 strcpy(histline,mHistory[hist]);
1734                 line = histline;
1735                 ind = strlen(line);
1736                 
1737                 write(STDOUT_FILENO,line,ind);
1738               }
1739           }
1740         // Arrow down : down in history
1741         else if (c==BBTK_DOWN_ARROW_KBCODE)
1742           {
1743             if (hist<mHistory.size()-1) 
1744               {
1745                 // erase current line
1746                 while (ind--) BackSpace();
1747                 // 
1748                 hist++;
1749                 // 
1750                 strcpy(histline,mHistory[hist]);
1751                 line = histline;
1752                 ind = strlen(line);
1753                 
1754                 write(STDOUT_FILENO,line,ind);
1755               }
1756             // end of history : switch back to newline
1757             else if (hist==mHistory.size()-1)
1758               {
1759                 // erase current line
1760                 while (ind--) BackSpace();
1761                 // 
1762                 hist++;
1763                 // 
1764                 line = newline;
1765                 ind = strlen(line);
1766                 
1767                 write(STDOUT_FILENO,line,ind);
1768               }
1769           }
1770         // Arrow right
1771         else if (line[ind]!=0 && c==BBTK_RIGHT_ARROW_KBCODE)
1772           {
1773             PrintChar(line[ind]);
1774             ind++;
1775           }
1776
1777         // Arrow left
1778         else if (ind>0 && c==BBTK_LEFT_ARROW_KBCODE)
1779           {
1780             PrintChar('\b');
1781             ind--;
1782     
1783           }
1784
1785       }
1786     write(STDOUT_FILENO,"\n\r",2);
1787     
1788     
1789     s = line;
1790     
1791   }
1792 #else
1793
1794   //=======================================================================
1795   void Interpreter::GetLineFromPrompt(std::string& s)
1796   {  
1797     s.clear();
1798
1799     putchar('>');
1800     putchar(' ');
1801
1802     do 
1803     {
1804       char c = getchar();
1805       if (c=='\n') 
1806       {
1807         putchar('\n');
1808         break;
1809       }
1810       if (c=='\t') 
1811       {
1812         // putchar('T');
1813         continue;
1814       }
1815       // putchar(c);
1816       s += c;
1817     } 
1818     while (true);  
1819     
1820   }
1821   //=======================================================================  
1822
1823 #endif
1824
1825
1826
1827   //=======================================================================
1828   void Interpreter::CommandLineInterpreter()
1829   {
1830     bbtkDebugMessageInc("Interpreter",9,
1831                         "Interpreter::CommandLineInterpreter()"<<std::endl);
1832
1833 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT  
1834     // Initialise the tty in non canonical mode with no echo
1835     // oter remembers the previous settings to restore them after 
1836     struct termios ter,oter;
1837     tcgetattr(0,&ter);
1838     oter=ter;
1839     ter.c_lflag &= ~ECHO;
1840     ter.c_lflag &= ~ICANON;
1841     ter.c_cc[VMIN]=1;
1842     ter.c_cc[VTIME]=0;
1843     tcsetattr(0,TCSANOW,&ter);
1844 #endif
1845     
1846     mCommandLine = true;
1847     bool again = true;
1848     bool insideComment = false; // for multiline comment  
1849     do 
1850     {
1851       try
1852       {
1853         std::string line;
1854         GetLineFromPrompt(line);
1855         InterpretLine(line, insideComment);
1856       }
1857       catch (QuitException e)
1858       {
1859         bbtkMessage("Interpreter",1,"Interpreter : Quit"<<std::endl);
1860         again = false;
1861       }
1862       catch (bbtk::Exception e) 
1863       {
1864         e.Print();
1865       }
1866         catch (std::exception& e) 
1867       {
1868         std::cerr << "* ERROR :: "<<e.what()<<" (not in bbtk)"<<std::endl;
1869       }
1870       catch (...)
1871       {
1872         std::cerr << "* UNDEFINED ERROR (not a bbtk nor a std exception)"<<std::endl;
1873       }
1874     }
1875     while (again);
1876
1877 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1878     tcsetattr(0,TCSANOW,&oter);
1879 #endif
1880
1881     std::cout << "Good bye !" << std::endl;
1882
1883     bbtkDebugDecTab("Interpreter",9);
1884   }
1885
1886 //=======================================================================
1887 void Interpreter::Graph(const std::vector<std::string>& words)
1888 {
1889   std::string page;
1890     bool system_display = true;
1891
1892     if ( ( mUser != 0 ) && ( mUser->InterpreterUserHasOwnHtmlPageViewer() ) )
1893       system_display = false; 
1894  
1895     if (words.size()==1) 
1896     {
1897       page = mVirtualExecuter->ShowGraph(".","0","0","","","",system_display);
1898     }
1899     else if (words.size()==2) 
1900     {
1901       page = mVirtualExecuter->ShowGraph(words[1],"0","0","","","",system_display);
1902     }
1903     else if (words.size()==3) 
1904     {
1905       page = mVirtualExecuter->ShowGraph(words[1],words[2],"0","","","",system_display);
1906     }
1907     else if (words.size()==4) 
1908     {
1909       page = mVirtualExecuter->ShowGraph(words[1],words[2],words[3],"","","",system_display);
1910     } 
1911     else if (words.size()==5) 
1912     {
1913       page = mVirtualExecuter->ShowGraph(words[1],words[2],words[3],words[4],"","",system_display);
1914     } 
1915     else if (words.size()==6) 
1916     {
1917       page = mVirtualExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],"",system_display);
1918     } 
1919     else if (words.size()==7) 
1920       {
1921         page = mVirtualExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],words[6],system_display);
1922       } 
1923     
1924     if ( ( mUser != 0 ) && ( mUser->InterpreterUserHasOwnHtmlPageViewer() ) )
1925       mUser->InterpreterUserViewHtmlPage(page);
1926
1927   }
1928 //=======================================================================
1929
1930
1931 //=======================================================================
1932 void  Interpreter::Index(const std::string& filename, 
1933                          const std::string& type)
1934 {
1935   Factory::IndexEntryType t;
1936   if (type=="Initials") t = Factory::Initials;
1937   else if (type=="Categories") t = Factory::Categories;
1938   else if (type=="Packages") t = Factory::Packages;
1939   else if (type=="Adaptors") t = Factory::Adaptors;
1940   
1941   GetExecuter()->GetFactory()->CreateHtmlIndex(t,filename);
1942 }
1943 //=======================================================================
1944
1945
1946 //=======================================================================
1947 void  Interpreter::NewGUI(const std::string& boxname,
1948                              const std::string& instanceName)
1949 {
1950   if (mRealExecuter.expired())
1951     {
1952       bbtkError("command 'newgui' cannot be compiled yet");
1953     }
1954
1955   std::string typeName = instanceName+"Type";
1956   std::stringstream* s = new std::stringstream;
1957   // create the complex box
1958   (*s) << "define "<<typeName<<std::endl;
1959   //  (*s) << "  description 'Automatically generated user interface for the box "
1960   //       << boxname << "'" <<std::endl;
1961   // create the Layout box
1962   (*s) << "  load wx"<<std::endl;
1963   (*s) << "  new LayoutLine layout"<<std::endl;
1964   // create the output 'Widget'
1965   (*s) << "  output Widget layout.Widget Widget"<<std::endl;
1966   // the box change output 
1967   (*s) << "  new MultipleInputs change"<<std::endl;
1968   (*s) << "  output BoxChange change.Out BoxChange"<<std::endl;
1969
1970   // Browse the inputs of the box in order to find which ones are not 
1971   // connected and can be adapted from a widget adaptor
1972   // vector which stores the list of inputs of the box which must be connected
1973   std::vector<std::string> in;
1974  
1975   Factory::Pointer F = mVirtualExecuter->GetFactory();
1976   /*
1977   Package::Pointer user = F->GetPackage("user");
1978   */
1979   ComplexBlackBoxDescriptor::Pointer workspace = 
1980     mRealExecuter.lock()->GetCurrentDescriptor();
1981
1982   if (workspace==0)
1983     {
1984       delete s;
1985       bbtkError("Interpreter::CreateGUI : could not access the executer currently defined complex box");
1986     }
1987  
1988
1989   /*
1990     (ComplexBlackBoxDescriptor::Pointer)(user->GetBlackBoxMap().find("workspace")->second.get());
1991   */
1992
1993   BlackBox::Pointer box = workspace->GetPrototype()->bbGetBlackBox(boxname);
1994   //  BlackBox::InputConnectorMapType incm = box->bbGetInputConnectorMap();
1995   // int nb = 0;
1996   BlackBox::InputConnectorMapType::iterator i;
1997   for (i=box->bbGetInputConnectorMap().begin();
1998        i!=box->bbGetInputConnectorMap().end();
1999        ++i)
2000     {
2001       // If the input is connected : continue
2002       if (i->second->IsConnected()) continue;
2003       // Get the input descriptor 
2004       const BlackBoxInputDescriptor* d = box->bbGetDescriptor()->GetInputDescriptor(i->first);
2005       // If it is a "system" input : skip it
2006       if ( ( d->GetCreatorTypeInfo() == typeid(AtomicBlackBoxDescriptor)) ||
2007            ( d->GetCreatorTypeInfo() == typeid(WxBlackBoxDescriptor)) )
2008         continue;
2009       bool widok = true;
2010       std::string widget,adaptor;
2011       // try to find a widget adaptor
2012       if (F->FindWidgetAdaptor(DataInfo(d->GetTypeInfo(),""),
2013                                d->GetDataInfo(),
2014                                adaptor))
2015         {
2016           // command to create the adaptor
2017           (*s) << "  new "<<adaptor<<" "<<i->first<<std::endl;
2018           // Sets the label of the widget adaptor to the name of the input
2019           (*s) << "  set "<<i->first<<".Label "<<i->first<<std::endl;
2020           // Sets the initial value of the widget to the value of the input
2021           (*s) << "  set "<<i->first<<".In \" "
2022                <<box->bbGetInputAsString(i->first)<<"\""
2023                << std::endl;
2024           // store the input name
2025           in.push_back(i->first);
2026           (*s) << "  connect "<<i->first<<".Widget layout.Widget"<<in.size()<<std::endl;
2027             //<i->first<<"'"<<std::endl;
2028           (*s) << "  connect "<<i->first<<".BoxChange change.In"<<in.size()<<std::endl;
2029         }
2030       // try to find a two pieces adaptor
2031       else if (F->FindWidgetAdaptor2(DataInfo(d->GetTypeInfo(),""),
2032                                      d->GetDataInfo(),
2033                                      widget,adaptor) )
2034         {
2035           // command to create the widget
2036           (*s) << "  new "<<widget<<" "<<i->first<<"Widget"<<std::endl;
2037           // command to create the adaptor
2038           (*s) << "  new "<<adaptor<<" "<<i->first<<std::endl;
2039           // connect the two
2040           (*s) << "  connect "<<i->first<<"Widget.Out "
2041                <<i->first<<".In"<<std::endl;
2042           // Sets the label of the widget adaptor to the name of the input
2043           (*s) << "  set "<<i->first<<"Widget.Label "<<i->first<<std::endl;
2044           // Sets the initial value of the widget to the value of the input
2045           (*s) << "  set "<<i->first<<"Widget.In \" "
2046                <<box->bbGetInputAsString(i->first)<<"\""<< std::endl;
2047           // store the input name
2048           in.push_back(i->first);
2049           (*s) << "  connect "<<i->first<<"Widget.Widget layout.Widget"<<in.size()<<std::endl;
2050             //<i->first<<"'"<<std::endl;
2051           (*s) << "  connect "<<i->first<<"Widget.BoxChange change.In"<<in.size()<<std::endl;
2052
2053         }
2054       // try to find an adaptor from string 
2055       // If found then can create a text input which 
2056       // will be automatically adapted 
2057       else if (F->FindAdaptor(DataInfo(typeid(std::string),""),
2058                                d->GetDataInfo(),
2059                                adaptor))
2060         {
2061           // command to create the adaptor
2062           (*s) << "  new InputText "<<i->first<<std::endl;
2063           // Sets the label of the widget adaptor to the name of the input
2064           (*s) << "  set "<<i->first<<".Title "<<i->first<<std::endl;
2065           // Sets the initial value of the widget to the value of the input
2066           (*s) << "  set "<<i->first<<".In \" "
2067                <<box->bbGetInputAsString(i->first)<<"\""<< std::endl;
2068           // store the input name
2069           in.push_back(i->first);
2070           (*s) << "  connect "<<i->first<<".Widget layout.Widget"<<in.size()<<std::endl;
2071             //<i->first<<"'"<<std::endl;
2072           (*s) << "  connect "<<i->first<<".BoxChange change.In"<<in.size()<<std::endl;
2073
2074         }
2075       else 
2076         {
2077           widok = false;
2078         }
2079       if (widok)
2080         {
2081           // command to create the output
2082           (*s) << "  output "<<i->first<<" "
2083                <<i->first<<".Out "<<i->first<<std::endl;
2084             //         <<" Output of the widget which allows to set "
2085           
2086         }
2087     }   
2088   // Inputs for window properties
2089   (*s) << "  input WinTitle layout.WinTitle Title"<<std::endl;
2090   (*s) << "  input WinWidth layout.WinWidth Width"<<std::endl;
2091   (*s) << "  input WinHeight layout.WinHeight Height"<<std::endl;
2092   (*s) << "  input WinDialog layout.WinDialog Dialog"<<std::endl;
2093   (*s) << "  input WinHide layout.WinHide Hide"<<std::endl;
2094
2095   
2096   
2097   // Execute the box executes the layout
2098   (*s) << "  exec layout" << std::endl;
2099   (*s) << "endefine" << std::endl;
2100   // (*s) << "help "<< typeName<< std::endl;
2101   // instanciate the box and connect it
2102   (*s) << "new "<<typeName<<" "<<instanceName<<std::endl;
2103   // connections
2104   std::vector<std::string>::iterator j;
2105   for (j=in.begin();j!=in.end();++j)
2106     {
2107       // connect
2108       (*s) << "connect "<<instanceName<<"."<<*j<<" "
2109            << boxname<<"."<<*j<<std::endl;
2110     }
2111   // That's all folks ! now execute the commands :
2112   SwitchToStream(s);
2113 }
2114 //=======================================================================
2115
2116
2117
2118  //==========================================================================
2119   void Interpreter::Debug(const std::string& name)
2120   {
2121     if ((name.length()==2)&&(name[0]=='-'))
2122       {
2123         if (name[1]=='D')
2124           {
2125             bbtk::StaticInitTime::PrintObjectListInfo = true;
2126           }
2127         if (name[1]=='C')
2128           {
2129             //      int o = MessageManager::GetMessageLevel("debug");
2130             //      if (o<2) MessageManager::SetMessageLevel("debug",2);
2131             mVirtualExecuter->GetFactory()->CheckPackages();
2132             //      MessageManager::SetMessageLevel("debug",o);
2133           }
2134       }
2135     else 
2136       {
2137         Object:: PrintObjectListInfo(name);
2138       }
2139   }
2140  //==========================================================================
2141  //==========================================================================
2142   std::string Interpreter::GetObjectName() const
2143   {
2144     return std::string("Interpreter");
2145   }
2146   //==========================================================================
2147   
2148   //==========================================================================
2149   std::string  Interpreter::GetObjectInfo() const 
2150   {
2151     std::stringstream i;
2152     return i.str();
2153   }
2154   //==========================================================================
2155
2156   //==========================================================================
2157 size_t  Interpreter::GetObjectSize() const 
2158 {
2159   size_t s = Superclass::GetObjectSize();
2160   s += Interpreter::GetObjectInternalSize();
2161   return s;
2162   }
2163   //==========================================================================
2164   //==========================================================================
2165 size_t  Interpreter::GetObjectInternalSize() const 
2166 {
2167   size_t s = sizeof(Interpreter);
2168   return s;
2169   }
2170   //==========================================================================
2171   //==========================================================================
2172   size_t  Interpreter::GetObjectRecursiveSize() const 
2173   {
2174     size_t s = Superclass::GetObjectRecursiveSize();
2175     s += Interpreter::GetObjectInternalSize();
2176     s += mVirtualExecuter->GetObjectRecursiveSize();
2177     return s;
2178   }
2179   //==========================================================================
2180 }//namespace
2181
2182