]> Creatis software - bbtk.git/blob - kernel/src/bbtkInterpreter.cxx
Created 2 applis :
[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 10:56:27 $
7   Version:   $Revision: 1.74 $
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 )
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);
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 = 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 (mCommandLine)
842         {
843            InterpretFile(words[1]); 
844         }
845         else
846         {
847             SwitchToFile(words[1]);
848         }
849         // if 'source' was given
850         if (words.size()==3) 
851           {
852             GetExecuter()->SetCurrentFileName(words[1]);
853           }
854         break;
855
856       case cLoad:
857         GetExecuter()->LoadPackage(words[1]);
858         break;
859
860       case cUnload:
861         GetExecuter()->UnLoadPackage(words[1]);
862         break;
863
864       case cQuit :
865         throw QuitException();
866         break;
867
868       case cDebug :
869         if (words.size()==2) Debug(words[1]);
870         else Debug("");
871         break;
872         /* obsolete
873       case cWorkspace :
874         if (words.size() == 2) 
875         {
876            if (words[1]=="freeze")        mVirtualExecuter->SetNoExecMode(true);
877            else if (words[1]=="unfreeze") mVirtualExecuter->SetNoExecMode(false);
878         }
879         else
880         {
881            mVirtualExecuter->SetWorkspaceName(words[2]);
882         }
883         break;
884         */
885       default:
886         bbtkInternalError("should not reach here !!!");
887    }
888
889    bbtkDecTab("Interpreter",9);
890 }
891   //=======================================================================  
892
893
894
895
896
897   //=======================================================================
898   /**
899    *
900    */
901 void Interpreter::SplitLine ( const std::string& str, std::vector<std::string>& tokens)
902 {
903     bbtkDebugMessageInc("Interpreter",9,"Interpreter::SplitLine(\""<<str<<"\")"<<std::endl);
904
905     std::string delimiters = "\"";
906     std::vector<std::string> quote;
907     Utilities::SplitString(str,delimiters,quote);
908
909     delimiters = " \t";
910     std::vector<std::string>::iterator i;
911     for (i=quote.begin(); i!=quote.end(); ) 
912     {
913        Utilities::SplitString(*i,delimiters,tokens);
914        ++i;
915        if (i!=quote.end()) 
916        {
917         //    bbtkDebugMessage("Interpreter",0,"\""<<*i<<"\""<<std::endl);
918           tokens.push_back(*i);
919           ++i;
920        }
921     }
922
923     for (i=tokens.begin(); i!=tokens.end(); ++i) 
924     {
925        bbtkDebugMessage("Interpreter",9,"["<<*i<<"] ");
926     }
927     bbtkDebugMessageCont("Interpreter",9,std::endl);
928
929     bbtkDebugDecTab("Interpreter",9);
930  }
931   //=======================================================================
932
933
934   //=======================================================================
935   void Interpreter::Reset()
936   {
937     // Cannot close all files if the reset command is read from a file !
938     //    CloseAllFiles();
939     mFileNameHistory.clear();
940     this->mVirtualExecuter->Reset();
941   }
942   //=======================================================================
943
944   //=======================================================================
945   /**
946    *
947    */
948   /*
949   void Interpreter::Print( const std::string& str)
950   {
951     if (mVirtualExecuter->GetNoExecMode()) return;
952
953     bbtkDebugMessageInc("Interpreter",9,"Interpreter::Print(\""<<str<<"\")"<<std::endl);
954
955  // TO DO :
956  // InterpretLine ("load std")
957  // InterpretLine("new ConcatStrings _C_ ") -> trouver un nom unique : # commande 
958  // InterpretLine("new Print _P_") 
959  // InterpretLine("connect _C_.Out _P_.In")
960  // int num = 1
961  
962
963     std::vector<std::string> chains;
964     std::string delimiters("$");
965
966     // Skip delimiters at beginning.
967     std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
968     bool is_text = true;
969     if (lastPos>0) is_text = false;
970
971     // Find first delimiter.
972     std::string::size_type pos     = str.find_first_of(delimiters, lastPos);
973
974     while (std::string::npos != pos || std::string::npos != lastPos)
975     {
976        if (is_text) 
977        {
978           // Found a text token, add it to the vector.
979           chains.push_back(str.substr(lastPos, pos - lastPos));
980  // std::string token = str.substr(lastPos, pos - lastPos)
981  // InterpretLine("set _C_.In%num% %token%")
982  
983        }
984        else 
985        {
986
987        // is an output (between $$) : decode 
988          std::string tok,box,output;
989          tok = str.substr(lastPos, pos - lastPos);
990          Utilities::SplitAroundFirstDot(tok,box,output);
991          chains.push_back( mVirtualExecuter->Get(box,output) );
992
993 // InterpretLine("connect %tok% _C_.In%num%") 
994
995        }
996         // Skip delimiters.  Note the "not_of"
997        lastPos = str.find_first_not_of(delimiters, pos);
998         // Find next delimiter
999        pos = str.find_first_of(delimiters, lastPos);
1000     //
1001        is_text = !is_text;
1002 // num ++;
1003      }
1004 // InterpretLine("exec _P_")
1005 // if (IS_IN_WORKSPACE) InterpretLine("delete _C_; delete _P_");
1006
1007      std::vector<std::string>::iterator i;
1008      for (i= chains.begin(); i!=chains.end(); ++i) 
1009      {
1010
1011        Utilities::SubsBackslashN(*i);
1012        std::cout << *i;
1013      }
1014      std::cout << std::endl;
1015      bbtkDebugDecTab("Interpreter",9);
1016  }
1017 */
1018
1019   //=======================================================================
1020   /**
1021    *
1022    */
1023
1024   // =========================================================================
1025   void Interpreter::SwitchToFile( const std::string& name )
1026   {
1027   // Note : in the following :
1028   // name : the user supplied name 
1029   //      - abreviated name    e.g.       scr   scr.bbs
1030   //      - relative full name e.g.       ./scr.bbs   ../../scr.bbs 
1031   //      - absolute full name e.g.       /home/usrname/proj/dir/scr.bbs
1032   //          same for Windows, with      c:, d: ...
1033   //
1034   // use ./directory/subdir/scrname.bbs
1035   //
1036
1037     bbtkDebugMessageInc("Interpreter",9,"Interpreter::SwitchToFile( \""
1038                          <<name<<"\")"<<std::endl);
1039
1040     std::vector<std::string> script_paths;
1041     std::string fullPathScriptName;  // full path script name
1042     std::string pkgname;             // e.g. <scriptname>.bbs
1043     std::vector<std::string> Filenames;
1044
1045     // The following is *NOT* a debug time message :
1046     // It's a user intended message.
1047     // Please don't remove it.
1048     bbtkMessage("Interpreter",1,
1049         "look for : [" << name
1050         << "]" << std::endl);
1051
1052
1053     std::string upath;
1054     pkgname = Utilities::ExtractScriptName(name,upath);
1055
1056     bbtkMessage("Interpreter",3,
1057                 "extract : pkgname [" << pkgname
1058                  << "] upath [" << upath << "]" << std::endl);
1059     bool fullnameGiven = false; 
1060     bool foundFile     = false;
1061
1062     // ==== "*" provided : load all scripts in given path 
1063     // relative (e.g. std/boxes/*) or absolute 
1064     if (pkgname == "*") 
1065         {
1066                 int nbBssFiles;
1067         
1068                 std::stringstream* stream = new std::stringstream;
1069                 //if (upath.size()!=0) // avoid troubles for "*"
1070         
1071                 // ==== no path provided : look in root bbs path
1072                 if (upath.size()==0)
1073                 {
1074                         //          bbtkMessage("Interpreter",1,
1075                         // LG : add all bbs path
1076                         //  script_paths.push_back(  ConfigurationFile::GetInstance().Get_root_bbs_path() );
1077                         std::vector<std::string>::const_iterator i;
1078                         for (i=ConfigurationFile::GetInstance().Get_bbs_paths().begin();
1079                                 i!=ConfigurationFile::GetInstance().Get_bbs_paths().end();
1080                                 i++)
1081                         {
1082                            script_paths.push_back(*i);
1083                         }
1084                 }
1085                 // ==== absolute path provided 
1086                 else if (upath[0]=='/' || upath[1] == ':' ) 
1087                 {
1088                         if ( Utilities::IsDirectory( upath ) )
1089                         {
1090                                 script_paths.push_back(upath);
1091                         }
1092                         else 
1093                         {
1094                                 bbtkError("'"<<upath<<"' : directory does not exist"); 
1095                         }
1096                 }
1097                 // ==== relative path provided : search all bbs path appended with 
1098                 // the relative path provided
1099                 else
1100                 {    
1101                         std::vector<std::string>::const_iterator i;
1102                         for (i=ConfigurationFile::GetInstance().Get_bbs_paths().begin();
1103                                 i!=ConfigurationFile::GetInstance().Get_bbs_paths().end();
1104                                 i++)
1105                         {
1106                                 std::string full_path(*i);
1107                                 // we *really* want '.' to be the current working directory
1108                                 if (full_path == ".") 
1109                                 {
1110                                         char buf[2048]; // for getcwd
1111                                         char * currentDir = getcwd(buf, 2048);
1112                                         std::string cwd(currentDir);
1113                                         full_path = currentDir;
1114                                 } // if full_path
1115          
1116                                 full_path += ConfigurationFile::GetInstance().Get_file_separator();
1117                                 full_path += upath;
1118
1119                                 if ( Utilities::IsDirectory( full_path ) )
1120                                 {
1121                                         script_paths.push_back(full_path);
1122                                 }
1123                         } 
1124                         if (script_paths.empty())
1125                         {
1126                                 bbtkError("no '"<<upath<<"' subdir found in search paths" 
1127                                                         << std::endl);
1128                         }
1129                 }
1130
1131
1132                 // === search paths list complete : now explore it
1133
1134                 // ==== relative name, iterate + load all .bbs/.bbp files
1135                 std::vector<std::string>::iterator i;
1136                 for (i=script_paths.begin();i!=script_paths.end();i++)
1137                 {
1138                         bbtkMessage("Interpreter",1,
1139                         "--> Looking in '" << *i << "'" << std::endl);
1140              
1141                         Filenames.clear();
1142                         //int nbFiles = 
1143                         Utilities::Explore(*i, false, Filenames);
1144             
1145                         nbBssFiles = 0;
1146                         for (std::vector<std::string>::iterator j = Filenames.begin(); 
1147                                 j!= Filenames.end(); ++j)
1148                         {
1149                                 int lgr = (*j).size();
1150                                 if (lgr < 5) continue;  
1151                                 // ignore non .bbp file
1152                                 if ( (*j).substr(lgr-4, 4) != ".bbp") continue; 
1153
1154                                 (*stream) << "include \"" << *j << "\"\n";
1155                                 bbtkMessage("Interpreter",2,"  --> Found '" << *j << "'" << std::endl);
1156                 
1157                                 nbBssFiles++;
1158                         } // for (std::vector...
1159                 } // for (i=script_...
1160                 if (nbBssFiles==0)
1161                 {
1162                         bbtkMessage("Interpreter",1,
1163                     "  --> No .bbp found"<< std::endl);
1164                 } 
1165                 else 
1166                 {
1167                         bbtkMessage("Interpreter",1,
1168                     "  --> "<<nbBssFiles<<" .bbp found"<< std::endl);
1169                         SwitchToStream(stream);
1170                 }
1171             return;
1172     }  
1173     //=============== end pkgname=="*" ===========
1174
1175
1176     // if name starts with a / or a . or contains : user is assumed to have passed a relative/absolute name
1177     // (not only a plain script name)
1178     // we trust him, and try to expland the directory name
1179     // WARNING : starting from current local directory :  ./whatYouWant  (./ mandatory!)
1180
1181     if (name[0]=='/' || name[1] == ':' || name[0]=='.')  // absolute path (linux/windows) or relative path
1182     { 
1183
1184       // ===========================================================check user supplied location
1185       fullnameGiven = true;
1186
1187       fullPathScriptName =  Utilities::ExpandLibName(name, false);
1188
1189       // allow user to always forget ".bbs"
1190       int l = fullPathScriptName.size();
1191
1192       if (l!=0) 
1193           {
1194          if ((fullPathScriptName.substr(l-4, 4) != ".bbs")&&
1195                          (fullPathScriptName.substr(l-4, 4) != ".bbp"))
1196          {
1197                         std::string tfullPathScriptName = fullPathScriptName + ".bbs";
1198                         if ( Utilities::FileExists(tfullPathScriptName) )
1199                         {
1200                                 fullPathScriptName = tfullPathScriptName;
1201                                 foundFile = true;
1202                         }
1203                         else 
1204                         {
1205                                 tfullPathScriptName = fullPathScriptName + ".bbp";
1206                                 if ( Utilities::FileExists(tfullPathScriptName) )
1207                                 {
1208                                         fullPathScriptName = tfullPathScriptName;
1209                                         foundFile = true;
1210                                 }
1211                         }
1212                  }
1213                  else 
1214                  {
1215                         if ( Utilities::FileExists(fullPathScriptName) )
1216                         {
1217                                 foundFile = true;
1218                         }
1219                  }
1220           } // endif l != 0
1221   }
1222   else
1223   // =============================== iterate on the paths
1224   {
1225       script_paths = ConfigurationFile::GetInstance().Get_bbs_paths();
1226       std::string path;
1227       std::vector<std::string>::iterator i;
1228       for (i=script_paths.begin();i!=script_paths.end();++i)
1229           {
1230                 path = *i;
1231                 // we *really* want '.' to be the current working directory
1232                 if (path == ".") 
1233                 {
1234                         char buf[2048]; // for getcwd
1235                         char * currentDir = getcwd(buf, 2048);
1236                         std::string cwd(currentDir);
1237                         path = currentDir;
1238                 }
1239           
1240                 std::string tfullPathScriptName = Utilities::MakePkgnameFromPath(path, name, false);
1241                 if (tfullPathScriptName.substr(tfullPathScriptName.size()-4, 3)==".bb")
1242                 {
1243                   fullPathScriptName = tfullPathScriptName;
1244                         if ( ! Utilities::FileExists(fullPathScriptName) )
1245                         {
1246                                 // The following is *NOT* a debug time message :
1247                                 // It's a user intended message.
1248                                 // Please don't remove it.
1249                                 bbtkMessage("Interpreter",2,
1250                           "   [" <<fullPathScriptName <<"] : does not exist" 
1251                           <<std::endl);
1252                                 continue;  // try next path
1253                         }
1254                         bbtkMessage("Interpreter",2,
1255                               "   [" <<fullPathScriptName 
1256                                   <<"] : found" <<std::endl);
1257                         foundFile = true;
1258                         break; // a script was found; we stop iterating
1259                 }
1260                 else 
1261                 {
1262                         fullPathScriptName = tfullPathScriptName + ".bbs";
1263                         // Check if library exists
1264                         if ( ! Utilities::FileExists(fullPathScriptName) )
1265                         {
1266                                 fullPathScriptName = tfullPathScriptName + ".bbp";
1267                                 if ( ! Utilities::FileExists(fullPathScriptName) )
1268                                 {
1269                                         // The following is *NOT* a debug time message :
1270                                         // It's a user intended message.
1271                                         // Please don't remove it.
1272                                         bbtkMessage("Interpreter",2,
1273                                         "   [" <<tfullPathScriptName <<".bbs/.bbp] : do not exist" 
1274                                         <<std::endl);
1275                                         continue;  // try next path
1276                                 }
1277                         }
1278                         bbtkMessage("Interpreter",2,
1279                       "   [" <<fullPathScriptName 
1280                       <<"] : found" <<std::endl);
1281                         foundFile = true;
1282                         break; // a script was found; we stop iterating
1283                 }
1284         } //------------------ // end for ( package_paths.begin();i!=package_paths.end() )
1285   }
1286
1287     if (!foundFile)
1288       {
1289         if (fullnameGiven)
1290           if(fullPathScriptName == "")
1291             bbtkError("Path ["<<upath<<"] doesn't exist");
1292           else
1293             bbtkError("Script ["<<fullPathScriptName<<"] not found");
1294         else
1295           bbtkError("No ["<<pkgname<<".bbs/.bbp] script found");
1296         return;
1297       }
1298     else
1299       LoadScript(fullPathScriptName,name);
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