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