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