]> Creatis software - bbtk.git/blob - kernel/src/bbtkInterpreter.cxx
6771d7788013d12bed23d9d1b85aac56b953a004
[bbtk.git] / kernel / src / bbtkInterpreter.cxx
1 /*=========================================================================                                                                               
2   Program:   bbtk
3   Module:    $RCSfile: bbtkInterpreter.cxx,v $
4   Language:  C++
5   Date:      $Date: 2010/09/15 14:17:17 $
6   Version:   $Revision: 1.89 $
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         void Interpreter::commandBreak()
871     {
872             /*
873                  std::cout << "BreakException(" 
874                  <<in_script<<","
875                  <<file<<","
876                  <<line<<")"<<std::endl;
877                  */
878                 bbtkError("break");//,in_script,file,line);
879             //      throw BreakException(in_script,file,line);
880     }
881         
882         void Interpreter::commandQuit()
883     {
884                 bbtkError("quit");//,in_script,file,line);
885                 //throw QuitException(in_script,file,line);
886     }
887         
888         void Interpreter::commandMessage()
889     {
890                 mVirtualExecuter->HelpMessages();
891     }
892         
893 //ups2 EED Borrame      
894         void Interpreter::commandMessage(std::string kind, std::string levelstr)
895     {
896                 int level=0;
897                 sscanf(levelstr.c_str(),"%d",&level);
898                 mVirtualExecuter->SetMessageLevel(kind,level);
899
900     }
901         
902         
903         
904   //=======================================================================  
905   void Interpreter::DoInterpretLine( const std::string& line )
906   {
907     bbtkDebugMessage("interpreter",6,"==> Interpreter::DoInterpretLine(\""
908                      <<line<<"\")"<<std::endl);
909     std::vector<std::string> words;
910     SplitLine(line,words);
911
912     // Empty line
913     if (words.size()<1) 
914     {
915        bbtkDebugDecTab("interpreter",9);
916        return;
917     }
918
919     // Single line comment : # or //
920     if ( words[0][0]=='#' || (words[0][0]=='/' && words[0][1]=='/') ) 
921     {  
922        bbtkDebugDecTab("interpreter",9);
923        bbtkMessage("interpreter",9,"Comment"<<std::endl);
924        return;
925     }
926
927     // Multi line comment ( /* ... */ ) -delimiters on different lines !-
928     
929     if (words[0][0]=='/' && words[0][1]=='*') 
930     {  
931        bbtkDebugDecTab("interpreter",9);
932        bbtkMessage("interpreter",9,"In multiline comment"<<std::endl);
933        mInsideComment = true;
934        return;
935     }
936
937     if (words[0][0]=='*' && words[0][1]=='/') 
938     {  
939        bbtkDebugDecTab("interpreter",9);
940        bbtkMessage("interpreter",9,"Out multiline comment"<<std::endl);
941        if ( !mInsideComment ) {
942           bbtkDebugDecTab("interpreter",9);
943           bbtkMessage("interpreter",9,"Comment mismatch : '*/' with no matching '/*'"<<std::endl);       
944        }
945        mInsideComment = false;
946        return;
947     }
948
949     if (mInsideComment) 
950     {  
951        bbtkDebugDecTab("interpreter",9);
952        bbtkMessage("interpreter",9,"Multiline Comment"<<std::endl);
953        return;
954     }
955
956     // Command 
957     CommandInfoType command;
958     InterpretCommand(words,command);
959 //std::cout<<"JCP bbtkInterpreter command.keyword ="<<command.keyword<<std::endl;
960     bbtkDebugMessage("interpreter",9,
961                      "Command='"<<command.keyword
962                       <<"' code="<<command.code<<std::endl); 
963           
964     std::string left,right,left2,right2;
965     std::string filename;
966
967 //ups1 EED borrame        
968     // message command
969     if (command.code==cMessage)
970       {
971         if (words.size()<3)
972           {
973                   commandMessage();
974 //EED Borrame       mVirtualExecuter->HelpMessages();
975           }
976         else
977           {
978                 commandMessage(words[1],words[2]);
979 //EED Borrame           sscanf(words[2].c_str(),"%d",&level);
980 //EED Borrame       mVirtualExecuter->SetMessageLevel(words[1],level);
981           }
982         return;
983       }
984     else 
985       {
986         bbtkMessage("echo",2,line<<std::endl);
987       }
988
989     // break and quit commands
990     if ((command.code==cBreak) || (command.code==cQuit))
991       {
992         bool in_script = false;
993         std::string file("");
994         int line = 0;
995
996         if (mFileName.size()) 
997           {
998             std::ifstream* fs = dynamic_cast<std::ifstream*>(mFile.back());
999             if (fs!=0) in_script = true;          
1000             file = mFileName.back();
1001             line = mLine.back();
1002           } 
1003         if (command.code==cBreak)
1004           {
1005             /*
1006             std::cout << "BreakException(" 
1007                       <<in_script<<","
1008                       <<file<<","
1009                       <<line<<")"<<std::endl;
1010             */
1011                   commandBreak();
1012 //EED Borrame       bbtkError("break");//,in_script,file,line);
1013             //      throw BreakException(in_script,file,line);
1014           }       
1015         else 
1016           {
1017                   commandQuit();
1018 //EED Borrame       bbtkError("quit");//,in_script,file,line);
1019               //throw QuitException(in_script,file,line);
1020           }
1021         return;
1022       }   
1023 //std::cout<<" mVirtualExecuter->Create(words[1],words[2]); "<<line<<std::endl;
1024     // other cammands
1025
1026     switch (command.code) 
1027       {
1028       case cNew :
1029                 commandNew(words[1],words[2]);
1030 //EED Borrame        mVirtualExecuter->Create(words[1],words[2]);
1031         break;
1032
1033       case cDelete :
1034                           commandDelete(words[1]);
1035 //EED Borrame   mVirtualExecuter->Destroy(words[1]);
1036         break;
1037
1038       case cConnect :
1039         Utilities::SplitAroundFirstDot(words[1],left,right);
1040         Utilities::SplitAroundFirstDot(words[2],left2,right2);      
1041         commandConnection(left,right,left2,right2);
1042 //EED Borrame        mVirtualExecuter->Connect(left,right,left2,right2);
1043         break;
1044
1045       case cPackage :
1046                           commandPackage(words[1]);
1047 //EED Borrame                mVirtualExecuter->BeginPackage(words[1]);
1048         break;
1049
1050       case cEndPackage :
1051                           commandEndPackage();
1052 //EED Borrame        mVirtualExecuter->EndPackage();
1053         break;
1054
1055       case cDefine :
1056         if (mFileName.size()>0) 
1057         {
1058 //???                   commandDefine(????);
1059                    filename = mFileName.back(); //mIncludeFileName.back(); //Utilities::get_file_name(mFileName.back());
1060         }
1061         if (words.size()==2) 
1062         {
1063                         commandDefine(words[1],"",filename);
1064 //EED Borrame           mVirtualExecuter->Define(words[1],"",filename);
1065         }
1066         else
1067         {
1068                         commandDefine(words[1],words[2],filename);
1069 //EED Borrame           mVirtualExecuter->Define(words[1],words[2],filename);
1070         }
1071         break;
1072
1073       case cEndDefine :
1074                 commandEndDefine();
1075 //EED Borrame        mVirtualExecuter->EndDefine();
1076         break;
1077
1078       case cKind :
1079                         commandKind(words[1]);
1080 //EED Borrame        mVirtualExecuter->Kind(words[1]);
1081         break;
1082
1083       case cPrint :
1084                           commandPrint(words[1]);
1085 //EED Borrame        mVirtualExecuter->Print(words[1]);
1086         break;
1087                           
1088       case cExec :
1089                           commandExec(words[1]);
1090 //EED Borrame        if (words[1]=="freeze") 
1091 //EED Borrame     {
1092 //EED Borrame       mVirtualExecuter->SetNoExecMode(true);
1093 //EED Borrame       mThrow = false;
1094 //EED Borrame     }
1095 //EED Borrame   else if (words[1]=="freeze_no_error") 
1096 //EED Borrame     {
1097 //EED Borrame       mVirtualExecuter->SetNoExecMode(true);
1098 //EED Borrame       mVirtualExecuter->SetNoErrorMode(true);
1099 //EED Borrame       mThrow = false;
1100 //EED Borrame     }
1101 //EED Borrame   else if (words[1]=="unfreeze") 
1102 //EED Borrame     {
1103 //EED Borrame       mVirtualExecuter->SetNoExecMode(false);
1104 //EED Borrame       mVirtualExecuter->SetNoErrorMode(false);
1105 //EED Borrame     }
1106 //EED Borrame   else
1107 //EED Borrame     {
1108 //EED Borrame       mVirtualExecuter->Execute(words[1]);
1109 //EED Borrame     }
1110                           
1111         break;
1112
1113       case cInput :
1114         Utilities::SplitAroundFirstDot(words[2],left,right);
1115                           commandInput(words[1],left,right,words[3]);
1116 //EED Borrame        mVirtualExecuter->DefineInput(words[1],left,right,words[3]);
1117         break;
1118
1119       case cOutput :
1120         Utilities::SplitAroundFirstDot(words[2],left,right);
1121                 commandOutput(words[1],left,right,words[3]);
1122 //EED Borrame         mVirtualExecuter->DefineOutput(words[1],left,right,words[3]);
1123         break;
1124
1125       case cSet :
1126         Utilities::SplitAroundFirstDot(words[1],left,right);
1127                 commandSet(left,right,words[2]);
1128 //EED Borrame        mVirtualExecuter->Set(left,right,words[2]);
1129         break;
1130
1131       case cAuthor :
1132                 commandAuthor(words[1]);
1133 //EED Borrame        mVirtualExecuter->Author(words[1]);
1134         break;
1135
1136       case cNewGUI :
1137                 commandNewGUI(words[1],words[2]);
1138         break;
1139
1140       case cCategory :
1141                 commandCategory(words[1]);
1142 //EED Borrame   mVirtualExecuter->Category(words[1]);
1143         break;
1144
1145       case cIndex :
1146         if (words.size()==1)
1147                         commandIndex("tmp_index.html");
1148         else if (words.size()==2)
1149                         commandIndex(words[1]);
1150         else if (words.size()==3)
1151                         commandIndex(words[1],words[2]);
1152         break;
1153
1154       case cDescription :
1155                 commandDescription(words[1]);
1156 //EED Borrame        mVirtualExecuter->Description(words[1]);
1157         break;
1158
1159       case cHelp :
1160         commandHelp(words);
1161         break;
1162
1163
1164       case cGraph :
1165         commandGraph(words);
1166         break;
1167
1168       case cConfig :
1169         commandConfig();
1170         break;
1171
1172       case cReset :  
1173         commandReset();
1174         break;
1175         
1176       case cClear :  
1177                 commandClear();
1178 //EED Borrame           mVirtualExecuter->Clear();
1179         break;
1180
1181       case cInclude :
1182                           commandInclude( words[1] , (words.size()==3) );
1183 //EED Borrame           // if 'source' was given (words.size()==3) then tell to set the 
1184 //EED Borrame           // source file name of the current complex box with the full file name included
1185 //EED Borrame           if (mCommandLine)
1186 //EED Borrame        {
1187 //EED Borrame           InterpretFile(words[1],(words.size()==3)); 
1188 //EED Borrame        } else{
1189 //EED Borrame            SwitchToFile(words[1],(words.size()==3) );
1190 //EED Borrame        }
1191                 break;
1192
1193       case cLoad:
1194                 commandLoad( words[1] );
1195 //EED Borrame        GetExecuter()->LoadPackage(words[1]);
1196         break;
1197
1198       case cUnload:
1199                 commandUnload( words[1] );
1200 //EED Borrame        GetExecuter()->UnLoadPackage(words[1]);
1201         break;
1202
1203       case cDebug :
1204                           if (words.size()==2) commandDebug(words[1]);
1205                                 else commandDebug("");
1206         break;
1207                           
1208         /* obsolete
1209       case cWorkspace :
1210         if (words.size() == 2) 
1211         {
1212            if (words[1]=="freeze")        mVirtualExecuter->SetNoExecMode(true);
1213            else if (words[1]=="unfreeze") mVirtualExecuter->SetNoExecMode(false);
1214         }
1215         else
1216         {
1217            mVirtualExecuter->SetWorkspaceName(words[2]);
1218         }
1219         break;
1220         */
1221       default:
1222         bbtkInternalError("should not reach here !!!");
1223    }
1224
1225     bbtkDebugMessage("interpreter",6,"<== Interpreter::DoInterpretLine(\""
1226                      <<line<<"\")"<<std::endl);
1227     
1228   }
1229   //=======================================================================  
1230
1231
1232
1233
1234
1235   //=======================================================================
1236   void Interpreter::SplitLine ( const std::string& str, std::vector<std::string>& tokens)
1237 {
1238     bbtkDebugMessage("interpreter",9,"==> Interpreter::SplitLine(\""<<str<<"\")"<<std::endl);
1239
1240     std::string delimiters = "\"";
1241     std::vector<std::string> quote;
1242     Utilities::SplitString(str,delimiters,quote);
1243
1244     delimiters = " \t";
1245     std::vector<std::string>::iterator i;
1246     for (i=quote.begin(); i!=quote.end(); ) 
1247     {
1248        Utilities::SplitString(*i,delimiters,tokens);
1249        ++i;
1250        if (i!=quote.end()) 
1251        {
1252         //    bbtkDebugMessage("interpreter",0,"\""<<*i<<"\""<<std::endl);
1253           tokens.push_back(*i);
1254           ++i;
1255        }
1256     }
1257
1258     for (i=tokens.begin(); i!=tokens.end(); ++i) 
1259     {
1260       bbtkDebugMessage("interpreter",9,"--["<<*i<<"]"<<std::endl);
1261     }
1262     bbtkDebugMessage("interpreter",9,"<== Interpreter::SplitLine(\""<<str<<"\")"<<std::endl);
1263
1264  }
1265   //=======================================================================
1266
1267
1268   //=======================================================================
1269   void Interpreter::commandReset()
1270   {
1271     // Cannot close all files if the reset command is read from a file !
1272     CloseAllFiles();
1273     mFileNameHistory.clear();
1274     this->mVirtualExecuter->Reset();
1275   }
1276   //=======================================================================
1277
1278   //=======================================================================
1279   /**
1280    *
1281    */
1282   /*
1283   void Interpreter::Print( const std::string& str)
1284   {
1285     if (mVirtualExecuter->GetNoExecMode()) return;
1286
1287     bbtkDebugMessageInc("interpreter",9,"Interpreter::Print(\""<<str<<"\")"<<std::endl);
1288
1289  // TO DO :
1290  // InterpretLine ("load std")
1291  // InterpretLine("new ConcatStrings _C_ ") -> trouver un nom unique : # commande 
1292  // InterpretLine("new Print _P_") 
1293  // InterpretLine("connect _C_.Out _P_.In")
1294  // int num = 1
1295  
1296
1297     std::vector<std::string> chains;
1298     std::string delimiters("$");
1299
1300     // Skip delimiters at beginning.
1301     std::string::size_type lastPos = str.find_first_not_of(delimiters, 0);
1302     bool is_text = true;
1303     if (lastPos>0) is_text = false;
1304
1305     // Find first delimiter.
1306     std::string::size_type pos     = str.find_first_of(delimiters, lastPos);
1307
1308     while (std::string::npos != pos || std::string::npos != lastPos)
1309     {
1310        if (is_text) 
1311        {
1312           // Found a text token, add it to the vector.
1313           chains.push_back(str.substr(lastPos, pos - lastPos));
1314  // std::string token = str.substr(lastPos, pos - lastPos)
1315  // InterpretLine("set _C_.In%num% %token%")
1316  
1317        }
1318        else 
1319        {
1320
1321        // is an output (between $$) : decode 
1322          std::string tok,box,output;
1323          tok = str.substr(lastPos, pos - lastPos);
1324          Utilities::SplitAroundFirstDot(tok,box,output);
1325          chains.push_back( mVirtualExecuter->Get(box,output) );
1326
1327 // InterpretLine("connect %tok% _C_.In%num%") 
1328
1329        }
1330         // Skip delimiters.  Note the "not_of"
1331        lastPos = str.find_first_not_of(delimiters, pos);
1332         // Find next delimiter
1333        pos = str.find_first_of(delimiters, lastPos);
1334     //
1335        is_text = !is_text;
1336 // num ++;
1337      }
1338 // InterpretLine("exec _P_")
1339 // if (IS_IN_WORKSPACE) InterpretLine("delete _C_; delete _P_");
1340
1341      std::vector<std::string>::iterator i;
1342      for (i= chains.begin(); i!=chains.end(); ++i) 
1343      {
1344
1345        Utilities::SubsBackslashN(*i);
1346        std::cout << *i;
1347      }
1348      std::cout << std::endl;
1349      bbtkDebugDecTab("interpreter",9);
1350  }
1351 */
1352
1353   //=======================================================================
1354   /**
1355    *
1356    */
1357
1358   // =========================================================================
1359   void Interpreter::SwitchToFile( const std::string& name , bool source )
1360   {
1361   // Note : in the following :
1362   // name : the user supplied name 
1363   //      - abreviated name    e.g.       scr   scr.bbs
1364   //      - relative full name e.g.       ./scr.bbs   ../../scr.bbs 
1365   //      - absolute full name e.g.       /home/usrname/proj/dir/scr.bbs
1366   //          same for Windows, with      c:, d: ...
1367   //
1368   // use ./directory/subdir/scrname.bbs
1369   //
1370
1371     bbtkDebugMessage("interpreter",4,"==> Interpreter::SwitchToFile( \""
1372                      <<name<<"\")"<<std::endl);
1373
1374     std::vector<std::string> script_paths;
1375     std::string fullPathScriptName;  // full path script name
1376     std::string pkgname;             // e.g. <scriptname>.bbs
1377     std::vector<std::string> Filenames;
1378
1379     // The following is *NOT* a debug time message :
1380     // It's a user intended message.
1381     // Please don't remove it.
1382     bbtkMessage("interpreter",1,
1383         "look for : [" << name
1384         << "]" << std::endl);
1385
1386
1387     std::string upath;
1388     pkgname = Utilities::ExtractScriptName(name,upath);
1389
1390     bbtkMessage("interpreter",3,
1391                 "package name:[" << pkgname
1392                  << "] path:[" << upath << "]" << std::endl);
1393     bool fullnameGiven = false; 
1394     bool foundFile     = false;
1395
1396     // ==== "*" provided : load all scripts in given path 
1397     // relative (e.g. std/boxes/*) or absolute 
1398     if (pkgname == "*") 
1399       {
1400
1401         std::stringstream* stream = new std::stringstream;
1402         //if (upath.size()!=0) // avoid troubles for "*"
1403         
1404         // ==== no path provided : look in root bbs path
1405         if (upath.size()==0)
1406           {
1407             //      bbtkMessage("interpreter",1,
1408             // LG : add all bbs path
1409             //  script_paths.push_back(  ConfigurationFile::GetInstance().Get_root_bbs_path() );
1410             std::vector<std::string>::const_iterator i;
1411             for (i=ConfigurationFile::GetInstance().Get_bbs_paths().begin();
1412                  i!=ConfigurationFile::GetInstance().Get_bbs_paths().end();
1413                  i++)
1414               {
1415                 script_paths.push_back(*i);
1416               }
1417           }
1418         // ==== absolute path provided 
1419         else if (upath[0]=='/' || upath[1] == ':' ) 
1420           {
1421             if ( Utilities::IsDirectory( upath ) )
1422               {
1423                 script_paths.push_back(upath);
1424               }
1425             else 
1426               {
1427                 bbtkError("'"<<upath<<"' : directory does not exist"); 
1428               }
1429           }
1430         // ==== relative path provided : search all bbs path appended with 
1431         // the relative path provided
1432         else
1433           {    
1434             std::vector<std::string>::const_iterator i;
1435             for (i=ConfigurationFile::GetInstance().Get_bbs_paths().begin();
1436                  i!=ConfigurationFile::GetInstance().Get_bbs_paths().end();
1437                  i++)
1438               {
1439                 std::string full_path(*i);
1440                 // we *really* want '.' to be the current working directory
1441                 if (full_path == ".") 
1442                   {
1443                     char buf[2048]; // for getcwd
1444                     char * currentDir = getcwd(buf, 2048);
1445                     std::string cwd(currentDir);
1446                     full_path = currentDir;
1447                   } // if full_path
1448                 
1449                 full_path += ConfigurationFile::GetInstance().Get_file_separator();
1450                 full_path += upath;
1451                 
1452                 if ( Utilities::IsDirectory( full_path ) )
1453                   {
1454                     script_paths.push_back(full_path);
1455                   }
1456               } 
1457             if (script_paths.empty())
1458               {
1459                 bbtkError("no '"<<upath<<"' subdir found in search paths" 
1460                           << std::endl);
1461               }
1462           }
1463         
1464         
1465         // === search paths list complete : now explore it
1466         int nbBssFiles = 0;     
1467         // ==== relative name, iterate + load all .bbs/.bbp files
1468         std::vector<std::string>::iterator i;
1469         for (i=script_paths.begin();i!=script_paths.end();i++)
1470           {
1471             bbtkMessage("interpreter",1,
1472                         "--> Looking in '" << *i << "'" << std::endl);
1473             
1474             Filenames.clear();
1475             //int nbFiles = 
1476             Utilities::Explore(*i, false, Filenames);
1477             
1478             for (std::vector<std::string>::iterator j = Filenames.begin(); 
1479                  j!= Filenames.end(); ++j)
1480               {
1481                 int lgr = (*j).size();
1482                 if (lgr < 5) continue;  
1483                 // ignore non .bbp file
1484                 if ( (*j).substr(lgr-4, 4) != ".bbp") continue; 
1485                 
1486                 (*stream) << "include \"" << *j << "\"\n";
1487                 bbtkMessage("interpreter",2,"  --> Found '" << *j << "'" << std::endl);
1488                 
1489                 nbBssFiles++;
1490               } // for (std::vector...
1491           } // for (i=script_...
1492
1493         // === Result ...
1494         if (nbBssFiles==0)
1495           {
1496             bbtkMessage("interpreter",1,
1497                         "  --> No .bbp found"<< std::endl);
1498           } 
1499         else 
1500           {
1501             bbtkMessage("interpreter",1,
1502                         "  --> "<<nbBssFiles<<" .bbp found"<< std::endl);
1503             SwitchToStream(stream);
1504           }
1505         return;
1506       }  
1507     //=============== end pkgname=="*" ===========
1508     
1509     
1510     // if name starts with a / or a . or contains : user is assumed to have passed a relative/absolute name
1511     // (not only a plain script name)
1512     // we trust him, and try to expland the directory name
1513     // WARNING : starting from current local directory :  ./whatYouWant  (./ mandatory!)
1514
1515     if (name[0]=='/' || name[1] == ':' || name[0]=='.')  // absolute path (linux/windows) or relative path
1516     { 
1517
1518       // ===========================================================check user supplied location
1519       fullnameGiven = true;
1520
1521       fullPathScriptName =  Utilities::ExpandLibName(name, false);
1522
1523       // allow user to always forget ".bbs"
1524       int l = fullPathScriptName.size();
1525
1526       if (l!=0) 
1527           {
1528          if ((fullPathScriptName.substr(l-4, 4) != ".bbs")&&
1529                          (fullPathScriptName.substr(l-4, 4) != ".bbp"))
1530          {
1531                         std::string tfullPathScriptName = fullPathScriptName + ".bbs";
1532                         if ( Utilities::FileExists(tfullPathScriptName) )
1533                         {
1534                                 fullPathScriptName = tfullPathScriptName;
1535                                 foundFile = true;
1536                         }
1537                         else 
1538                         {
1539                                 tfullPathScriptName = fullPathScriptName + ".bbp";
1540                                 if ( Utilities::FileExists(tfullPathScriptName) )
1541                                 {
1542                                         fullPathScriptName = tfullPathScriptName;
1543                                         foundFile = true;
1544                                 }
1545                         }
1546                  }
1547                  else 
1548                  {
1549                         if ( Utilities::FileExists(fullPathScriptName) )
1550                         {
1551                                 foundFile = true;
1552                         }
1553                  }
1554           } // endif l != 0
1555   }
1556   else
1557   // =============================== iterate on the paths
1558   {
1559       script_paths = ConfigurationFile::GetInstance().Get_bbs_paths();
1560       std::string path;
1561       std::vector<std::string>::iterator i;
1562       for (i=script_paths.begin();i!=script_paths.end();++i)
1563           {
1564                 path = *i;
1565                 // we *really* want '.' to be the current working directory
1566                 if (path == ".") 
1567                 {
1568                         char buf[2048]; // for getcwd
1569                         char * currentDir = getcwd(buf, 2048);
1570                         std::string cwd(currentDir);
1571                         path = currentDir;
1572                 }
1573           
1574                 std::string tfullPathScriptName = Utilities::MakePkgnameFromPath(path, name, false);
1575 //Addition JCP tfullPathScriptName.size()>=4 
1576                 if(tfullPathScriptName.size()>=4){
1577                         if (tfullPathScriptName.substr(tfullPathScriptName.size()-4, 3)==".bb")
1578                         {
1579                           fullPathScriptName = tfullPathScriptName;
1580                                 if ( ! Utilities::FileExists(fullPathScriptName) )
1581                                 {
1582                                         // The following is *NOT* a debug time message :
1583                                         // It's a user intended message.
1584                                         // Please don't remove it.
1585                                         bbtkMessage("interpreter",2,
1586                                   "   [" <<fullPathScriptName <<"] : does not exist" 
1587                                   <<std::endl);
1588                                         continue;  // try next path
1589                                 }
1590                                 bbtkMessage("interpreter",2,
1591                                           "   [" <<fullPathScriptName 
1592                                           <<"] : found" <<std::endl);
1593                                 foundFile = true;
1594                                 break; // a script was found; we stop iterating
1595                         }
1596                         else 
1597                         {
1598                                 fullPathScriptName = tfullPathScriptName + ".bbs";
1599                                 // Check if library exists
1600                                 if ( ! Utilities::FileExists(fullPathScriptName) )
1601                                 {
1602                                         fullPathScriptName = tfullPathScriptName + ".bbp";
1603                                         if ( ! Utilities::FileExists(fullPathScriptName) )
1604                                         {
1605                                                 // The following is *NOT* a debug time message :
1606                                                 // It's a user intended message.
1607                                                 // Please don't remove it.
1608                                                 bbtkMessage("interpreter",2,
1609                                                 "   [" <<tfullPathScriptName <<".bbs/.bbp] : do not exist" 
1610                                                 <<std::endl);
1611                                                 continue;  // try next path
1612                                         }
1613                                 }
1614                                 bbtkMessage("interpreter",2,
1615                                   "   [" <<fullPathScriptName 
1616                                   <<"] : found" <<std::endl);
1617                                 foundFile = true;
1618                                 break; // a script was found; we stop iterating
1619                         }
1620                 }               
1621         } //------------------ // end for ( package_paths.begin();i!=package_paths.end() )
1622   }
1623
1624     if (!foundFile)
1625       {
1626         if (fullnameGiven)
1627           if(fullPathScriptName == "")
1628             bbtkError("Path ["<<upath<<"] doesn't exist");
1629           else
1630             bbtkError("Script ["<<fullPathScriptName<<"] not found");
1631         else
1632           bbtkError("No ["<<pkgname<<".bbs/.bbp] script found");
1633         return;
1634       }
1635     else
1636         {
1637       LoadScript(fullPathScriptName,name);
1638           if (source) GetExecuter()->SetCurrentFileName(fullPathScriptName);
1639         }
1640     
1641     return;
1642   }
1643   //=======================================================================
1644
1645
1646   //=======================================================================
1647 void Interpreter::SwitchToStream( std::stringstream* stream )
1648 {
1649   bbtkDebugMessage("interpreter",4,"==> Interpreter::SwitchToStream()"
1650                    <<std::endl);
1651    mFile.push_back(stream);
1652     std::ostringstream buffer_name;
1653     bufferNb++;
1654     buffer_name << "buffer_" ;
1655
1656     if (mFileName.size()>0 )
1657     {
1658        buffer_name << mFileName.back() << "_" << mLine.back();
1659     }
1660     mFileName.push_back(buffer_name.str());
1661     mIncludeFileName.push_back(buffer_name.str());
1662     mLine.push_back(0);
1663 }
1664   //=======================================================================
1665
1666   //=======================================================================
1667
1668   void Interpreter::LoadScript( std::string fullPathScriptName,
1669                                 std::string includeScriptName)
1670   {
1671     bbtkDebugMessage("interpreter",4,"==> Interpreter::LoadScript("
1672                      <<fullPathScriptName<<")"
1673                      <<std::endl);
1674
1675     Utilities::replace( fullPathScriptName , 
1676                          INVALID_FILE_SEPARATOR , VALID_FILE_SEPARATOR);
1677    
1678      if (find(mFileNameHistory.begin(),
1679               mFileNameHistory.end(),
1680               fullPathScriptName)!=mFileNameHistory.end())
1681      {
1682         return;
1683      }
1684
1685     std::ifstream* s;
1686     s = new std::ifstream;
1687     s->open(fullPathScriptName.c_str());
1688     if (!s->good())
1689     {
1690         bbtkError("Could not open file ["<<fullPathScriptName<<"]");
1691         return;
1692     }
1693
1694     bbtkMessage("interpreter",1,"   -->[" << fullPathScriptName 
1695                 << "] found" << std::endl);
1696
1697     mFile.push_back(s);
1698     mFileName.push_back(fullPathScriptName);
1699     mFileNameHistory.push_back(fullPathScriptName);
1700     mIncludeFileName.push_back(includeScriptName);
1701     mLine.push_back(0);
1702
1703     return;
1704   }
1705   //=======================================================================
1706
1707   //=======================================================================
1708   void Interpreter::CloseCurrentFile()
1709   {
1710     bbtkDebugMessage("interpreter",9,"==> Interpreter::CloseCurrentFile()"
1711                       <<std::endl);
1712
1713     if (mFile.size()==0)
1714     {
1715       bbtkDebugMessage("interpreter",9," -> no file left open"<<std::endl);
1716       return;
1717     }
1718
1719     bbtkDebugMessage("interpreter",9," Closing file '"<<mFileName.back()<<"'"<<std::endl);
1720
1721     std::ifstream* file = dynamic_cast<std::ifstream*>(mFile.back());
1722     if (file!=0) file->close();
1723
1724     delete mFile.back();
1725     mFile.pop_back();
1726     mFileName.pop_back();
1727     mIncludeFileName.pop_back();
1728     mLine.pop_back();
1729
1730     bbtkDebugMessage("interpreter",9," Remains "
1731                      <<mFile.size()
1732                      <<" open"<<std::endl);
1733     bbtkDebugMessage("interpreter",9,"<== Interpreter::CloseCurrentFile()"
1734                      <<std::endl);
1735   }
1736   //=======================================================================
1737
1738  //=======================================================================
1739   void Interpreter::CloseAllFiles()
1740   {
1741     bbtkDebugMessage("interpreter",9,"==> Interpreter::CloseAllFiles()"
1742                       <<std::endl);
1743
1744     while (mFile.size() != 0) 
1745     {
1746        CloseCurrentFile();
1747     }
1748     bbtkDebugMessage("interpreter",9,"<== Interpreter::CloseAllFiles()"
1749                       <<std::endl);
1750   }
1751   //=======================================================================
1752
1753
1754
1755   //=======================================================================
1756   void Interpreter::InterpretCommand( const std::vector<std::string>& words,
1757                                       CommandInfoType& info )
1758   {
1759     bbtkDebugMessage("interpreter",9,"==> Interpreter::InterpretCommand(...)"<<std::endl);
1760
1761     // searches the command keyword
1762     CommandDictType::iterator c;
1763     c = mCommandDict.find(words[0]);
1764     if ( c == mCommandDict.end() ) {
1765       bbtkError(words[0]<<" : unknown command");
1766     }
1767
1768     // tests the number of args 
1769     if ( ( ((int)words.size())-1 < c->second.argmin ) ||
1770          ( ((int)words.size())-1 > c->second.argmax ) )
1771     {
1772        HelpCommand(words[0]);
1773        bbtkError(words[0]<<" : wrong number of arguments");
1774     }
1775 //std::cout<<"Interpreter::InterpretCommand( const std::vector<std::string>& words,"<<std::endl;
1776     info = c->second;
1777
1778     bbtkDebugMessage("interpreter",9,"<== Interpreter::InterpretCommand(...)"<<std::endl);
1779
1780   }
1781   //=======================================================================
1782
1783
1784   //=======================================================================
1785   /// Displays help on all the commands
1786 void Interpreter::commandHelp(const std::vector<std::string>& words)
1787 {
1788     unsigned int nbarg = words.size()-1;
1789
1790     if (nbarg==0) 
1791     {
1792        HelpCommands();
1793     }
1794     else if (nbarg==1) 
1795     {
1796       if (words[1]=="packages") 
1797       {
1798          GetExecuter()->GetFactory()->PrintHelpListPackages(true);
1799          return;
1800       }
1801       try 
1802       {
1803           HelpCommand(words[1]);
1804       }
1805       catch (bbtk::Exception e) 
1806       {
1807          try 
1808          {
1809             GetExecuter()->GetFactory()->PrintHelpPackage(words[1]);
1810             if ( mUser != 0 )
1811               {
1812                 std::string url = 
1813                   ConfigurationFile::GetInstance().Get_doc_path();
1814                 url += "/bbdoc/" + words[1] + "/index.html";
1815                 if (Utilities::FileExists(url)) 
1816                   {
1817                     mUser->InterpreterUserViewHtmlPage(url);
1818                   }
1819               }
1820          }
1821          catch (bbtk::Exception f) 
1822          {
1823            try 
1824              {
1825                std::string package;
1826                GetExecuter()->GetFactory()->PrintHelpDescriptor(words[1],
1827                                                                 package);
1828                if ( mUser != 0 )
1829                  {
1830                    std::string url = 
1831                      ConfigurationFile::GetInstance().Get_doc_path();
1832                    url += "/bbdoc/" + package + "/index.html";
1833                    if (Utilities::FileExists(url)) 
1834                      {
1835                        url += "#" + words[1];
1836                        mUser->InterpreterUserViewHtmlPage(url);
1837                      }
1838                  }
1839              }
1840            catch (bbtk::Exception g) 
1841              {
1842                try
1843                  {
1844                    GetExecuter()->PrintHelpBlackBox(words[1],"0","9999");
1845                  }
1846                catch (bbtk::Exception h){
1847                  bbtkError("\""<<words[1].c_str()
1848                            <<"\" is not a known command, package, black box type or black box name");
1849                }
1850              }
1851          }
1852       }
1853     }
1854     else if (nbarg==2) 
1855     {
1856       if (words[2]=="all")
1857       {
1858          if ( words[1]=="packages" )
1859          {
1860             GetExecuter()->GetFactory()->PrintHelpListPackages(true,true);
1861             return;
1862           }
1863          try 
1864          {
1865             GetExecuter()->GetFactory()->PrintHelpPackage(words[1],true);
1866          }
1867          catch (bbtk::Exception f) 
1868          {
1869          }
1870      }
1871      else 
1872      {
1873         HelpCommand(words[0]);
1874         bbtkError(words[0]<<" : syntax error");
1875      }
1876   }
1877   else 
1878   {
1879      bbtkError("Should not reach here !!!");
1880   }
1881 }
1882   //=======================================================================
1883
1884    //===================================================================    
1885   /// Displays the Configuration
1886   void Interpreter::commandConfig() const
1887   {
1888     ConfigurationFile::GetInstance().GetHelp(1);
1889   }  
1890    //===================================================================    
1891
1892   //=======================================================================
1893   /// Displays help on all the commands
1894   void Interpreter::HelpCommands()
1895   {
1896     std::cout << "Available commands :" << std::endl;
1897     CommandDictType::iterator i;
1898     for ( i =  mCommandDict.begin();
1899           i != mCommandDict.end();
1900         ++i) {
1901               std::cout << " " << i->first << std::endl;
1902       //      std::cout << "   usage : " << i->second.syntax << std::endl;
1903       //     std::cout << "    " << i->second.help << std::endl;
1904
1905     }
1906   }
1907   //=======================================================================
1908
1909
1910   //=======================================================================
1911   /// Displays help on a particular commands
1912   void Interpreter::HelpCommand(const std::string& s)
1913   {
1914     CommandDictType::iterator c;
1915     c = mCommandDict.find(s);
1916     if ( c == mCommandDict.end() ) {
1917       bbtkError(s<<" : Unknown command");
1918     }   
1919     //    std::cout << " " << s << " : "<<  std::endl;
1920     //    CommandParamDictType::iterator i;
1921     //    for ( i =  c->second.begin();
1922     //      i != c->second.end();
1923     //      ++i) {
1924     std::cout << " usage : " << c->second.syntax << std::endl;
1925     std::cout << "  " << c->second.help << std::endl;
1926
1927   }
1928   //=======================================================================
1929
1930
1931   //=======================================================================
1932   /// Fills the vector commands with the commands which 
1933   /// have the first n chars of buf for prefix
1934   /// TODO : skip initial spaces in buf and also return the position of first
1935   /// non blank char in buf
1936   void Interpreter::FindCommandsWithPrefix( char* buf,
1937                                             int n,
1938                                             std::vector<std::string>& commands )
1939   {
1940     CommandDictType::const_iterator i;
1941     for (i=mCommandDict.begin(); i!=mCommandDict.end(); ++i)
1942     {
1943       if ((i->first).find(buf,0,n) == 0) 
1944         commands.push_back(i->first);
1945     }
1946   }
1947   //=======================================================================
1948
1949
1950
1951   //=======================================================================
1952 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
1953   
1954   inline void PrintChar(char c) { write(STDOUT_FILENO,&c,1); }
1955   inline void BackSpace() { write(STDOUT_FILENO,"\b \b",3); }
1956   
1957   // LG : KEYBOARD CODES AS SCANNED ON MY TTY : UNIVERSAL ?
1958   // IF NOT THE USER SHOULD BE ABLE TO CONFIGURE IT
1959   // E.G. STORE THIS IN bbtk_config.xml
1960 #define BBTK_UP_ARROW_KBCODE    0x00415B1B
1961 #define BBTK_DOWN_ARROW_KBCODE  0x00425B1B
1962 #define BBTK_RIGHT_ARROW_KBCODE 0x00435B1B
1963 #define BBTK_LEFT_ARROW_KBCODE  0x00445B1B
1964 #define BBTK_BACKSPACE_KBCODE   0x00000008
1965 #define BBTK_DEL_KBCODE         0x0000007F
1966 #define BBTK_SPACE_KBCODE       0x00000020 
1967
1968   //=======================================================================
1969   void Interpreter::GetLineFromPrompt(std::string& s)
1970   {
1971     int c;
1972     unsigned int ind=0;
1973
1974     unsigned int MAX_LINE_SIZE = 160;
1975     unsigned int MAX_HISTORY_SIZE = 100;
1976
1977     char* newline = new char[MAX_LINE_SIZE];
1978     memset(newline,0,MAX_LINE_SIZE);
1979     char* histline = new char[MAX_LINE_SIZE];
1980     memset(histline,0,MAX_LINE_SIZE);
1981
1982     char* line = newline;
1983     unsigned int hist = mHistory.size();
1984
1985     write(1,"> ",2);
1986     while(1)
1987     {
1988        c=0;
1989        read ( STDIN_FILENO, &c, 4) ;
1990
1991        bbtkDebugMessage("debug",9,"[0x"<<std::hex<<c<<"]\n");
1992
1993        // Printable character
1994        if ( (ind<MAX_LINE_SIZE-1) &&
1995             ( c >= BBTK_SPACE_KBCODE ) && 
1996             ( c <  BBTK_DEL_KBCODE )) 
1997        {
1998           PrintChar(c);
1999           line[ind++]=c;
2000        }
2001       // CR
2002        else if (c=='\n')
2003        {
2004        // delete the unused line
2005           if (line==newline)
2006               delete histline;
2007           else
2008               delete newline;
2009    
2010     // empty lines are not stored in from history
2011           if (strlen(line)) 
2012           {
2013              // if history too long : delete oldest command
2014              if (mHistory.size()>MAX_HISTORY_SIZE) 
2015              {
2016                 delete mHistory.front();
2017                 mHistory.pop_front();
2018              }
2019              mHistory.push_back(line);
2020           }
2021           break;
2022         }
2023        // Backspace
2024         else if ( (ind>0) && 
2025                   ((c == BBTK_BACKSPACE_KBCODE) ||
2026                    (c == BBTK_DEL_KBCODE)) )
2027           {
2028             line[ind--]=' ';
2029             BackSpace();
2030           }
2031         // Tab 
2032         else if (c=='\t')
2033           {
2034             // TODO : Command completion  
2035             std::vector<std::string> commands;
2036             FindCommandsWithPrefix( line,ind,commands);
2037             if (commands.size()==1) 
2038               {
2039                 std::string com = *commands.begin();
2040                 for (; ind<com.size(); ++ind) 
2041                   {
2042                     PrintChar(com[ind]); 
2043                     line[ind]=com[ind];
2044                   }
2045                 PrintChar(' '); 
2046                 line[ind++]=' ';
2047               }
2048             else if (commands.size()>1) 
2049               {
2050                 std::vector<std::string>::iterator i;
2051                 write(1,"\n",1);
2052                 for (i=commands.begin();i!=commands.end();++i) 
2053                   {
2054                     write(STDOUT_FILENO,(*i).c_str(),strlen((*i).c_str()));
2055                     PrintChar(' ');
2056                   }
2057                 write(STDOUT_FILENO,"\n> ",3);
2058                 //for (int j=0;j<ind;++j) 
2059                   //{
2060                     write(STDOUT_FILENO,line,ind); 
2061                     //  }
2062               }
2063           }
2064         // Arrow up : back in history
2065         else if (c==BBTK_UP_ARROW_KBCODE)
2066           {
2067             if (hist) 
2068               {
2069                 // erase current line
2070                 while (ind--) BackSpace();
2071                 // 
2072                 hist--;
2073                 // 
2074                 strcpy(histline,mHistory[hist]);
2075                 line = histline;
2076                 ind = strlen(line);
2077                 
2078                 write(STDOUT_FILENO,line,ind);
2079               }
2080           }
2081         // Arrow down : down in history
2082         else if (c==BBTK_DOWN_ARROW_KBCODE)
2083           {
2084             if (hist<mHistory.size()-1) 
2085               {
2086                 // erase current line
2087                 while (ind--) BackSpace();
2088                 // 
2089                 hist++;
2090                 // 
2091                 strcpy(histline,mHistory[hist]);
2092                 line = histline;
2093                 ind = strlen(line);
2094                 
2095                 write(STDOUT_FILENO,line,ind);
2096               }
2097             // end of history : switch back to newline
2098             else if (hist==mHistory.size()-1)
2099               {
2100                 // erase current line
2101                 while (ind--) BackSpace();
2102                 // 
2103                 hist++;
2104                 // 
2105                 line = newline;
2106                 ind = strlen(line);
2107                 
2108                 write(STDOUT_FILENO,line,ind);
2109               }
2110           }
2111         // Arrow right
2112         else if (line[ind]!=0 && c==BBTK_RIGHT_ARROW_KBCODE)
2113           {
2114             PrintChar(line[ind]);
2115             ind++;
2116           }
2117
2118         // Arrow left
2119         else if (ind>0 && c==BBTK_LEFT_ARROW_KBCODE)
2120           {
2121             PrintChar('\b');
2122             ind--;
2123     
2124           }
2125
2126       }
2127     write(STDOUT_FILENO,"\n\r",2);
2128     
2129     
2130     s = line;
2131     
2132   }
2133 #else
2134
2135   //=======================================================================
2136   void Interpreter::GetLineFromPrompt(std::string& s)
2137   {  
2138     s.clear();
2139
2140     putchar('>');
2141     putchar(' ');
2142
2143     do 
2144     {
2145       char c = getchar();
2146       if (c=='\n') 
2147       {
2148         putchar('\n');
2149         break;
2150       }
2151       if (c=='\t') 
2152       {
2153         // putchar('T');
2154         continue;
2155       }
2156       // putchar(c);
2157       s += c;
2158     } 
2159     while (true);  
2160     
2161   }
2162   //=======================================================================  
2163
2164 #endif
2165
2166
2167
2168   //=======================================================================
2169   void Interpreter::CommandLineInterpreter()
2170   {
2171     bbtkDebugMessageInc("interpreter",9,
2172                         "Interpreter::CommandLineInterpreter()"<<std::endl);
2173
2174 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT  
2175     // Initialise the tty in non canonical mode with no echo
2176     // oter remembers the previous settings to restore them after 
2177     struct termios ter,oter;
2178     tcgetattr(0,&ter);
2179     oter=ter;
2180     ter.c_lflag &= ~ECHO;
2181     ter.c_lflag &= ~ICANON;
2182     ter.c_cc[VMIN]=1;
2183     ter.c_cc[VTIME]=0;
2184     tcsetattr(0,TCSANOW,&ter);
2185 #endif
2186     
2187     mCommandLine = true;
2188     bool again = true;
2189     // bool insideComment = false; // for multiline comment  
2190     mInsideComment = false;
2191     do 
2192     {
2193       try
2194       {
2195         std::string line;
2196         GetLineFromPrompt(line);
2197         DoInterpretLine(line); //, insideComment);
2198       }
2199       /*
2200       catch (QuitException e)
2201       {
2202         bbtkMessage("interpreter",1,"Interpreter : Quit"<<std::endl);
2203         again = false;
2204       }
2205       */
2206       catch (bbtk::Exception e) 
2207       {
2208         e.Print();
2209       }
2210         catch (std::exception& e) 
2211       {
2212         std::cerr << "* ERROR :: "<<e.what()<<" (not in bbtk)"<<std::endl;
2213       }
2214       catch (...)
2215       {
2216         std::cerr << "* UNDEFINED ERROR (not a bbtk nor a std exception)"<<std::endl;
2217       }
2218     }
2219     while (again);
2220
2221 #ifdef BBTK_USE_TERMIOS_BASED_PROMPT
2222     tcsetattr(0,TCSANOW,&oter);
2223 #endif
2224
2225     std::cout << "Good bye !" << std::endl;
2226
2227     bbtkDebugDecTab("interpreter",9);
2228   }
2229
2230 //=======================================================================
2231 void Interpreter::commandGraph(const std::vector<std::string>& words)
2232 {
2233   std::string page;
2234     bool system_display = true;
2235
2236     if ( ( mUser != 0 ) && ( mUser->InterpreterUserHasOwnHtmlPageViewer() ) )
2237       system_display = false; 
2238  
2239     if (words.size()==1) 
2240     {
2241       page = mVirtualExecuter->ShowGraph(".","0","0","","","",system_display);
2242     }
2243     else if (words.size()==2) 
2244     {
2245       page = mVirtualExecuter->ShowGraph(words[1],"0","0","","","",system_display);
2246     }
2247     else if (words.size()==3) 
2248     {
2249       page = mVirtualExecuter->ShowGraph(words[1],words[2],"0","","","",system_display);
2250     }
2251     else if (words.size()==4) 
2252     {
2253       page = mVirtualExecuter->ShowGraph(words[1],words[2],words[3],"","","",system_display);
2254     } 
2255     else if (words.size()==5) 
2256     {
2257       page = mVirtualExecuter->ShowGraph(words[1],words[2],words[3],words[4],"","",system_display);
2258     } 
2259     else if (words.size()==6) 
2260     {
2261       page = mVirtualExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],"",system_display);
2262     } 
2263     else if (words.size()==7) 
2264       {
2265         page = mVirtualExecuter->ShowGraph(words[1],words[2],words[3],words[4],words[5],words[6],system_display);
2266       } 
2267     
2268     if ( ( mUser != 0 ) && ( mUser->InterpreterUserHasOwnHtmlPageViewer() ) )
2269       mUser->InterpreterUserViewHtmlPage(page);
2270
2271   }
2272 //=======================================================================
2273
2274
2275 //=======================================================================
2276 void  Interpreter::commandIndex(const std::string& filename, 
2277                          const std::string& type)
2278 {
2279   Factory::IndexEntryType t;
2280   if (type=="Initials") t = Factory::Initials;
2281   else if (type=="Categories") t = Factory::Categories;
2282   else if (type=="Packages") t = Factory::Packages;
2283   else if (type=="Adaptors") t = Factory::Adaptors;
2284   
2285   GetExecuter()->GetFactory()->CreateHtmlIndex(t,filename);
2286 }
2287 //=======================================================================
2288
2289
2290 //=======================================================================
2291 void  Interpreter::commandNewGUI(const std::string& boxname,
2292                              const std::string& instanceName)
2293 {
2294   if (mRealExecuter.expired())
2295     {
2296       bbtkError("command 'newgui' cannot be compiled yet");
2297     }
2298
2299   std::string typeName = instanceName+"Type";
2300   std::stringstream* s = new std::stringstream;
2301   // create the complex box
2302   (*s) << "define "<<typeName<<std::endl;
2303   //  (*s) << "  description 'Automatically generated user interface for the box "
2304   //       << boxname << "'" <<std::endl;
2305   // create the Layout box
2306   (*s) << "  load wx"<<std::endl;
2307   (*s) << "  new LayoutLine layout"<<std::endl;
2308   // create the output 'Widget'
2309   (*s) << "  output Widget layout.Widget Widget"<<std::endl;
2310   // the box change output 
2311   (*s) << "  new MultipleInputs change"<<std::endl;
2312   (*s) << "  output BoxChange change.Out BoxChange"<<std::endl;
2313
2314   // Browse the inputs of the box in order to find which ones are not 
2315   // connected and can be adapted from a widget adaptor
2316   // vector which stores the list of inputs of the box which must be connected
2317   std::vector<std::string> in;
2318  
2319   Factory::Pointer F = mVirtualExecuter->GetFactory();
2320   /*
2321   Package::Pointer user = F->GetPackage("user");
2322   */
2323   ComplexBlackBoxDescriptor::Pointer workspace = 
2324     mRealExecuter.lock()->GetCurrentDescriptor();
2325
2326   if (workspace==0)
2327     {
2328       delete s;
2329       bbtkError("interpreter::CreateGUI : could not access the executer currently defined complex box");
2330     }
2331  
2332
2333   /*
2334     (ComplexBlackBoxDescriptor::Pointer)(user->GetBlackBoxMap().find("workspace")->second.get());
2335   */
2336
2337   BlackBox::Pointer box = workspace->GetPrototype()->bbGetBlackBox(boxname);
2338   //  BlackBox::InputConnectorMapType incm = box->bbGetInputConnectorMap();
2339   // int nb = 0;
2340   BlackBox::InputConnectorMapType::iterator i;
2341   for (i=box->bbGetInputConnectorMap().begin();
2342        i!=box->bbGetInputConnectorMap().end();
2343        ++i)
2344     {
2345       // If the input is connected : continue
2346       if (i->second->IsConnected()) continue;
2347       // Get the input descriptor 
2348       const BlackBoxInputDescriptor* d = box->bbGetDescriptor()->GetInputDescriptor(i->first);
2349       // If it is a "system" input : skip it
2350 #ifdef USE_WXWIDGETS
2351       if ( ( d->GetCreatorTypeInfo() == typeid(AtomicBlackBoxDescriptor)) ||
2352            ( d->GetCreatorTypeInfo() == typeid(WxBlackBoxDescriptor)) )
2353         continue;
2354 #else
2355       if ( ( d->GetCreatorTypeInfo() == typeid(AtomicBlackBoxDescriptor)) )
2356         continue;
2357 #endif
2358       bool widok = true;
2359       std::string widget,adaptor;
2360       // try to find a widget adaptor
2361       if (F->FindWidgetAdaptor(DataInfo(d->GetTypeInfo(),""),
2362                                d->GetDataInfo(),
2363                                adaptor))
2364         {
2365           // command to create the adaptor
2366           (*s) << "  new "<<adaptor<<" "<<i->first<<std::endl;
2367           // Sets the label of the widget adaptor to the name of the input
2368           (*s) << "  set "<<i->first<<".Label "<<i->first<<std::endl;
2369           // Sets the initial value of the widget to the value of the input
2370           (*s) << "  set "<<i->first<<".In \" "
2371                <<box->bbGetInputAsString(i->first)<<"\""
2372                << std::endl;
2373           // store the input name
2374           in.push_back(i->first);
2375           (*s) << "  connect "<<i->first<<".Widget layout.Widget"<<in.size()<<std::endl;
2376             //<i->first<<"'"<<std::endl;
2377           (*s) << "  connect "<<i->first<<".BoxChange change.In"<<in.size()<<std::endl;
2378         }
2379       // try to find a two pieces adaptor
2380       else if (F->FindWidgetAdaptor2(DataInfo(d->GetTypeInfo(),""),
2381                                      d->GetDataInfo(),
2382                                      widget,adaptor) )
2383         {
2384           // command to create the widget
2385           (*s) << "  new "<<widget<<" "<<i->first<<"Widget"<<std::endl;
2386           // command to create the adaptor
2387           (*s) << "  new "<<adaptor<<" "<<i->first<<std::endl;
2388           // connect the two
2389           (*s) << "  connect "<<i->first<<"Widget.Out "
2390                <<i->first<<".In"<<std::endl;
2391           // Sets the label of the widget adaptor to the name of the input
2392           (*s) << "  set "<<i->first<<"Widget.Label "<<i->first<<std::endl;
2393           // Sets the initial value of the widget to the value of the input
2394           (*s) << "  set "<<i->first<<"Widget.In \" "
2395                <<box->bbGetInputAsString(i->first)<<"\""<< std::endl;
2396           // store the input name
2397           in.push_back(i->first);
2398           (*s) << "  connect "<<i->first<<"Widget.Widget layout.Widget"<<in.size()<<std::endl;
2399             //<i->first<<"'"<<std::endl;
2400           (*s) << "  connect "<<i->first<<"Widget.BoxChange change.In"<<in.size()<<std::endl;
2401
2402         }
2403       // try to find an adaptor from string 
2404       // If found then can create a text input which 
2405       // will be automatically adapted 
2406       else if (F->FindAdaptor(DataInfo(typeid(std::string),""),
2407                                d->GetDataInfo(),
2408                                adaptor))
2409         {
2410           // command to create the adaptor
2411           (*s) << "  new InputText "<<i->first<<std::endl;
2412           // Sets the label of the widget adaptor to the name of the input
2413           (*s) << "  set "<<i->first<<".Title "<<i->first<<std::endl;
2414           // Sets the initial value of the widget to the value of the input
2415           (*s) << "  set "<<i->first<<".In \" "
2416                <<box->bbGetInputAsString(i->first)<<"\""<< std::endl;
2417           // store the input name
2418           in.push_back(i->first);
2419           (*s) << "  connect "<<i->first<<".Widget layout.Widget"<<in.size()<<std::endl;
2420             //<i->first<<"'"<<std::endl;
2421           (*s) << "  connect "<<i->first<<".BoxChange change.In"<<in.size()<<std::endl;
2422
2423         }
2424       else 
2425         {
2426           widok = false;
2427         }
2428       if (widok)
2429         {
2430           // command to create the output
2431           (*s) << "  output "<<i->first<<" "
2432                <<i->first<<".Out "<<i->first<<std::endl;
2433             //         <<" Output of the widget which allows to set "
2434           
2435         }
2436     }   
2437   // Inputs for window properties
2438   (*s) << "  input WinTitle layout.WinTitle Title"<<std::endl;
2439   (*s) << "  input WinWidth layout.WinWidth Width"<<std::endl;
2440   (*s) << "  input WinHeight layout.WinHeight Height"<<std::endl;
2441   (*s) << "  input WinDialog layout.WinDialog Dialog"<<std::endl;
2442   (*s) << "  input WinHide layout.WinHide Hide"<<std::endl;
2443
2444   
2445   
2446   // Execute the box executes the layout
2447   (*s) << "  exec layout" << std::endl;
2448   (*s) << "endefine" << std::endl;
2449   // (*s) << "help "<< typeName<< std::endl;
2450   // instanciate the box and connect it
2451   (*s) << "new "<<typeName<<" "<<instanceName<<std::endl;
2452   // connections
2453   std::vector<std::string>::iterator j;
2454   for (j=in.begin();j!=in.end();++j)
2455     {
2456       // connect
2457       (*s) << "connect "<<instanceName<<"."<<*j<<" "
2458            << boxname<<"."<<*j<<std::endl;
2459     }
2460   // That's all folks ! now execute the commands :
2461   SwitchToStream(s);
2462 }
2463 //=======================================================================
2464
2465
2466
2467  //==========================================================================
2468   void Interpreter::commandDebug(const std::string& name)
2469   {
2470     if ((name.length()==2)&&(name[0]=='-'))
2471       {
2472         if (name[1]=='D')
2473           {
2474             bbtk::StaticInitTime::PrintObjectListInfo = true;
2475           }
2476         if (name[1]=='C')
2477           {
2478             //      int o = MessageManager::GetMessageLevel("debug");
2479             //      if (o<2) MessageManager::SetMessageLevel("debug",2);
2480             mVirtualExecuter->GetFactory()->Check();
2481             //      MessageManager::SetMessageLevel("debug",o);
2482           }
2483       }
2484     else 
2485       {
2486         Object:: PrintObjectListInfo(name);
2487       }
2488   }
2489  //==========================================================================
2490
2491   /*
2492   //==========================================================================
2493   // Adds a callback when 'break' command issued
2494   void Interpreter::AddBreakObserver( BreakCallbackType c )
2495   {
2496     mBreakSignal.connect(c);
2497   }
2498  //==========================================================================
2499  */
2500
2501  //==========================================================================
2502   std::string Interpreter::GetObjectName() const
2503   {
2504     return std::string("Interpreter");
2505   }
2506   //==========================================================================
2507   
2508   //==========================================================================
2509   std::string  Interpreter::GetObjectInfo() const 
2510   {
2511     std::stringstream i;
2512     return i.str();
2513   }
2514   //==========================================================================
2515
2516   //==========================================================================
2517 size_t  Interpreter::GetObjectSize() const 
2518 {
2519   size_t s = Superclass::GetObjectSize();
2520   s += Interpreter::GetObjectInternalSize();
2521   return s;
2522   }
2523   //==========================================================================
2524   //==========================================================================
2525 size_t  Interpreter::GetObjectInternalSize() const 
2526 {
2527   size_t s = sizeof(Interpreter);
2528   return s;
2529   }
2530   //==========================================================================
2531   //==========================================================================
2532   size_t  Interpreter::GetObjectRecursiveSize() const 
2533   {
2534     size_t s = Superclass::GetObjectRecursiveSize();
2535     s += Interpreter::GetObjectInternalSize();
2536     s += mVirtualExecuter->GetObjectRecursiveSize();
2537     return s;
2538   }
2539   //==========================================================================
2540 }//namespace
2541
2542