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